nfc(api): Add API to set/get default NFC SubscriptionId
For devices that have UICC/EUICC configured to serve as NFCEE, this API
will return the subscription ID of default NFCEE.
Bug: 321314635
Test: atest CtsNfcTestCases
Change-Id: I9d49c807ffa28653c205855448094435c30b2f02
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 7ae2eafa..2aa73db 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -202,6 +202,7 @@
method public boolean categoryAllowsForegroundPreference(String);
method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public java.util.List<java.lang.String> getAidsForPreferredPaymentService();
method public java.util.List<java.lang.String> getAidsForService(android.content.ComponentName, String);
+ method @FlaggedApi("android.nfc.enable_card_emulation_euicc") public int getDefaultNfcSubscriptionId();
method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public CharSequence getDescriptionForPreferredPaymentService();
method public static android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
method @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public String getRouteDestinationForPreferredPaymentService();
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 15814ed..9ada14b 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -186,14 +186,19 @@
public final class CardEmulation {
method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
- method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, int, int);
- method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity);
+ method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overrideRoutingTable(@NonNull android.app.Activity, int, int);
+ method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void recoverRoutingTable(@NonNull android.app.Activity);
+ method @FlaggedApi("android.nfc.enable_card_emulation_euicc") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setDefaultNfcSubscriptionId(int);
method @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setServiceEnabledForCategoryOther(@NonNull android.content.ComponentName, boolean);
field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3; // 0x3
field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1; // 0x1
field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2; // 0x2
field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4; // 0x4
field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_OK = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2; // 0x2
+ field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1; // 0x1
+ field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3; // 0x3
+ field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0; // 0x0
}
}
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index 633d8bf..bb9fe95 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -53,6 +53,8 @@
void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
void recoverRoutingTable(int userHandle);
boolean isEuiccSupported();
+ int getDefaultNfcSubscriptionId(in String pkg);
+ int setDefaultNfcSubscriptionId(int subscriptionId, in String pkg);
void setAutoChangeStatus(boolean state);
boolean isAutoChangeEnabled();
List<String> getRoutingStatus();
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index e9ec721..3ccdbe4 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -22,6 +22,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -45,6 +46,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
+import android.telephony.SubscriptionManager;
import android.util.ArrayMap;
import android.util.Log;
@@ -1010,6 +1012,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
@FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
public void overrideRoutingTable(
@NonNull Activity activity, @ProtocolAndTechnologyRoute int protocol,
@@ -1037,6 +1040,7 @@
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
@FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
public void recoverRoutingTable(@NonNull Activity activity) {
if (!activity.isResumed()) {
@@ -1058,6 +1062,97 @@
}
/**
+ * Setting the default subscription ID succeeded.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0;
+
+ /**
+ * Setting the default subscription ID failed because the subscription ID is invalid.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1;
+
+ /**
+ * Setting the default subscription ID failed because there was an internal error processing
+ * the request. For ex: NFC service died in the middle of handling the API.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR = 2;
+
+ /**
+ * Setting the default subscription ID failed because this feature is not supported on the
+ * device.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3;
+
+ /** @hide */
+ @IntDef(prefix = "SET_SUBSCRIPTION_ID_STATUS_",
+ value = {
+ SET_SUBSCRIPTION_ID_STATUS_SUCCESS,
+ SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID,
+ SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR,
+ SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SetSubscriptionIdStatus {}
+
+ /**
+ * Sets the system's default NFC subscription id.
+ *
+ * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this sets the
+ * default UICC NFCEE that will handle NFC offhost CE transactoions </p>
+ *
+ * @param subscriptionId the default NFC subscription Id to set.
+ * @return status of the operation.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ * @hide
+ */
+ @SystemApi
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public @SetSubscriptionIdStatus int setDefaultNfcSubscriptionId(int subscriptionId) {
+ return callServiceReturn(() ->
+ sService.setDefaultNfcSubscriptionId(
+ subscriptionId, mContext.getPackageName()),
+ SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR);
+ }
+
+ /**
+ * Returns the system's default NFC subscription id.
+ *
+ * <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this returns the
+ * default UICC NFCEE that will handle NFC offhost CE transactoions </p>
+ * <p> If the device has no UICC that can serve as NFCEE, this will return
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.</p>
+ *
+ * @return the default NFC subscription Id if set,
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} otherwise.
+ *
+ * @throws UnsupportedOperationException If the device does not have
+ * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}.
+ */
+ @RequiresFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+ @FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public int getDefaultNfcSubscriptionId() {
+ return callServiceReturn(() ->
+ sService.getDefaultNfcSubscriptionId(mContext.getPackageName()),
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ /**
* Returns the value of {@link Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT}.
*
* @param context A context