Loading nfc/api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -90,7 +90,11 @@ package android.nfc { method public void onEnable(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onEnableFinished(int); method public void onEnableStarted(); method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>); method public void onHceEventReceived(int); method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String); method public void onLaunchHceTapAgainDialog(@NonNull android.nfc.cardemulation.ApduServiceInfo, @NonNull String); method public void onNdefMessage(@NonNull android.nfc.Tag, @NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onReaderOptionChanged(boolean); method public void onRfDiscoveryStarted(boolean); Loading nfc/java/android/nfc/INfcOemExtensionCallback.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ */ package android.nfc; import android.content.ComponentName; import android.nfc.cardemulation.ApduServiceInfo; import android.nfc.NdefMessage; import android.nfc.Tag; import android.os.ResultReceiver; import java.util.List; /** * @hide */ Loading @@ -41,4 +46,8 @@ interface INfcOemExtensionCallback { void onCardEmulationActivated(boolean isActivated); void onRfFieldActivated(boolean isActivated); void onRfDiscoveryStarted(boolean isDiscoveryStarted); void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer); void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent); void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category); void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category); } nfc/java/android/nfc/NfcOemExtension.java +127 −9 Original line number Diff line number Diff line Loading @@ -23,8 +23,12 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.nfc.cardemulation.ApduServiceInfo; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Log; Loading Loading @@ -306,6 +310,60 @@ public final class NfcOemExtension { * @param isDiscoveryStarted true, if RF discovery started, else RF state is Idle. */ void onRfDiscoveryStarted(boolean isDiscoveryStarted); /** * Gets the intent to find the OEM package in the OEM App market. If the consumer returns * {@code null} or a timeout occurs, the intent from the first available package will be * used instead. * * @param packages the OEM packages name stored in the tag * @param intentConsumer The {@link Consumer} to be completed. * The {@link Consumer#accept(Object)} should be called with * the Intent required. * */ void onGetOemAppSearchIntent(@NonNull List<String> packages, @NonNull Consumer<Intent> intentConsumer); /** * Checks if the NDEF message contains any specific OEM package executable content * * @param tag the {@link android.nfc.Tag Tag} * @param message NDEF Message to read from tag * @param hasOemExecutableContent The {@link Consumer} to be completed. If there is * OEM package executable content, the * {@link Consumer#accept(Object)} should be called with * {@link Boolean#TRUE}, otherwise call with * {@link Boolean#FALSE}. */ void onNdefMessage(@NonNull Tag tag, @NonNull NdefMessage message, @NonNull Consumer<Boolean> hasOemExecutableContent); /** * Callback to indicate the app chooser activity should be launched for handling CE * transaction. This is invoked for example when there are more than 1 app installed that * can handle the HCE transaction. OEMs can launch the Activity based * on their requirement. * * @param selectedAid the selected AID from APDU * @param services {@link ApduServiceInfo} of the service triggering the activity * @param failedComponent the component failed to be resolved * @param category the category of the service */ void onLaunchHceAppChooserActivity(@NonNull String selectedAid, @NonNull List<ApduServiceInfo> services, @NonNull ComponentName failedComponent, @NonNull String category); /** * Callback to indicate tap again dialog should be launched for handling HCE transaction. * This is invoked for example when a CE service needs the device to unlocked before * handling the transaction. OEMs can launch the Activity based on their requirement. * * @param service {@link ApduServiceInfo} of the service triggering the dialog * @param category the category of the service */ void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category); } Loading Loading @@ -562,25 +620,25 @@ public final class NfcOemExtension { public void onApplyRouting(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onApplyRouting, ex)); new ReceiverWrapper<>(isSkipped), cb::onApplyRouting, ex)); } @Override public void onNdefRead(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onNdefRead, ex)); new ReceiverWrapper<>(isSkipped), cb::onNdefRead, ex)); } @Override public void onEnable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isAllowed), cb::onEnable, ex)); new ReceiverWrapper<>(isAllowed), cb::onEnable, ex)); } @Override public void onDisable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isAllowed), cb::onDisable, ex)); new ReceiverWrapper<>(isAllowed), cb::onDisable, ex)); } @Override public void onBootStarted() throws RemoteException { Loading Loading @@ -616,7 +674,7 @@ public final class NfcOemExtension { public void onTagDispatch(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onTagDispatch, ex)); new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex)); } @Override public void onRoutingChanged() throws RemoteException { Loading @@ -635,6 +693,59 @@ public final class NfcOemExtension { handleVoidCallback(enabled, cb::onReaderOptionChanged, ex)); } @Override public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoid2ArgCallback(packages, new ReceiverWrapper<>(intentConsumer), cb::onGetOemAppSearchIntent, ex)); } @Override public void onNdefMessage(Tag tag, NdefMessage message, ResultReceiver hasOemExecutableContent) throws RemoteException { mCallbackMap.forEach((cb, ex) -> { synchronized (mLock) { final long identity = Binder.clearCallingIdentity(); try { ex.execute(() -> cb.onNdefMessage( tag, message, new ReceiverWrapper<>(hasOemExecutableContent))); } catch (RuntimeException exception) { throw exception; } finally { Binder.restoreCallingIdentity(identity); } } }); } @Override public void onLaunchHceAppChooserActivity(String selectedAid, List<ApduServiceInfo> services, ComponentName failedComponent, String category) throws RemoteException { mCallbackMap.forEach((cb, ex) -> { synchronized (mLock) { final long identity = Binder.clearCallingIdentity(); try { ex.execute(() -> cb.onLaunchHceAppChooserActivity( selectedAid, services, failedComponent, category)); } catch (RuntimeException exception) { throw exception; } finally { Binder.restoreCallingIdentity(identity); } } }); } @Override public void onLaunchHceTapAgainActivity(ApduServiceInfo service, String category) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoid2ArgCallback(service, category, cb::onLaunchHceTapAgainDialog, ex)); } private <T> void handleVoidCallback( T input, Consumer<T> callbackMethod, Executor executor) { synchronized (mLock) { Loading Loading @@ -718,7 +829,7 @@ public final class NfcOemExtension { } } private class ReceiverWrapper implements Consumer<Boolean> { private class ReceiverWrapper<T> implements Consumer<T> { private final ResultReceiver mResultReceiver; ReceiverWrapper(ResultReceiver resultReceiver) { Loading @@ -726,12 +837,19 @@ public final class NfcOemExtension { } @Override public void accept(Boolean result) { mResultReceiver.send(result ? 1 : 0, null); public void accept(T result) { if (result instanceof Boolean) { mResultReceiver.send((Boolean) result ? 1 : 0, null); } else if (result instanceof Intent) { Bundle bundle = new Bundle(); bundle.putParcelable("intent", (Intent) result); mResultReceiver.send(0, bundle); } } @Override public Consumer<Boolean> andThen(Consumer<? super Boolean> after) { public Consumer<T> andThen(Consumer<? super T> after) { return Consumer.super.andThen(after); } } Loading Loading
nfc/api/system-current.txt +4 −0 Original line number Diff line number Diff line Loading @@ -90,7 +90,11 @@ package android.nfc { method public void onEnable(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onEnableFinished(int); method public void onEnableStarted(); method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>); method public void onHceEventReceived(int); method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String); method public void onLaunchHceTapAgainDialog(@NonNull android.nfc.cardemulation.ApduServiceInfo, @NonNull String); method public void onNdefMessage(@NonNull android.nfc.Tag, @NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onReaderOptionChanged(boolean); method public void onRfDiscoveryStarted(boolean); Loading
nfc/java/android/nfc/INfcOemExtensionCallback.aidl +9 −0 Original line number Diff line number Diff line Loading @@ -15,9 +15,14 @@ */ package android.nfc; import android.content.ComponentName; import android.nfc.cardemulation.ApduServiceInfo; import android.nfc.NdefMessage; import android.nfc.Tag; import android.os.ResultReceiver; import java.util.List; /** * @hide */ Loading @@ -41,4 +46,8 @@ interface INfcOemExtensionCallback { void onCardEmulationActivated(boolean isActivated); void onRfFieldActivated(boolean isActivated); void onRfDiscoveryStarted(boolean isDiscoveryStarted); void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer); void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent); void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category); void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category); }
nfc/java/android/nfc/NfcOemExtension.java +127 −9 Original line number Diff line number Diff line Loading @@ -23,8 +23,12 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.nfc.cardemulation.ApduServiceInfo; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.util.Log; Loading Loading @@ -306,6 +310,60 @@ public final class NfcOemExtension { * @param isDiscoveryStarted true, if RF discovery started, else RF state is Idle. */ void onRfDiscoveryStarted(boolean isDiscoveryStarted); /** * Gets the intent to find the OEM package in the OEM App market. If the consumer returns * {@code null} or a timeout occurs, the intent from the first available package will be * used instead. * * @param packages the OEM packages name stored in the tag * @param intentConsumer The {@link Consumer} to be completed. * The {@link Consumer#accept(Object)} should be called with * the Intent required. * */ void onGetOemAppSearchIntent(@NonNull List<String> packages, @NonNull Consumer<Intent> intentConsumer); /** * Checks if the NDEF message contains any specific OEM package executable content * * @param tag the {@link android.nfc.Tag Tag} * @param message NDEF Message to read from tag * @param hasOemExecutableContent The {@link Consumer} to be completed. If there is * OEM package executable content, the * {@link Consumer#accept(Object)} should be called with * {@link Boolean#TRUE}, otherwise call with * {@link Boolean#FALSE}. */ void onNdefMessage(@NonNull Tag tag, @NonNull NdefMessage message, @NonNull Consumer<Boolean> hasOemExecutableContent); /** * Callback to indicate the app chooser activity should be launched for handling CE * transaction. This is invoked for example when there are more than 1 app installed that * can handle the HCE transaction. OEMs can launch the Activity based * on their requirement. * * @param selectedAid the selected AID from APDU * @param services {@link ApduServiceInfo} of the service triggering the activity * @param failedComponent the component failed to be resolved * @param category the category of the service */ void onLaunchHceAppChooserActivity(@NonNull String selectedAid, @NonNull List<ApduServiceInfo> services, @NonNull ComponentName failedComponent, @NonNull String category); /** * Callback to indicate tap again dialog should be launched for handling HCE transaction. * This is invoked for example when a CE service needs the device to unlocked before * handling the transaction. OEMs can launch the Activity based on their requirement. * * @param service {@link ApduServiceInfo} of the service triggering the dialog * @param category the category of the service */ void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category); } Loading Loading @@ -562,25 +620,25 @@ public final class NfcOemExtension { public void onApplyRouting(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onApplyRouting, ex)); new ReceiverWrapper<>(isSkipped), cb::onApplyRouting, ex)); } @Override public void onNdefRead(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onNdefRead, ex)); new ReceiverWrapper<>(isSkipped), cb::onNdefRead, ex)); } @Override public void onEnable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isAllowed), cb::onEnable, ex)); new ReceiverWrapper<>(isAllowed), cb::onEnable, ex)); } @Override public void onDisable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isAllowed), cb::onDisable, ex)); new ReceiverWrapper<>(isAllowed), cb::onDisable, ex)); } @Override public void onBootStarted() throws RemoteException { Loading Loading @@ -616,7 +674,7 @@ public final class NfcOemExtension { public void onTagDispatch(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( new ReceiverWrapper(isSkipped), cb::onTagDispatch, ex)); new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex)); } @Override public void onRoutingChanged() throws RemoteException { Loading @@ -635,6 +693,59 @@ public final class NfcOemExtension { handleVoidCallback(enabled, cb::onReaderOptionChanged, ex)); } @Override public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoid2ArgCallback(packages, new ReceiverWrapper<>(intentConsumer), cb::onGetOemAppSearchIntent, ex)); } @Override public void onNdefMessage(Tag tag, NdefMessage message, ResultReceiver hasOemExecutableContent) throws RemoteException { mCallbackMap.forEach((cb, ex) -> { synchronized (mLock) { final long identity = Binder.clearCallingIdentity(); try { ex.execute(() -> cb.onNdefMessage( tag, message, new ReceiverWrapper<>(hasOemExecutableContent))); } catch (RuntimeException exception) { throw exception; } finally { Binder.restoreCallingIdentity(identity); } } }); } @Override public void onLaunchHceAppChooserActivity(String selectedAid, List<ApduServiceInfo> services, ComponentName failedComponent, String category) throws RemoteException { mCallbackMap.forEach((cb, ex) -> { synchronized (mLock) { final long identity = Binder.clearCallingIdentity(); try { ex.execute(() -> cb.onLaunchHceAppChooserActivity( selectedAid, services, failedComponent, category)); } catch (RuntimeException exception) { throw exception; } finally { Binder.restoreCallingIdentity(identity); } } }); } @Override public void onLaunchHceTapAgainActivity(ApduServiceInfo service, String category) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoid2ArgCallback(service, category, cb::onLaunchHceTapAgainDialog, ex)); } private <T> void handleVoidCallback( T input, Consumer<T> callbackMethod, Executor executor) { synchronized (mLock) { Loading Loading @@ -718,7 +829,7 @@ public final class NfcOemExtension { } } private class ReceiverWrapper implements Consumer<Boolean> { private class ReceiverWrapper<T> implements Consumer<T> { private final ResultReceiver mResultReceiver; ReceiverWrapper(ResultReceiver resultReceiver) { Loading @@ -726,12 +837,19 @@ public final class NfcOemExtension { } @Override public void accept(Boolean result) { mResultReceiver.send(result ? 1 : 0, null); public void accept(T result) { if (result instanceof Boolean) { mResultReceiver.send((Boolean) result ? 1 : 0, null); } else if (result instanceof Intent) { Bundle bundle = new Bundle(); bundle.putParcelable("intent", (Intent) result); mResultReceiver.send(0, bundle); } } @Override public Consumer<Boolean> andThen(Consumer<? super Boolean> after) { public Consumer<T> andThen(Consumer<? super T> after) { return Consumer.super.andThen(after); } } Loading