am 3fa53e44: am 36e6c4c1: am cc9ee72b: Implement dead service recovery in NFC extras library.

* commit '3fa53e448a4b2255f6ed14f8b8355ac2ee3379e9':
  Implement dead service recovery in NFC extras library.
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index 9bd8f36..6001be9 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -56,13 +56,21 @@
     public static final String ACTION_RF_FIELD_OFF_DETECTED =
             "com.android.nfc_extras.action.RF_FIELD_OFF_DETECTED";
 
-    // protected by NfcAdapterExtras.class, and final after first construction
+    // protected by NfcAdapterExtras.class, and final after first construction,
+    // except for attemptDeadServiceRecovery() when NFC crashes - we accept a
+    // best effort recovery
+    private static NfcAdapter sAdapter;
     private static INfcAdapterExtras sService;
     private static NfcAdapterExtras sSingleton;
     private static NfcExecutionEnvironment sEmbeddedEe;
     private static CardEmulationRoute sRouteOff;
     private static CardEmulationRoute sRouteOnWhenScreenOn;
 
+    /** get service handles */
+    private static void initService() {
+        sService = sAdapter.getNfcAdapterExtrasInterface();
+    }
+
     /**
      * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
      *
@@ -76,12 +84,13 @@
         synchronized(NfcAdapterExtras.class) {
             if (sSingleton == null) {
                 try {
-                    sService = adapter.getNfcAdapterExtrasInterface();
-                    sEmbeddedEe = new NfcExecutionEnvironment(sService);
+                    sAdapter = adapter;
                     sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
+                    sSingleton = new NfcAdapterExtras();
+                    sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
                     sRouteOnWhenScreenOn = new CardEmulationRoute(
                             CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
-                    sSingleton = new NfcAdapterExtras();
+                    initService();
                 } finally {
                     if (sSingleton == null) {
                         sService = null;
@@ -136,6 +145,19 @@
     }
 
     /**
+     * NFC service dead - attempt best effort recovery
+     */
+    void attemptDeadServiceRecovery(Exception e) {
+        Log.e(TAG, "NFC Adapter Extras dead - attempting to recover");
+        sAdapter.attemptDeadServiceRecovery(e);
+        initService();
+    }
+
+    INfcAdapterExtras getService() {
+        return sService;
+    }
+
+    /**
      * Get the routing state of this NFC EE.
      *
      * <p class="note">
@@ -150,7 +172,7 @@
                     sRouteOff :
                     sRouteOnWhenScreenOn;
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
             return sRouteOff;
         }
     }
@@ -169,7 +191,7 @@
         try {
             sService.setCardEmulationRoute(route.route);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -190,7 +212,7 @@
         try {
             sService.registerTearDownApdus(packageName, apdus);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 
@@ -198,7 +220,7 @@
         try {
             sService.unregisterTearDownApdus(packageName);
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            attemptDeadServiceRecovery(e);
         }
     }
 }
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
index 3efe492..eb2f6f8 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcExecutionEnvironment.java
@@ -29,7 +29,7 @@
 import android.os.RemoteException;
 
 public class NfcExecutionEnvironment {
-    private final INfcAdapterExtras mService;
+    private final NfcAdapterExtras mExtras;
 
     /**
      * Broadcast Action: An ISO-DEP AID was selected.
@@ -55,8 +55,8 @@
      */
     public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
 
-    NfcExecutionEnvironment(INfcAdapterExtras service) {
-        mService = service;
+    NfcExecutionEnvironment(NfcAdapterExtras extras) {
+        mExtras = extras;
     }
 
     /**
@@ -75,10 +75,11 @@
      */
     public void open() throws IOException {
         try {
-            Bundle b = mService.open(new Binder());
+            Bundle b = mExtras.getService().open(new Binder());
             throwBundle(b);
         } catch (RemoteException e) {
-            return;
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead, try again");
         }
     }
 
@@ -92,9 +93,10 @@
      */
     public void close() throws IOException {
         try {
-            throwBundle(mService.close());
+            throwBundle(mExtras.getService().close());
         } catch (RemoteException e) {
-            return;
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead");
         }
     }
 
@@ -109,9 +111,10 @@
     public byte[] transceive(byte[] in) throws IOException {
         Bundle b;
         try {
-            b = mService.transceive(in);
+            b = mExtras.getService().transceive(in);
         } catch (RemoteException e) {
-            throw new IOException(e.getMessage());
+            mExtras.attemptDeadServiceRecovery(e);
+            throw new IOException("NFC Service was dead, need to re-open");
         }
         throwBundle(b);
         return b.getByteArray("out");