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 =
"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 @@ public final class NfcAdapterExtras {
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;
@@ -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.
*
@@ -150,7 +172,7 @@ public final class NfcAdapterExtras {
sRouteOff :
sRouteOnWhenScreenOn;
} catch (RemoteException e) {
Log.e(TAG, "", e);
attemptDeadServiceRecovery(e);
return sRouteOff;
}
}
@@ -169,7 +191,7 @@ public final class NfcAdapterExtras {
try {
sService.setCardEmulationRoute(route.route);
} catch (RemoteException e) {
Log.e(TAG, "", e);
attemptDeadServiceRecovery(e);
}
}
@@ -190,7 +212,7 @@ public final class NfcAdapterExtras {
try {
sService.registerTearDownApdus(packageName, apdus);
} catch (RemoteException e) {
Log.e(TAG, "", e);
attemptDeadServiceRecovery(e);
}
}
@@ -198,7 +220,7 @@ public final class NfcAdapterExtras {
try {
sService.unregisterTearDownApdus(packageName);
} catch (RemoteException e) {
Log.e(TAG, "", e);
attemptDeadServiceRecovery(e);
}
}
}

View File

@@ -29,7 +29,7 @@ import android.os.IBinder;
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 class NfcExecutionEnvironment {
*/
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 class NfcExecutionEnvironment {
*/
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 class NfcExecutionEnvironment {
*/
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 class NfcExecutionEnvironment {
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");