diff --git a/core/api/system-current.txt b/core/api/system-current.txt index eebf2831eafca..e31f174973234 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -6728,12 +6728,18 @@ package android.nfc { method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean enableSecureNfc(boolean); 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(); + method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback); 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 public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity, int); + method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void unregisterControllerAlwaysOnStateCallback(@NonNull android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback); field public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 1; // 0x1 } + public static interface NfcAdapter.ControllerAlwaysOnStateCallback { + method public void onStateChanged(boolean); + } + public static interface NfcAdapter.NfcUnlockHandler { method public boolean onUnlockAttempted(android.nfc.Tag); } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 11445e9aec5aa..d5cc01aac0cc7 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -24,6 +24,7 @@ import android.nfc.Tag; import android.nfc.TechListParcel; import android.nfc.IAppCallback; import android.nfc.INfcAdapterExtras; +import android.nfc.INfcControllerAlwaysOnStateCallback; import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; import android.nfc.INfcFCardEmulation; @@ -75,4 +76,6 @@ interface INfcAdapter boolean setControllerAlwaysOn(boolean value); boolean isControllerAlwaysOn(); boolean isControllerAlwaysOnSupported(); + void registerControllerAlwaysOnStateCallback(in INfcControllerAlwaysOnStateCallback callback); + void unregisterControllerAlwaysOnStateCallback(in INfcControllerAlwaysOnStateCallback callback); } diff --git a/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl b/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl new file mode 100644 index 0000000000000..1e4fdd79e8314 --- /dev/null +++ b/core/java/android/nfc/INfcControllerAlwaysOnStateCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright 2021 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; + +/** + * @hide + */ +oneway interface INfcControllerAlwaysOnStateCallback { + /** + * Called whenever the controller always on state changes + * + * @param isEnabled true if the state is enabled, false otherwise + */ + void onControllerAlwaysOnStateChanged(boolean isEnabled); +} diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index eed2c77b06b93..bbf802ca58d8a 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -16,6 +16,7 @@ package android.nfc; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; @@ -47,6 +48,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.concurrent.Executor; /** * Represents the local NFC adapter. @@ -65,6 +67,8 @@ import java.util.List; public final class NfcAdapter { static final String TAG = "NFC"; + private final NfcControllerAlwaysOnStateListener mControllerAlwaysOnStateListener; + /** * Intent to start an activity when a tag with NDEF payload is discovered. * @@ -349,22 +353,6 @@ public final class NfcAdapter { public static final String EXTRA_HANDOVER_TRANSFER_STATUS = "android.nfc.extra.HANDOVER_TRANSFER_STATUS"; - /** @hide */ - public static final String ACTION_ALWAYS_ON_STATE_CHANGED = - "android.nfc.action.ALWAYS_ON_STATE_CHANGED"; - - /** - * Used as an int extra field in {@link #ACTION_ALWAYS_ON_STATE_CHANGED} - * intents to request the current power state. Possible values are: - * {@link #STATE_OFF}, - * {@link #STATE_TURNING_ON}, - * {@link #STATE_ON}, - * {@link #STATE_TURNING_OFF}, - * @hide - */ - public static final String EXTRA_ALWAYS_ON_STATE = - "android.nfc.extra.ALWAYS_ON_STATE"; - /** @hide */ public static final int HANDOVER_TRANSFER_STATUS_SUCCESS = 0; /** @hide */ @@ -429,6 +417,22 @@ public final class NfcAdapter { public void onTagDiscovered(Tag tag); } + /** + * A callback to be invoked when NFC controller always on state changes. + *
Register your {@code ControllerAlwaysOnStateCallback} implementation with {@link
+ * NfcAdapter#registerControllerAlwaysOnStateCallback} and disable it with {@link
+ * NfcAdapter#unregisterControllerAlwaysOnStateCallback}.
+ * @see #registerControllerAlwaysOnStateCallback
+ * @hide
+ */
+ @SystemApi
+ public interface ControllerAlwaysOnStateCallback {
+ /**
+ * Called on NFC controller always on state changes
+ */
+ void onStateChanged(boolean isEnabled);
+ }
+
/**
* A callback to be invoked when the system successfully delivers your {@link NdefMessage}
* to another device.
@@ -744,6 +748,7 @@ public final class NfcAdapter {
mNfcUnlockHandlers = new HashMap This API is for the NFCC internal state management. It allows to discriminate
- * the controller function from the NFC function by keeping the NFC Controller on without
+ * the controller function from the NFC function by keeping the NFC controller on without
* any NFC RF enabled if necessary.
- * This call is asynchronous. Listen for {@link #ACTION_ALWAYS_ON_STATE_CHANGED}
- * broadcasts to find out when the operation is complete.
- * If this returns true, then either NFCC is already on, or
- * a {@link #ACTION_ALWAYS_ON_STATE_CHANGED} broadcast will be sent to indicate
- * a state transition.
- * If this returns false, then there is some problem that prevents an attempt to turn NFCC on.
+ * This call is asynchronous. Register a callback {@link #ControllerAlwaysOnStateCallback}
+ * by {@link #registerControllerAlwaysOnStateCallback} to find out when the operation is
+ * complete.
+ * If this returns true, then either NFCC always on state has been set based on the value,
+ * or a {@link ControllerAlwaysOnStateCallback#onStateChanged(boolean)} will be invoked to
+ * indicate the state change.
+ * If this returns false, then there is some problem that prevents an attempt to turn NFCC
+ * always on.
* @param value if true the NFCC will be kept on (with no RF enabled if NFC adapter is
* disabled), if false the NFCC will follow completely the Nfc adapter state.
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
@@ -2284,7 +2291,6 @@ public final class NfcAdapter {
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @hide
*/
-
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean isControllerAlwaysOn() {
@@ -2313,7 +2319,6 @@ public final class NfcAdapter {
* @throws UnsupportedOperationException if FEATURE_NFC is unavailable.
* @hide
*/
-
@SystemApi
@RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
public boolean isControllerAlwaysOnSupported() {
@@ -2337,4 +2342,39 @@ public final class NfcAdapter {
return false;
}
}
+
+ /**
+ * Register a {@link ControllerAlwaysOnStateCallback} to listen for NFC controller always on
+ * state changes
+ * The provided callback will be invoked by the given {@link Executor}.
+ *
+ * @param executor an {@link Executor} to execute given callback
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public void registerControllerAlwaysOnStateCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull ControllerAlwaysOnStateCallback callback) {
+ mControllerAlwaysOnStateListener.register(executor, callback);
+ }
+
+ /**
+ * Unregister the specified {@link ControllerAlwaysOnStateCallback}
+ * The same {@link ControllerAlwaysOnStateCallback} object used when calling
+ * {@link #registerControllerAlwaysOnStateCallback(Executor, ControllerAlwaysOnStateCallback)}
+ * must be used.
+ *
+ * Callbacks are automatically unregistered when application process goes away
+ *
+ * @param callback user implementation of the {@link ControllerAlwaysOnStateCallback}
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON)
+ public void unregisterControllerAlwaysOnStateCallback(
+ @NonNull ControllerAlwaysOnStateCallback callback) {
+ mControllerAlwaysOnStateListener.unregister(callback);
+ }
}
diff --git a/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java b/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java
new file mode 100644
index 0000000000000..69a9ec79edb29
--- /dev/null
+++ b/core/java/android/nfc/NfcControllerAlwaysOnStateListener.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2021 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.NonNull;
+import android.nfc.NfcAdapter.ControllerAlwaysOnStateCallback;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class NfcControllerAlwaysOnStateListener extends INfcControllerAlwaysOnStateCallback.Stub {
+ private static final String TAG = "NfcControllerAlwaysOnStateListener";
+
+ private final INfcAdapter mAdapter;
+
+ private final Map