diff options
-rw-r--r-- | nfc/api/system-current.txt | 11 | ||||
-rw-r--r-- | nfc/java/android/nfc/INfcAdapter.aidl | 4 | ||||
-rw-r--r-- | nfc/java/android/nfc/INfcOemExtensionCallback.aidl | 25 | ||||
-rw-r--r-- | nfc/java/android/nfc/NfcAdapter.java | 17 | ||||
-rw-r--r-- | nfc/java/android/nfc/NfcOemExtension.java | 160 | ||||
-rw-r--r-- | nfc/java/android/nfc/flags.aconfig | 8 |
6 files changed, 225 insertions, 0 deletions
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index ece8851df42f..79373a5bbf6c 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -9,6 +9,7 @@ package android.nfc { method @FlaggedApi("android.nfc.enable_nfc_reader_option") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableReaderOption(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean); method @FlaggedApi("android.nfc.enable_nfc_mainline") public int getAdapterState(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public android.nfc.NfcOemExtension getNfcOemExtension(); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn(); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported(); @@ -46,6 +47,16 @@ package android.nfc { method @FlaggedApi("android.nfc.nfc_vendor_cmd") public void onVendorNciResponse(@IntRange(from=0, to=15) int, int, @NonNull byte[]); } + @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension { + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback); + } + + public static interface NfcOemExtension.Callback { + method public void onTagConnected(boolean, @NonNull android.nfc.Tag); + } + } package android.nfc.cardemulation { diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index 8fea5af8fda1..bde63c36aefa 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -28,6 +28,7 @@ import android.nfc.INfcVendorNciCallback; import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; import android.nfc.INfcFCardEmulation; +import android.nfc.INfcOemExtensionCallback; import android.nfc.INfcUnlockHandler; import android.nfc.ITagRemovedCallback; import android.nfc.INfcDta; @@ -91,4 +92,7 @@ interface INfcAdapter int sendVendorNciMessage(int mt, int gid, int oid, in byte[] payload); void registerVendorExtensionCallback(in INfcVendorNciCallback callbacks); void unregisterVendorExtensionCallback(in INfcVendorNciCallback callbacks); + void registerOemExtensionCallback(INfcOemExtensionCallback callbacks); + void unregisterOemExtensionCallback(INfcOemExtensionCallback callbacks); + void clearPreference(); } diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl new file mode 100644 index 000000000000..6c9096d5d03e --- /dev/null +++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl @@ -0,0 +1,25 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.nfc; + +import android.nfc.Tag; + +/** + * @hide + */ +interface INfcOemExtensionCallback { + void onTagConnected(boolean connected, in Tag tag); +} diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index 40bbe746045c..7e0a1111b574 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -556,6 +556,7 @@ public final class NfcAdapter { final Context mContext; final HashMap<NfcUnlockHandler, INfcUnlockHandler> mNfcUnlockHandlers; final Object mLock; + final NfcOemExtension mNfcOemExtension; ITagRemovedCallback mTagRemovedListener; // protected by mLock @@ -864,6 +865,7 @@ public final class NfcAdapter { mLock = new Object(); mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener(getService()); mNfcVendorNciCallbackListener = new NfcVendorNciCallbackListener(getService()); + mNfcOemExtension = new NfcOemExtension(mContext, this); } /** @@ -2919,4 +2921,19 @@ public final class NfcAdapter { void onVendorNciNotification( @IntRange(from = 9, to = 15) int gid, int oid, @NonNull byte[] payload); } + + /** + * Returns an instance of {@link NfcOemExtension} associated with {@link NfcAdapter} instance. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @NonNull public NfcOemExtension getNfcOemExtension() { + synchronized (sLock) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } + return mNfcOemExtension; + } } diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java new file mode 100644 index 000000000000..1eff58cb80fd --- /dev/null +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +import android.annotation.CallbackExecutor; +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.content.Context; +import android.os.Binder; +import android.os.RemoteException; +import android.util.Log; + +import java.util.concurrent.Executor; + +/** + * Used for OEM extension APIs. + * This class holds all the APIs and callbacks defined for OEMs/vendors to extend the NFC stack + * for their proprietary features. + * + * @hide + */ +@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) +@SystemApi +public final class NfcOemExtension { + private static final String TAG = "NfcOemExtension"; + private static final int OEM_EXTENSION_RESPONSE_THRESHOLD_MS = 2000; + private final NfcAdapter mAdapter; + private final NfcOemExtensionCallback mOemNfcExtensionCallback; + private final Context mContext; + private Executor mExecutor = null; + private Callback mCallback = null; + private final Object mLock = new Object(); + + /** + * Interface for Oem extensions for NFC. + */ + public interface Callback { + /** + * Notify Oem to tag is connected or not + * ex - if tag is connected notify cover and Nfctest app if app is in testing mode + * + * @param connected status of the tag true if tag is connected otherwise false + * @param tag Tag details + */ + void onTagConnected(boolean connected, @NonNull Tag tag); + } + + + /** + * Constructor to be used only by {@link NfcAdapter}. + * @hide + */ + public NfcOemExtension(@NonNull Context context, @NonNull NfcAdapter adapter) { + mContext = context; + mAdapter = adapter; + mOemNfcExtensionCallback = new NfcOemExtensionCallback(); + } + + /** + * Register an {@link Callback} to listen for UWB oem extension callbacks + * <p>The provided callback will be invoked by the given {@link Executor}. + * + * @param executor an {@link Executor} to execute given callback + * @param callback oem implementation of {@link Callback} + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public void registerCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull Callback callback) { + synchronized (mLock) { + if (mCallback != null) { + Log.e(TAG, "Callback already registered. Unregister existing callback before" + + "registering"); + throw new IllegalArgumentException(); + } + try { + NfcAdapter.sService.registerOemExtensionCallback(mOemNfcExtensionCallback); + mCallback = callback; + mExecutor = executor; + } catch (RemoteException e) { + mAdapter.attemptDeadServiceRecovery(e); + } + } + } + + /** + * Unregister the specified {@link Callback} + * + * <p>The same {@link Callback} object used when calling + * {@link #registerCallback(Executor, Callback)} must be used. + * + * <p>Callbacks are automatically unregistered when an application process goes away + * + * @param callback oem implementation of {@link Callback} + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public void unregisterCallback(@NonNull Callback callback) { + synchronized (mLock) { + if (mCallback == null || mCallback != callback) { + Log.e(TAG, "Callback not registered"); + throw new IllegalArgumentException(); + } + try { + NfcAdapter.sService.unregisterOemExtensionCallback(mOemNfcExtensionCallback); + mCallback = null; + mExecutor = null; + } catch (RemoteException e) { + mAdapter.attemptDeadServiceRecovery(e); + } + } + } + + /** + * Clear NfcService preference, interface method to clear NFC preference values on OEM specific + * events. For ex: on soft reset, Nfc default values needs to be overridden by OEM defaults. + */ + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + public void clearPreference() { + try { + NfcAdapter.sService.clearPreference(); + } catch (RemoteException e) { + mAdapter.attemptDeadServiceRecovery(e); + } + } + + private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub { + @Override + public void onTagConnected(boolean connected, Tag tag) throws RemoteException { + synchronized (mLock) { + if (mCallback == null || mExecutor == null) { + return; + } + final long identity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mCallback.onTagConnected(connected, tag)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + } + } +} diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig index 44924ae925ef..5879595b00b7 100644 --- a/nfc/java/android/nfc/flags.aconfig +++ b/nfc/java/android/nfc/flags.aconfig @@ -76,3 +76,11 @@ flag { description: "Enable NFC vendor command support" bug: "289879306" } + +flag { + name: "nfc_oem_extension" + is_exported: true + namespace: "nfc" + description: "Enable NFC OEM extension support" + bug: "331206243" +} |