Implement dead service recovery in NFC extras library.

Change-Id: I4f1d714c625470df4cda2c4c9aacb8d27bfabb10
This commit is contained in:
Nick Pelly
2011-04-26 16:38:00 -07:00
parent d2127c438f
commit cc9ee72bd4
2 changed files with 42 additions and 17 deletions

View File

@@ -56,13 +56,21 @@ public final class NfcAdapterExtras {
public static final String ACTION_RF_FIELD_OFF_DETECTED = public static final String ACTION_RF_FIELD_OFF_DETECTED =
"com.android.nfc_extras.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 INfcAdapterExtras sService;
private static NfcAdapterExtras sSingleton; private static NfcAdapterExtras sSingleton;
private static NfcExecutionEnvironment sEmbeddedEe; private static NfcExecutionEnvironment sEmbeddedEe;
private static CardEmulationRoute sRouteOff; private static CardEmulationRoute sRouteOff;
private static CardEmulationRoute sRouteOnWhenScreenOn; private static CardEmulationRoute sRouteOnWhenScreenOn;
/** get service handles */
private static void initService() {
sService = sAdapter.getNfcAdapterExtrasInterface();
}
/** /**
* Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}. * Get the {@link NfcAdapterExtras} for the given {@link NfcAdapter}.
* *
@@ -76,12 +84,13 @@ public final class NfcAdapterExtras {
synchronized(NfcAdapterExtras.class) { synchronized(NfcAdapterExtras.class) {
if (sSingleton == null) { if (sSingleton == null) {
try { try {
sService = adapter.getNfcAdapterExtrasInterface(); sAdapter = adapter;
sEmbeddedEe = new NfcExecutionEnvironment(sService);
sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null); sRouteOff = new CardEmulationRoute(CardEmulationRoute.ROUTE_OFF, null);
sSingleton = new NfcAdapterExtras();
sEmbeddedEe = new NfcExecutionEnvironment(sSingleton);
sRouteOnWhenScreenOn = new CardEmulationRoute( sRouteOnWhenScreenOn = new CardEmulationRoute(
CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe); CardEmulationRoute.ROUTE_ON_WHEN_SCREEN_ON, sEmbeddedEe);
sSingleton = new NfcAdapterExtras(); initService();
} finally { } finally {
if (sSingleton == null) { if (sSingleton == null) {
sService = null; sService = null;
@@ -135,6 +144,19 @@ public final class NfcAdapterExtras {
} }
} }
/**
* 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. * Get the routing state of this NFC EE.
* *
@@ -150,7 +172,7 @@ public final class NfcAdapterExtras {
sRouteOff : sRouteOff :
sRouteOnWhenScreenOn; sRouteOnWhenScreenOn;
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); attemptDeadServiceRecovery(e);
return sRouteOff; return sRouteOff;
} }
} }
@@ -169,7 +191,7 @@ public final class NfcAdapterExtras {
try { try {
sService.setCardEmulationRoute(route.route); sService.setCardEmulationRoute(route.route);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); attemptDeadServiceRecovery(e);
} }
} }
@@ -190,7 +212,7 @@ public final class NfcAdapterExtras {
try { try {
sService.registerTearDownApdus(packageName, apdus); sService.registerTearDownApdus(packageName, apdus);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); attemptDeadServiceRecovery(e);
} }
} }
@@ -198,7 +220,7 @@ public final class NfcAdapterExtras {
try { try {
sService.unregisterTearDownApdus(packageName); sService.unregisterTearDownApdus(packageName);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "", e); attemptDeadServiceRecovery(e);
} }
} }
} }

View File

@@ -29,7 +29,7 @@ import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
public class NfcExecutionEnvironment { public class NfcExecutionEnvironment {
private final INfcAdapterExtras mService; private final NfcAdapterExtras mExtras;
/** /**
* Broadcast Action: An ISO-DEP AID was selected. * Broadcast Action: An ISO-DEP AID was selected.
@@ -55,8 +55,8 @@ public class NfcExecutionEnvironment {
*/ */
public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID"; public static final String EXTRA_AID = "com.android.nfc_extras.extra.AID";
NfcExecutionEnvironment(INfcAdapterExtras service) { NfcExecutionEnvironment(NfcAdapterExtras extras) {
mService = service; mExtras = extras;
} }
/** /**
@@ -75,10 +75,11 @@ public class NfcExecutionEnvironment {
*/ */
public void open() throws IOException { public void open() throws IOException {
try { try {
Bundle b = mService.open(new Binder()); Bundle b = mExtras.getService().open(new Binder());
throwBundle(b); throwBundle(b);
} catch (RemoteException e) { } catch (RemoteException e) {
return; mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead, try again");
} }
} }
@@ -92,9 +93,10 @@ public class NfcExecutionEnvironment {
*/ */
public void close() throws IOException { public void close() throws IOException {
try { try {
throwBundle(mService.close()); throwBundle(mExtras.getService().close());
} catch (RemoteException e) { } catch (RemoteException e) {
return; mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead");
} }
} }
@@ -109,9 +111,10 @@ public class NfcExecutionEnvironment {
public byte[] transceive(byte[] in) throws IOException { public byte[] transceive(byte[] in) throws IOException {
Bundle b; Bundle b;
try { try {
b = mService.transceive(in); b = mExtras.getService().transceive(in);
} catch (RemoteException e) { } catch (RemoteException e) {
throw new IOException(e.getMessage()); mExtras.attemptDeadServiceRecovery(e);
throw new IOException("NFC Service was dead, need to re-open");
} }
throwBundle(b); throwBundle(b);
return b.getByteArray("out"); return b.getByteArray("out");