Implement dead service recovery in NFC extras library.
Change-Id: I4f1d714c625470df4cda2c4c9aacb8d27bfabb10
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user