diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 64734f4dc762f4601211d28eb73a276db02d8b7f..64ea1ab0c826f6f62a5cb25039e083f4fff84dc7 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -10251,6 +10251,7 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean removeNfcUnlockHandler(android.nfc.NfcAdapter.NfcUnlockHandler); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean setControllerAlwaysOn(boolean); + method @FlaggedApi("android.nfc.enable_nfc_mainline") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setReaderMode(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setTagIntentAppPreferenceForUser(int, @NonNull String, boolean); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnListener(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); field public static final int TAG_INTENT_APP_PREF_RESULT_PACKAGE_NOT_FOUND = -1; // 0xffffffff diff --git a/core/java/Android.bp b/core/java/Android.bp index 70864d5329864678fc0416df59e597779c2b22f9..26b7581899964ca4056853bd13bb996725000c10 100644 --- a/core/java/Android.bp +++ b/core/java/Android.bp @@ -14,6 +14,15 @@ aidl_library { hdrs: ["android/hardware/HardwareBuffer.aidl"], } +// TODO (b/303286040): Remove this once |ENABLE_NFC_MAINLINE_FLAG| is rolled out +filegroup { + name: "framework-core-nfc-infcadapter-sources", + srcs: [ + "android/nfc/INfcAdapter.aidl", + ], + visibility: ["//frameworks/base/services/core"], +} + filegroup { name: "framework-core-sources", srcs: [ diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 46586308e3cfa14b0621a8fc54b0517145918bb2..4a7bd3f294584fc6c34dc607754ed69341fbb061 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -24,6 +24,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.UserIdInt; import android.app.Activity; @@ -37,6 +38,7 @@ import android.nfc.tech.MifareClassic; import android.nfc.tech.Ndef; import android.nfc.tech.NfcA; import android.nfc.tech.NfcF; +import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -1594,6 +1596,40 @@ public final class NfcAdapter { mNfcActivityManager.disableReaderMode(activity); } + // Flags arguments to NFC adapter to enable/disable NFC + private static final int DISABLE_POLLING_FLAGS = 0x1000; + private static final int ENABLE_POLLING_FLAGS = 0x0000; + + /** + * Privileged API to enable disable reader polling. + * Note: Use with caution! The app is responsible for ensuring that the polling state is + * returned to normal. + * + * @see #enableReaderMode(Activity, ReaderCallback, int, Bundle) for more detailed + * documentation. + * + * @param enablePolling whether to enable or disable polling. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE) + @SuppressLint("VisiblySynchronized") + public void setReaderMode(boolean enablePolling) { + synchronized (NfcAdapter.class) { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + } + Binder token = new Binder(); + int flags = enablePolling ? ENABLE_POLLING_FLAGS : DISABLE_POLLING_FLAGS; + try { + NfcAdapter.sService.setReaderMode(token, null, flags, null); + } catch (RemoteException e) { + attemptDeadServiceRecovery(e); + } + } + /** * Manually invoke Android Beam to share data. * diff --git a/services/core/Android.bp b/services/core/Android.bp index 9ac30f334d0b134c3b00dc023b5a7eae7d0980fc..189ab19763acb5823187e7de7ff14c4cf58acce8 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -118,6 +118,7 @@ java_library_static { ":display-device-config", ":display-layout-config", ":device-state-config", + ":framework-core-nfc-infcadapter-sources", "java/com/android/server/EventLogTags.logtags", "java/com/android/server/am/EventLogTags.logtags", "java/com/android/server/wm/EventLogTags.logtags", @@ -178,6 +179,7 @@ java_library_static { "android.hardware.power.stats-V2-java", "android.hardware.power-V4-java", "android.hidl.manager-V1.2-java", + "android.nfc.flags-aconfig-java", "cbor-java", "icu4j_calendar_astronomer", "android.security.aaid_aidl-java", diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index f8f0088ac04771eaace65479752786dbb7eda12a..3c885a14531555c957facae5d104e252f8596bb5 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -53,6 +53,8 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.media.AudioManager; import android.nfc.INfcAdapter; +import android.nfc.NfcAdapter; +import android.nfc.NfcManager; import android.os.Binder; import android.os.Handler; import android.os.HandlerExecutor; @@ -162,10 +164,6 @@ public class CameraServiceProxy extends SystemService * SCALER_ROTATE_AND_CROP_NONE -> Always return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE */ - // Flags arguments to NFC adapter to enable/disable NFC - public static final int DISABLE_POLLING_FLAGS = 0x1000; - public static final int ENABLE_POLLING_FLAGS = 0x0000; - // Handler message codes private static final int MSG_SWITCH_USER = 1; private static final int MSG_NOTIFY_DEVICE_STATE = 2; @@ -215,7 +213,6 @@ public class CameraServiceProxy extends SystemService private final List<CameraUsageEvent> mCameraUsageHistory = new ArrayList<>(); private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc"; - private static final String NFC_SERVICE_BINDER_NAME = "nfc"; private static final IBinder nfcInterfaceToken = new Binder(); private final boolean mNotifyNfc; @@ -1255,8 +1252,13 @@ public class CameraServiceProxy extends SystemService } } - private void notifyNfcService(boolean enablePolling) { - + // TODO(b/303286040): Remove the raw INfcAdapter usage once |ENABLE_NFC_MAINLINE_FLAG| is + // rolled out. + private static final String NFC_SERVICE_BINDER_NAME = "nfc"; + // Flags arguments to NFC adapter to enable/disable NFC + public static final int DISABLE_POLLING_FLAGS = 0x1000; + public static final int ENABLE_POLLING_FLAGS = 0x0000; + private void setNfcReaderModeUsingINfcAdapter(boolean enablePolling) { IBinder nfcServiceBinder = getBinderService(NFC_SERVICE_BINDER_NAME); if (nfcServiceBinder == null) { Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); @@ -1272,6 +1274,25 @@ public class CameraServiceProxy extends SystemService } } + private void notifyNfcService(boolean enablePolling) { + if (android.nfc.Flags.enableNfcMainline()) { + NfcManager nfcManager = mContext.getSystemService(NfcManager.class); + if (nfcManager == null) { + Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); + return; + } + NfcAdapter nfcAdapter = nfcManager.getDefaultAdapter(); + if (nfcAdapter == null) { + Slog.w(TAG, "Could not connect to NFC service to notify it of camera state"); + return; + } + if (DEBUG) Slog.v(TAG, "Setting NFC reader mode. enablePolling: " + enablePolling); + nfcAdapter.setReaderMode(enablePolling); + } else { + setNfcReaderModeUsingINfcAdapter(enablePolling); + } + } + private static int[] toArray(Collection<Integer> c) { int len = c.size(); int[] ret = new int[len];