summaryrefslogtreecommitdiff
path: root/nfc-non-updatable
diff options
context:
space:
mode:
author Roshan Pius <rpius@google.com> 2024-12-13 15:37:37 -0800
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2024-12-13 15:37:37 -0800
commit19faae068d207e915eaf00be489cb1a0fe63bba1 (patch)
treeefcb891ca8758d8fd75fdbe7be9ea02d9cf75751 /nfc-non-updatable
parent132a431ef6685b02525da38e45088bc142251927 (diff)
Revert "nfc(framework): Split non-updatable portion to a separat..."
Revert submission 3411958-framework-nfc-code-split Reason for revert: Causing a lot of merge conflicts down the chain because of missing changes in aosp/main. Reverted changes: /q/submissionid:3411958-framework-nfc-code-split Bug: 384067476 Change-Id: Ic451b2f5ebd80f875bc2c46c6a17516dc81dfd16 Test: Compiles
Diffstat (limited to 'nfc-non-updatable')
-rw-r--r--nfc-non-updatable/Android.bp23
-rw-r--r--nfc-non-updatable/OWNERS2
-rw-r--r--nfc-non-updatable/flags/flags.aconfig191
-rw-r--r--nfc-non-updatable/java/android/nfc/NfcServiceManager.java126
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.aidl19
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.java298
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.aidl19
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.java1172
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.aidl19
-rw-r--r--nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.java497
10 files changed, 0 insertions, 2366 deletions
diff --git a/nfc-non-updatable/Android.bp b/nfc-non-updatable/Android.bp
deleted file mode 100644
index ff987bb84b17..000000000000
--- a/nfc-non-updatable/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-package {
- default_team: "trendy_team_fwk_nfc",
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "framework-nfc-non-updatable-sources",
- path: "java",
- srcs: [
- "java/android/nfc/NfcServiceManager.java",
- "java/android/nfc/cardemulation/ApduServiceInfo.aidl",
- "java/android/nfc/cardemulation/ApduServiceInfo.java",
- "java/android/nfc/cardemulation/NfcFServiceInfo.aidl",
- "java/android/nfc/cardemulation/NfcFServiceInfo.java",
- "java/android/nfc/cardemulation/AidGroup.aidl",
- "java/android/nfc/cardemulation/AidGroup.java",
- ],
-}
diff --git a/nfc-non-updatable/OWNERS b/nfc-non-updatable/OWNERS
deleted file mode 100644
index f46dccd97974..000000000000
--- a/nfc-non-updatable/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 48448
-include platform/packages/apps/Nfc:/OWNERS \ No newline at end of file
diff --git a/nfc-non-updatable/flags/flags.aconfig b/nfc-non-updatable/flags/flags.aconfig
deleted file mode 100644
index ee287aba709f..000000000000
--- a/nfc-non-updatable/flags/flags.aconfig
+++ /dev/null
@@ -1,191 +0,0 @@
-package: "android.nfc"
-container: "system"
-
-flag {
- name: "nfc_event_listener"
- is_exported: true
- namespace: "nfc"
- description: "Enable NFC Event listener APIs"
- bug: "356447790"
-}
-
-flag {
- name: "enable_nfc_mainline"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC mainline changes"
- bug: "292140387"
-}
-
-flag {
- name: "enable_nfc_reader_option"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC reader option API changes"
- bug: "291187960"
-}
-
-flag {
- name: "enable_nfc_user_restriction"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC user restriction"
- bug: "291187960"
-}
-
-flag {
- name: "nfc_observe_mode"
- is_exported: true
- namespace: "nfc"
- description: "Enable NFC Observe Mode"
- bug: "294217286"
-}
-
-flag {
- name: "nfc_read_polling_loop"
- is_exported: true
- namespace: "nfc"
- description: "Enable NFC Polling Loop Notifications"
- bug: "294217286"
-}
-
-flag {
- name: "nfc_observe_mode_st_shim"
- namespace: "nfc"
- description: "Enable NFC Observe Mode ST shim"
- bug: "294217286"
-}
-
-flag {
- name: "nfc_read_polling_loop_st_shim"
- namespace: "nfc"
- description: "Enable NFC Polling Loop Notifications ST shim"
- bug: "294217286"
-}
-
-flag {
- name: "enable_tag_detection_broadcasts"
- namespace: "nfc"
- description: "Enable sending broadcasts to Wallet role holder when a tag enters/leaves the field."
- bug: "306203494"
-}
-
-flag {
- name: "enable_nfc_charging"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC charging changes"
- bug: "292143899"
-}
-
-flag {
- name: "enable_nfc_set_discovery_tech"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC set discovery tech API"
- bug: "300351519"
-}
-
-flag {
- name: "nfc_vendor_cmd"
- is_exported: true
- namespace: "nfc"
- 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"
-}
-
-flag {
- name: "nfc_state_change"
- is_exported: true
- namespace: "nfc"
- description: "Enable nfc state change API"
- bug: "319934052"
-}
-
-flag {
- name: "nfc_set_default_disc_tech"
- is_exported: true
- namespace: "nfc"
- description: "Flag for NFC set default disc tech API"
- bug: "321311407"
-}
-
-flag {
- name: "nfc_persist_log"
- is_exported: true
- namespace: "nfc"
- description: "Enable NFC persistent log support"
- bug: "321310044"
-}
-
-flag {
- name: "nfc_action_manage_services_settings"
- is_exported: true
- namespace: "nfc"
- description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS"
- bug: "358129872"
-}
-
-flag {
- name: "nfc_override_recover_routing_table"
- is_exported: true
- namespace: "nfc"
- description: "Enable override and recover routing table"
- bug: "329043523"
-}
-
-flag {
- name: "nfc_watchdog"
- is_exported: true
- namespace: "nfc"
- description: "Enable watchdog for the NFC system process"
- bug: "362937338"
-}
-
-flag {
- name: "enable_card_emulation_euicc"
- is_exported: true
- namespace: "nfc"
- description: "Enable EUICC card emulation"
- bug: "321314635"
-}
-
-flag {
- name: "nfc_state_change_security_log_event_enabled"
- is_exported: true
- namespace: "nfc"
- description: "Enabling security log for nfc state change"
- bug: "319934052"
-}
-
-flag {
- name: "nfc_associated_role_services"
- is_exported: true
- namespace: "nfc"
- description: "Share wallet role routing priority with associated services"
- bug: "366243361"
-}
-
-flag {
- name: "nfc_set_service_enabled_for_category_other"
- is_exported: true
- namespace: "nfc"
- description: "Enable set service enabled for category other"
- bug: "338157113"
-}
-
-flag {
- name: "nfc_check_tag_intent_preference"
- is_exported: true
- namespace: "nfc"
- description: "App can check its tag intent preference status"
- bug: "335916336"
-}
diff --git a/nfc-non-updatable/java/android/nfc/NfcServiceManager.java b/nfc-non-updatable/java/android/nfc/NfcServiceManager.java
deleted file mode 100644
index 5582f1154cad..000000000000
--- a/nfc-non-updatable/java/android/nfc/NfcServiceManager.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2022 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.
- */
-
-
-/**********************************************************************
- * This file is not a part of the NFC mainline modure *
- * *******************************************************************/
-
-package android.nfc;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.annotation.SystemApi.Client;
-import android.content.Context;
-import android.os.IBinder;
-import android.os.ServiceManager;
-
-/**
- * Provides a way to register and obtain the system service binder objects managed by the nfc
- * service.
- *
- * @hide
- */
-@SystemApi(client = Client.MODULE_LIBRARIES)
-public class NfcServiceManager {
-
- /**
- * @hide
- */
- public NfcServiceManager() {
- }
-
- /**
- * A class that exposes the methods to register and obtain each system service.
- */
- public static final class ServiceRegisterer {
- private final String mServiceName;
-
- /**
- * @hide
- */
- public ServiceRegisterer(String serviceName) {
- mServiceName = serviceName;
- }
-
- /**
- * Register a system server binding object for a service.
- */
- public void register(@NonNull IBinder service) {
- ServiceManager.addService(mServiceName, service);
- }
-
- /**
- * Get the system server binding object for a service.
- *
- * <p>This blocks until the service instance is ready,
- * or a timeout happens, in which case it returns null.
- */
- @Nullable
- public IBinder get() {
- return ServiceManager.getService(mServiceName);
- }
-
- /**
- * Get the system server binding object for a service.
- *
- * <p>This blocks until the service instance is ready,
- * or a timeout happens, in which case it throws {@link ServiceNotFoundException}.
- */
- @NonNull
- public IBinder getOrThrow() throws ServiceNotFoundException {
- try {
- return ServiceManager.getServiceOrThrow(mServiceName);
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new ServiceNotFoundException(mServiceName);
- }
- }
-
- /**
- * Get the system server binding object for a service. If the specified service is
- * not available, it returns null.
- */
- @Nullable
- public IBinder tryGet() {
- return ServiceManager.checkService(mServiceName);
- }
- }
-
- /**
- * See {@link ServiceRegisterer#getOrThrow}.
- *
- */
- public static class ServiceNotFoundException extends ServiceManager.ServiceNotFoundException {
- /**
- * Constructor.
- *
- * @param name the name of the binder service that cannot be found.
- *
- */
- public ServiceNotFoundException(@NonNull String name) {
- super(name);
- }
- }
-
- /**
- * Returns {@link ServiceRegisterer} for the "nfc" service.
- */
- @NonNull
- public ServiceRegisterer getNfcManagerServiceRegisterer() {
- return new ServiceRegisterer(Context.NFC_SERVICE);
- }
-}
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.aidl b/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.aidl
deleted file mode 100644
index 56d6fa559677..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013 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.cardemulation;
-
-parcelable AidGroup;
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.java b/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.java
deleted file mode 100644
index ae3e333051d7..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/AidGroup.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2015 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.cardemulation;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.nfc.Flags;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Log;
-import android.util.proto.ProtoOutputStream;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.regex.Pattern;
-
-/**********************************************************************
- * This file is not a part of the NFC mainline module *
- * *******************************************************************/
-
-/**
- * The AidGroup class represents a group of Application Identifiers (AIDs).
- *
- * <p>The format of AIDs is defined in the ISO/IEC 7816-4 specification. This class
- * requires the AIDs to be input as a hexadecimal string, with an even amount of
- * hexadecimal characters, e.g. "F014811481".
- *
- * @hide
- */
-@SystemApi
-@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-public final class AidGroup implements Parcelable {
- /**
- * The maximum number of AIDs that can be present in any one group.
- */
- private static final int MAX_NUM_AIDS = 256;
-
- private static final String TAG = "AidGroup";
-
-
- private final List<String> mAids;
- private final String mCategory;
- @SuppressWarnings("unused") // Unused as of now, but part of the XML input.
- private final String mDescription;
-
- /**
- * Creates a new AidGroup object.
- *
- * @param aids list of AIDs present in the group
- * @param category category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public AidGroup(@NonNull List<String> aids, @Nullable String category) {
- if (aids == null || aids.size() == 0) {
- throw new IllegalArgumentException("No AIDS in AID group.");
- }
- if (aids.size() > MAX_NUM_AIDS) {
- throw new IllegalArgumentException("Too many AIDs in AID group.");
- }
- for (String aid : aids) {
- if (!isValidAid(aid)) {
- throw new IllegalArgumentException("AID " + aid + " is not a valid AID.");
- }
- }
- if (isValidCategory(category)) {
- this.mCategory = category;
- } else {
- this.mCategory = CardEmulation.CATEGORY_OTHER;
- }
- this.mAids = new ArrayList<String>(aids.size());
- for (String aid : aids) {
- this.mAids.add(aid.toUpperCase(Locale.US));
- }
- this.mDescription = null;
- }
-
- /**
- * Creates a new AidGroup object.
- *
- * @param category category of this group, e.g. {@link CardEmulation#CATEGORY_PAYMENT}
- * @param description description of this group
- */
- AidGroup(@NonNull String category, @NonNull String description) {
- this.mAids = new ArrayList<String>();
- this.mCategory = category;
- this.mDescription = description;
- }
-
- /**
- * Returns the category of this group.
- * @return the category of this AID group
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getCategory() {
- return mCategory;
- }
-
- /**
- * Returns the list of AIDs in this group.
- *
- * @return the list of AIDs in this group
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public List<String> getAids() {
- return mAids;
- }
-
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder("Category: " + mCategory
- + ", AIDs:");
- for (String aid : mAids) {
- out.append(aid);
- out.append(", ");
- }
- return out.toString();
- }
-
- /**
- * Dump debugging info as AidGroupProto.
- *
- * If the output belongs to a sub message, the caller is responsible for wrapping this function
- * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
- *
- * @param proto the ProtoOutputStream to write to
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void dump(@NonNull ProtoOutputStream proto) {
- proto.write(AidGroupProto.CATEGORY, mCategory);
- for (String aid : mAids) {
- proto.write(AidGroupProto.AIDS, aid);
- }
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public int describeContents() {
- return 0;
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString8(mCategory);
- dest.writeInt(mAids.size());
- if (mAids.size() > 0) {
- dest.writeStringList(mAids);
- }
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public static final @NonNull Parcelable.Creator<AidGroup> CREATOR =
- new Parcelable.Creator<AidGroup>() {
-
- @Override
- public AidGroup createFromParcel(Parcel source) {
- String category = source.readString8();
- int listSize = source.readInt();
- ArrayList<String> aidList = new ArrayList<String>();
- if (listSize > 0) {
- source.readStringList(aidList);
- }
- return new AidGroup(aidList, category);
- }
-
- @Override
- public AidGroup[] newArray(int size) {
- return new AidGroup[size];
- }
- };
-
- /**
- * Create an instance of AID group from XML file.
- *
- * @param parser input xml parser stream
- * @throws XmlPullParserException If an error occurs parsing the element.
- * @throws IOException If an error occurs reading the element.
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Nullable
- public static AidGroup createFromXml(@NonNull XmlPullParser parser)
- throws XmlPullParserException, IOException {
- String category = null;
- ArrayList<String> aids = new ArrayList<String>();
- AidGroup group = null;
- boolean inGroup = false;
-
- int eventType = parser.getEventType();
- int minDepth = parser.getDepth();
- while (eventType != XmlPullParser.END_DOCUMENT && parser.getDepth() >= minDepth) {
- String tagName = parser.getName();
- if (eventType == XmlPullParser.START_TAG) {
- if (tagName.equals("aid")) {
- if (inGroup) {
- String aid = parser.getAttributeValue(null, "value");
- if (aid != null) {
- aids.add(aid.toUpperCase());
- }
- } else {
- Log.d(TAG, "Ignoring <aid> tag while not in group");
- }
- } else if (tagName.equals("aid-group")) {
- category = parser.getAttributeValue(null, "category");
- if (category == null) {
- Log.e(TAG, "<aid-group> tag without valid category");
- return null;
- }
- inGroup = true;
- } else {
- Log.d(TAG, "Ignoring unexpected tag: " + tagName);
- }
- } else if (eventType == XmlPullParser.END_TAG) {
- if (tagName.equals("aid-group") && inGroup && aids.size() > 0) {
- group = new AidGroup(aids, category);
- break;
- }
- }
- eventType = parser.next();
- }
- return group;
- }
-
- /**
- * Serialize instance of AID group to XML file.
- * @param out XML serializer stream
- * @throws IOException If an error occurs reading the element.
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void writeAsXml(@NonNull XmlSerializer out) throws IOException {
- out.startTag(null, "aid-group");
- out.attribute(null, "category", mCategory);
- for (String aid : mAids) {
- out.startTag(null, "aid");
- out.attribute(null, "value", aid);
- out.endTag(null, "aid");
- }
- out.endTag(null, "aid-group");
- }
-
- private static boolean isValidCategory(String category) {
- return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
- CardEmulation.CATEGORY_OTHER.equals(category);
- }
-
- private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
- /**
- * Copied over from {@link CardEmulation#isValidAid(String)}
- * @hide
- */
- private static boolean isValidAid(String aid) {
- if (aid == null)
- return false;
-
- // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
- if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- // If not a prefix/subset AID, the total length must be even (even # of AID chars)
- if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- // Verify hex characters
- if (!AID_PATTERN.matcher(aid).matches()) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- return true;
- }
-}
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.aidl b/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.aidl
deleted file mode 100644
index a62fdd6a6c5c..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013 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.cardemulation;
-
-parcelable ApduServiceInfo;
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.java
deleted file mode 100644
index eac783628ed9..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ /dev/null
@@ -1,1172 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-/**********************************************************************
- * This file is not a part of the NFC mainline module *
- * *******************************************************************/
-
-package android.nfc.cardemulation;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.content.res.Resources.NotFoundException;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.nfc.Flags;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.R;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-
-/**
- * Class holding APDU service info.
- *
- * @hide
- */
-@SystemApi
-@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-public final class ApduServiceInfo implements Parcelable {
- private static final String TAG = "ApduServiceInfo";
-
- /**
- * The service that implements this
- */
- private final ResolveInfo mService;
-
- /**
- * Description of the service
- */
- private final String mDescription;
-
- /**
- * Whether this service represents AIDs running on the host CPU
- */
- private final boolean mOnHost;
-
- /**
- * Offhost reader name.
- * eg: SIM, eSE etc
- */
- private String mOffHostName;
-
- /**
- * Offhost reader name from manifest file.
- * Used for resetOffHostSecureElement()
- */
- private final String mStaticOffHostName;
-
- /**
- * Mapping from category to static AID group
- */
- private final HashMap<String, AidGroup> mStaticAidGroups;
-
- /**
- * Mapping from category to dynamic AID group
- */
- private final HashMap<String, AidGroup> mDynamicAidGroups;
-
-
- private final Map<String, Boolean> mAutoTransact;
-
- private final Map<Pattern, Boolean> mAutoTransactPatterns;
-
- /**
- * Whether this service should only be started when the device is unlocked.
- */
- private final boolean mRequiresDeviceUnlock;
-
- /**
- * Whether this service should only be started when the device is screen on.
- */
- private final boolean mRequiresDeviceScreenOn;
-
- /**
- * The id of the service banner specified in XML.
- */
- private final int mBannerResourceId;
-
- /**
- * The uid of the package the service belongs to
- */
- private final int mUid;
-
- /**
- * Settings Activity for this service
- */
- private final String mSettingsActivityName;
-
- /**
- * State of the service for CATEGORY_OTHER selection
- */
- private boolean mCategoryOtherServiceEnabled;
-
- /**
- * Whether the NFC stack should default to Observe Mode when this preferred service.
- */
- private boolean mShouldDefaultToObserveMode;
-
- /**
- * Whether or not this service wants to share the same routing priority as the
- * Wallet role owner.
- */
- private boolean mShareRolePriority;
-
- /**
- * @hide
- */
- @UnsupportedAppUsage
- public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, int bannerResource, int uid,
- String settingsActivityName, String offHost, String staticOffHost) {
- this(info, onHost, description, staticAidGroups, dynamicAidGroups,
- requiresUnlock, bannerResource, uid, settingsActivityName,
- offHost, staticOffHost, false);
- }
-
- /**
- * @hide
- */
- public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, int bannerResource, int uid,
- String settingsActivityName, String offHost, String staticOffHost,
- boolean isEnabled) {
- this(info, onHost, description, staticAidGroups, dynamicAidGroups,
- requiresUnlock, onHost ? true : false, bannerResource, uid,
- settingsActivityName, offHost, staticOffHost, isEnabled);
- }
-
- /**
- * @hide
- */
- public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
- String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled) {
- this(info, onHost, description, staticAidGroups, dynamicAidGroups,
- requiresUnlock, requiresScreenOn, bannerResource, uid,
- settingsActivityName, offHost, staticOffHost, isEnabled,
- new HashMap<String, Boolean>(), new TreeMap<>(
- Comparator.comparing(Pattern::toString)));
- }
-
- /**
- * @hide
- */
- public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- List<AidGroup> staticAidGroups, List<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
- String settingsActivityName, String offHost, String staticOffHost, boolean isEnabled,
- Map<String, Boolean> autoTransact, Map<Pattern, Boolean> autoTransactPatterns) {
- this.mService = info;
- this.mDescription = description;
- this.mStaticAidGroups = new HashMap<String, AidGroup>();
- this.mDynamicAidGroups = new HashMap<String, AidGroup>();
- this.mAutoTransact = autoTransact;
- this.mAutoTransactPatterns = autoTransactPatterns;
- this.mOffHostName = offHost;
- this.mStaticOffHostName = staticOffHost;
- this.mOnHost = onHost;
- this.mRequiresDeviceUnlock = requiresUnlock;
- this.mRequiresDeviceScreenOn = requiresScreenOn;
- for (AidGroup aidGroup : staticAidGroups) {
- this.mStaticAidGroups.put(aidGroup.getCategory(), aidGroup);
- }
- for (AidGroup aidGroup : dynamicAidGroups) {
- this.mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
- }
- this.mBannerResourceId = bannerResource;
- this.mUid = uid;
- this.mSettingsActivityName = settingsActivityName;
- this.mCategoryOtherServiceEnabled = isEnabled;
- }
-
- /**
- * Creates a new ApduServiceInfo object.
- *
- * @param pm packageManager instance
- * @param info app component info
- * @param onHost whether service is on host or not (secure element)
- * @throws XmlPullParserException If an error occurs parsing the element.
- * @throws IOException If an error occurs reading the element.
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public ApduServiceInfo(@NonNull PackageManager pm, @NonNull ResolveInfo info, boolean onHost)
- throws XmlPullParserException, IOException {
- ServiceInfo si = info.serviceInfo;
- XmlResourceParser parser = null;
- try {
- if (onHost) {
- parser = si.loadXmlMetaData(pm, HostApduService.SERVICE_META_DATA);
- if (parser == null) {
- throw new XmlPullParserException("No " + HostApduService.SERVICE_META_DATA +
- " meta-data");
- }
- } else {
- parser = si.loadXmlMetaData(pm, OffHostApduService.SERVICE_META_DATA);
- if (parser == null) {
- throw new XmlPullParserException("No " + OffHostApduService.SERVICE_META_DATA +
- " meta-data");
- }
- }
-
- int eventType = parser.getEventType();
- while (eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_DOCUMENT) {
- eventType = parser.next();
- }
-
- String tagName = parser.getName();
- if (onHost && !"host-apdu-service".equals(tagName)) {
- throw new XmlPullParserException(
- "Meta-data does not start with <host-apdu-service> tag");
- } else if (!onHost && !"offhost-apdu-service".equals(tagName)) {
- throw new XmlPullParserException(
- "Meta-data does not start with <offhost-apdu-service> tag");
- }
-
- Resources res = pm.getResourcesForApplication(si.applicationInfo);
- AttributeSet attrs = Xml.asAttributeSet(parser);
- if (onHost) {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.HostApduService);
- mService = info;
- mDescription = sa.getString(
- com.android.internal.R.styleable.HostApduService_description);
- mRequiresDeviceUnlock = sa.getBoolean(
- com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
- false);
- mRequiresDeviceScreenOn = sa.getBoolean(
- com.android.internal.R.styleable.HostApduService_requireDeviceScreenOn,
- true);
- mBannerResourceId = sa.getResourceId(
- com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
- mSettingsActivityName = sa.getString(
- com.android.internal.R.styleable.HostApduService_settingsActivity);
- mOffHostName = null;
- mStaticOffHostName = mOffHostName;
- mShouldDefaultToObserveMode = sa.getBoolean(
- R.styleable.HostApduService_shouldDefaultToObserveMode,
- false);
- if (Flags.nfcAssociatedRoleServices()) {
- mShareRolePriority = sa.getBoolean(
- R.styleable.HostApduService_shareRolePriority,
- false
- );
- }
- sa.recycle();
- } else {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.OffHostApduService);
- mService = info;
- mDescription = sa.getString(
- com.android.internal.R.styleable.OffHostApduService_description);
- mRequiresDeviceUnlock = sa.getBoolean(
- com.android.internal.R.styleable.OffHostApduService_requireDeviceUnlock,
- false);
- mRequiresDeviceScreenOn = sa.getBoolean(
- com.android.internal.R.styleable.OffHostApduService_requireDeviceScreenOn,
- false);
- mBannerResourceId = sa.getResourceId(
- com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
- mSettingsActivityName = sa.getString(
- com.android.internal.R.styleable.HostApduService_settingsActivity);
- mOffHostName = sa.getString(
- com.android.internal.R.styleable.OffHostApduService_secureElementName);
- mShouldDefaultToObserveMode = sa.getBoolean(
- R.styleable.OffHostApduService_shouldDefaultToObserveMode,
- false);
- if (mOffHostName != null) {
- if (mOffHostName.equals("eSE")) {
- mOffHostName = "eSE1";
- } else if (mOffHostName.equals("SIM")) {
- mOffHostName = "SIM1";
- }
- }
- mStaticOffHostName = mOffHostName;
- if (Flags.nfcAssociatedRoleServices()) {
- mShareRolePriority = sa.getBoolean(
- R.styleable.OffHostApduService_shareRolePriority,
- false
- );
- }
- sa.recycle();
- }
-
- mStaticAidGroups = new HashMap<String, AidGroup>();
- mDynamicAidGroups = new HashMap<String, AidGroup>();
- mAutoTransact = new HashMap<String, Boolean>();
- mAutoTransactPatterns = new TreeMap<Pattern, Boolean>(
- Comparator.comparing(Pattern::toString));
- mOnHost = onHost;
-
- final int depth = parser.getDepth();
- AidGroup currentGroup = null;
-
- // Parsed values for the current AID group
- while (((eventType = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && eventType != XmlPullParser.END_DOCUMENT) {
- tagName = parser.getName();
- if (eventType == XmlPullParser.START_TAG && "aid-group".equals(tagName) &&
- currentGroup == null) {
- final TypedArray groupAttrs = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AidGroup);
- // Get category of AID group
- String groupCategory = groupAttrs.getString(
- com.android.internal.R.styleable.AidGroup_category);
- String groupDescription = groupAttrs.getString(
- com.android.internal.R.styleable.AidGroup_description);
- if (!CardEmulation.CATEGORY_PAYMENT.equals(groupCategory)) {
- groupCategory = CardEmulation.CATEGORY_OTHER;
- }
- currentGroup = mStaticAidGroups.get(groupCategory);
- if (currentGroup != null) {
- if (!CardEmulation.CATEGORY_OTHER.equals(groupCategory)) {
- Log.e(TAG, "Not allowing multiple aid-groups in the " +
- groupCategory + " category");
- currentGroup = null;
- }
- } else {
- currentGroup = new AidGroup(groupCategory, groupDescription);
- }
- groupAttrs.recycle();
- } else if (eventType == XmlPullParser.END_TAG && "aid-group".equals(tagName) &&
- currentGroup != null) {
- if (currentGroup.getAids().size() > 0) {
- if (!mStaticAidGroups.containsKey(currentGroup.getCategory())) {
- mStaticAidGroups.put(currentGroup.getCategory(), currentGroup);
- }
- } else {
- Log.e(TAG, "Not adding <aid-group> with empty or invalid AIDs");
- }
- currentGroup = null;
- } else if (eventType == XmlPullParser.START_TAG && "aid-filter".equals(tagName) &&
- currentGroup != null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AidFilter);
- String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
- toUpperCase();
- if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
- currentGroup.getAids().add(aid);
- } else {
- Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG &&
- "aid-prefix-filter".equals(tagName) && currentGroup != null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AidFilter);
- String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
- toUpperCase();
- // Add wildcard char to indicate prefix
- aid = aid.concat("*");
- if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
- currentGroup.getAids().add(aid);
- } else {
- Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG &&
- tagName.equals("aid-suffix-filter") && currentGroup != null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AidFilter);
- String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
- toUpperCase();
- // Add wildcard char to indicate suffix
- aid = aid.concat("#");
- if (isValidAid(aid) && !currentGroup.getAids().contains(aid)) {
- currentGroup.getAids().add(aid);
- } else {
- Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG
- && "polling-loop-filter".equals(tagName) && currentGroup == null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.PollingLoopFilter);
- String plf =
- a.getString(com.android.internal.R.styleable.PollingLoopFilter_name)
- .toUpperCase(Locale.ROOT);
- boolean autoTransact = a.getBoolean(
- com.android.internal.R.styleable.PollingLoopFilter_autoTransact,
- false);
- if (!mOnHost && !autoTransact) {
- Log.e(TAG, "Ignoring polling-loop-filter " + plf
- + " for offhost service that isn't autoTransact");
- } else {
- mAutoTransact.put(plf, autoTransact);
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG
- && "polling-loop-pattern-filter".equals(tagName) && currentGroup == null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.PollingLoopPatternFilter);
- String plf = a.getString(
- com.android.internal.R.styleable.PollingLoopPatternFilter_name)
- .toUpperCase(Locale.ROOT);
- boolean autoTransact = a.getBoolean(
- com.android.internal.R.styleable.PollingLoopFilter_autoTransact,
- false);
- if (!mOnHost && !autoTransact) {
- Log.e(TAG, "Ignoring polling-loop-filter " + plf
- + " for offhost service that isn't autoTransact");
- } else {
- mAutoTransactPatterns.put(Pattern.compile(plf), autoTransact);
- }
- a.recycle();
- }
- }
- } catch (NameNotFoundException e) {
- throw new XmlPullParserException("Unable to create context for: " + si.packageName);
- } finally {
- if (parser != null) parser.close();
- }
- // Set uid
- mUid = si.applicationInfo.uid;
-
- mCategoryOtherServiceEnabled = true; // support other category
-
- }
-
- /**
- * Returns the app component corresponding to this APDU service.
- *
- * @return app component for this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public ComponentName getComponent() {
- return new ComponentName(mService.serviceInfo.packageName,
- mService.serviceInfo.name);
- }
-
- /**
- * Returns the offhost secure element name (if the service is offhost).
- *
- * @return offhost secure element name for offhost services
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Nullable
- public String getOffHostSecureElement() {
- return mOffHostName;
- }
-
- /**
- * Returns a consolidated list of AIDs from the AID groups
- * registered by this service. Note that if a service has both
- * a static (manifest-based) AID group for a category and a dynamic
- * AID group, only the dynamically registered AIDs will be returned
- * for that category.
- * @return List of AIDs registered by the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public List<String> getAids() {
- final ArrayList<String> aids = new ArrayList<String>();
- for (AidGroup group : getAidGroups()) {
- aids.addAll(group.getAids());
- }
- return aids;
- }
-
- /**
- * Returns the current polling loop filters for this service.
- * @return List of polling loop filters.
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- @NonNull
- public List<String> getPollingLoopFilters() {
- return new ArrayList<>(mAutoTransact.keySet());
- }
-
- /**
- * Returns whether this service would like to automatically transact for a given plf.
- *
- * @param plf the polling loop filter to query.
- * @return {@code true} indicating to auto transact, {@code false} indicating to not.
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public boolean getShouldAutoTransact(@NonNull String plf) {
- if (mAutoTransact.getOrDefault(plf.toUpperCase(Locale.ROOT), false)) {
- return true;
- }
- List<Pattern> patternMatches = mAutoTransactPatterns.keySet().stream()
- .filter(p -> p.matcher(plf).matches()).toList();
- if (patternMatches == null || patternMatches.size() == 0) {
- return false;
- }
- for (Pattern patternMatch : patternMatches) {
- if (mAutoTransactPatterns.get(patternMatch)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns the current polling loop pattern filters for this service.
- * @return List of polling loop pattern filters.
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- @NonNull
- public List<Pattern> getPollingLoopPatternFilters() {
- return new ArrayList<>(mAutoTransactPatterns.keySet());
- }
-
- /**
- * Returns a consolidated list of AIDs with prefixes from the AID groups
- * registered by this service. Note that if a service has both
- * a static (manifest-based) AID group for a category and a dynamic
- * AID group, only the dynamically registered AIDs will be returned
- * for that category.
- * @return List of prefix AIDs registered by the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public List<String> getPrefixAids() {
- final ArrayList<String> prefixAids = new ArrayList<String>();
- for (AidGroup group : getAidGroups()) {
- for (String aid : group.getAids()) {
- if (aid.endsWith("*")) {
- prefixAids.add(aid);
- }
- }
- }
- return prefixAids;
- }
-
- /**
- * Returns a consolidated list of AIDs with subsets from the AID groups
- * registered by this service. Note that if a service has both
- * a static (manifest-based) AID group for a category and a dynamic
- * AID group, only the dynamically registered AIDs will be returned
- * for that category.
- * @return List of prefix AIDs registered by the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public List<String> getSubsetAids() {
- final ArrayList<String> subsetAids = new ArrayList<String>();
- for (AidGroup group : getAidGroups()) {
- for (String aid : group.getAids()) {
- if (aid.endsWith("#")) {
- subsetAids.add(aid);
- }
- }
- }
- return subsetAids;
- }
-
- /**
- * Returns the registered AID group for this category.
- *
- * @param category category name
- * @return {@link AidGroup} instance for the provided category
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public AidGroup getDynamicAidGroupForCategory(@NonNull String category) {
- return mDynamicAidGroups.get(category);
- }
-
- /**
- * Removes the registered AID group for this category.
- *
- * @param category category name
- * @return {@code true} if an AID group existed
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public boolean removeDynamicAidGroupForCategory(@NonNull String category) {
- return (mDynamicAidGroups.remove(category) != null);
- }
-
- /**
- * Returns a consolidated list of AID groups
- * registered by this service. Note that if a service has both
- * a static (manifest-based) AID group for a category and a dynamic
- * AID group, only the dynamically registered AID group will be returned
- * for that category.
- * @return List of AIDs registered by the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public List<AidGroup> getAidGroups() {
- final ArrayList<AidGroup> groups = new ArrayList<AidGroup>();
- for (Map.Entry<String, AidGroup> entry : mDynamicAidGroups.entrySet()) {
- groups.add(entry.getValue());
- }
- for (Map.Entry<String, AidGroup> entry : mStaticAidGroups.entrySet()) {
- if (!mDynamicAidGroups.containsKey(entry.getKey())) {
- // Consolidate AID groups - don't return static ones
- // if a dynamic group exists for the category.
- groups.add(entry.getValue());
- }
- }
- return groups;
- }
-
- /**
- * Returns the category to which this service has attributed the AID that is passed in,
- * or null if we don't know this AID.
- * @param aid AID to lookup for
- * @return category name corresponding to this AID
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getCategoryForAid(@NonNull String aid) {
- List<AidGroup> groups = getAidGroups();
- for (AidGroup group : groups) {
- if (group.getAids().contains(aid.toUpperCase())) {
- return group.getCategory();
- }
- }
- return null;
- }
-
- /**
- * Returns whether there is any AID group for this category.
- * @param category category name
- * @return {@code true} if an AID group exists
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean hasCategory(@NonNull String category) {
- return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
- }
-
- /**
- * Returns whether the service is on host or not.
- * @return true if the service is on host (not secure element)
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean isOnHost() {
- return mOnHost;
- }
-
- /**
- * Returns whether the service requires device unlock.
- * @return whether the service requires device unlock
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean requiresUnlock() {
- return mRequiresDeviceUnlock;
- }
-
- /**
- * Returns whether this service should only be started when the device is screen on.
- * @return whether the service requires screen on
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean requiresScreenOn() {
- return mRequiresDeviceScreenOn;
- }
-
- /**
- * Returns whether the NFC stack should default to observe mode when this service is preferred.
- * @return whether the NFC stack should default to observe mode when this service is preferred
- */
- @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
- public boolean shouldDefaultToObserveMode() {
- return mShouldDefaultToObserveMode;
- }
-
- /**
- * Sets whether the NFC stack should default to observe mode when this service is preferred.
- * @param shouldDefaultToObserveMode whether the NFC stack should default to observe mode when
- * this service is preferred
- */
- @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
- public void setShouldDefaultToObserveMode(boolean shouldDefaultToObserveMode) {
- mShouldDefaultToObserveMode = shouldDefaultToObserveMode;
- }
-
- /**
- * Returns whether or not this service wants to share the Wallet role holder priority
- * with other packages/services with the same signature.
- *
- * @return whether or not this service wants to share priority
- */
- @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)
- public boolean shareRolePriority() {
- return mShareRolePriority;
- }
-
- /**
- * Returns description of service.
- * @return user readable description of service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getDescription() {
- return mDescription;
- }
-
- /**
- * Returns uid of service.
- * @return uid of the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public int getUid() {
- return mUid;
- }
-
- /**
- * Add or replace an AID group to this service.
- * @param aidGroup instance of aid group to set or replace
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setDynamicAidGroup(@NonNull AidGroup aidGroup) {
- mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
- }
-
- /**
- * Add a Polling Loop Filter. Custom NFC polling frames that match this filter will be
- * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this
- * multiple times will cause the value to be overwritten each time.
- * @param pollingLoopFilter the polling loop filter to add, must be a valid hexadecimal string
- * @param autoTransact when true, disable observe mode when this filter matches, when false,
- * matching does not change the observe mode state
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void addPollingLoopFilter(@NonNull String pollingLoopFilter,
- boolean autoTransact) {
- if (!mOnHost && !autoTransact) {
- return;
- }
- mAutoTransact.put(pollingLoopFilter, autoTransact);
- }
-
- /**
- * Remove a Polling Loop Filter. Custom NFC polling frames that match this filter will no
- * longer be delivered to {@link HostApduService#processPollingFrames(List)}.
- * @param pollingLoopFilter this polling loop filter to add.
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void removePollingLoopFilter(@NonNull String pollingLoopFilter) {
- mAutoTransact.remove(pollingLoopFilter.toUpperCase(Locale.ROOT));
- }
-
- /**
- * Add a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will be
- * delivered to {@link HostApduService#processPollingFrames(List)}. Adding a key with this
- * multiple times will cause the value to be overwritten each time.
- * @param pollingLoopPatternFilter the polling loop pattern filter to add, must be a valid
- * regex to match a hexadecimal string
- * @param autoTransact when true, disable observe mode when this filter matches, when false,
- * matching does not change the observe mode state
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void addPollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter,
- boolean autoTransact) {
- if (!mOnHost && !autoTransact) {
- return;
- }
- mAutoTransactPatterns.put(Pattern.compile(pollingLoopPatternFilter), autoTransact);
- }
-
- /**
- * Remove a Polling Loop Pattern Filter. Custom NFC polling frames that match this filter will
- * no longer be delivered to {@link HostApduService#processPollingFrames(List)}.
- * @param pollingLoopPatternFilter this polling loop filter to add.
- */
- @FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP)
- public void removePollingLoopPatternFilter(@NonNull String pollingLoopPatternFilter) {
- mAutoTransactPatterns.remove(
- Pattern.compile(pollingLoopPatternFilter.toUpperCase(Locale.ROOT)));
- }
-
- /**
- * Sets the off host Secure Element.
- * @param offHost Secure Element to set. Only accept strings with prefix SIM or prefix eSE.
- * Ref: GSMA TS.26 - NFC Handset Requirements
- * TS26_NFC_REQ_069: For UICC, Secure Element Name SHALL be SIM[smartcard slot]
- * (e.g. SIM/SIM1, SIM2… SIMn).
- * TS26_NFC_REQ_070: For embedded SE, Secure Element Name SHALL be eSE[number]
- * (e.g. eSE/eSE1, eSE2, etc.).
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setOffHostSecureElement(@NonNull String offHost) {
- mOffHostName = offHost;
- }
-
- /**
- * Resets the off host Secure Element to statically defined
- * by the service in the manifest file.
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void resetOffHostSecureElement() {
- mOffHostName = mStaticOffHostName;
- }
-
- /**
- * Load label for this service.
- * @param pm packagemanager instance
- * @return label name corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public CharSequence loadLabel(@NonNull PackageManager pm) {
- return mService.loadLabel(pm);
- }
-
- /**
- * Load application label for this service.
- * @param pm packagemanager instance
- * @return app label name corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public CharSequence loadAppLabel(@NonNull PackageManager pm) {
- try {
- return pm.getApplicationLabel(pm.getApplicationInfo(
- mService.resolvePackageName, PackageManager.GET_META_DATA));
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
- }
-
- /**
- * Load application icon for this service.
- * @param pm packagemanager instance
- * @return app icon corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public Drawable loadIcon(@NonNull PackageManager pm) {
- return mService.loadIcon(pm);
- }
-
- /**
- * Load application banner for this service.
- * @param pm packagemanager instance
- * @return app banner corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public Drawable loadBanner(@NonNull PackageManager pm) {
- Resources res;
- try {
- res = pm.getResourcesForApplication(mService.serviceInfo.packageName);
- Drawable banner = res.getDrawable(mBannerResourceId);
- return banner;
- } catch (NotFoundException e) {
- Log.e(TAG, "Could not load banner.");
- return null;
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Could not load banner.");
- return null;
- }
- }
-
- /**
- * Load activity name for this service.
- * @return activity name for this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getSettingsActivityName() { return mSettingsActivityName; }
-
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder("ApduService: ");
- out.append(getComponent());
- out.append(", UID: " + mUid);
- out.append(", description: " + mDescription);
- out.append(", Static AID Groups: ");
- for (AidGroup aidGroup : mStaticAidGroups.values()) {
- out.append(aidGroup.toString());
- }
- out.append(", Dynamic AID Groups: ");
- for (AidGroup aidGroup : mDynamicAidGroups.values()) {
- out.append(aidGroup.toString());
- }
- return out.toString();
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) return true;
- if (!(o instanceof ApduServiceInfo)) return false;
- ApduServiceInfo thatService = (ApduServiceInfo) o;
-
- return thatService.getComponent().equals(this.getComponent())
- && thatService.getUid() == this.getUid();
- }
-
- @Override
- public int hashCode() {
- return getComponent().hashCode();
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public int describeContents() {
- return 0;
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- mService.writeToParcel(dest, flags);
- dest.writeString(mDescription);
- dest.writeInt(mOnHost ? 1 : 0);
- dest.writeString(mOffHostName);
- dest.writeString(mStaticOffHostName);
- dest.writeInt(mStaticAidGroups.size());
- if (mStaticAidGroups.size() > 0) {
- dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values()));
- }
- dest.writeInt(mDynamicAidGroups.size());
- if (mDynamicAidGroups.size() > 0) {
- dest.writeTypedList(new ArrayList<AidGroup>(mDynamicAidGroups.values()));
- }
- dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
- dest.writeInt(mRequiresDeviceScreenOn ? 1 : 0);
- dest.writeInt(mBannerResourceId);
- dest.writeInt(mUid);
- dest.writeString(mSettingsActivityName);
-
- dest.writeInt(mCategoryOtherServiceEnabled ? 1 : 0);
- dest.writeInt(mAutoTransact.size());
- dest.writeMap(mAutoTransact);
- dest.writeInt(mAutoTransactPatterns.size());
- dest.writeMap(mAutoTransactPatterns);
- };
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public static final @NonNull Parcelable.Creator<ApduServiceInfo> CREATOR =
- new Parcelable.Creator<ApduServiceInfo>() {
- @Override
- public ApduServiceInfo createFromParcel(Parcel source) {
- ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
- String description = source.readString();
- boolean onHost = source.readInt() != 0;
- String offHostName = source.readString();
- String staticOffHostName = source.readString();
- ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
- int numStaticGroups = source.readInt();
- if (numStaticGroups > 0) {
- source.readTypedList(staticAidGroups, AidGroup.CREATOR);
- }
- ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
- int numDynamicGroups = source.readInt();
- if (numDynamicGroups > 0) {
- source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
- }
- boolean requiresUnlock = source.readInt() != 0;
- boolean requiresScreenOn = source.readInt() != 0;
- int bannerResource = source.readInt();
- int uid = source.readInt();
- String settingsActivityName = source.readString();
- boolean isEnabled = source.readInt() != 0;
- int autoTransactSize = source.readInt();
- HashMap<String, Boolean> autoTransact =
- new HashMap<String, Boolean>(autoTransactSize);
- source.readMap(autoTransact, getClass().getClassLoader(),
- String.class, Boolean.class);
- int autoTransactPatternSize = source.readInt();
- HashMap<Pattern, Boolean> autoTransactPatterns =
- new HashMap<Pattern, Boolean>(autoTransactSize);
- source.readMap(autoTransactPatterns, getClass().getClassLoader(),
- Pattern.class, Boolean.class);
- return new ApduServiceInfo(info, onHost, description, staticAidGroups,
- dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid,
- settingsActivityName, offHostName, staticOffHostName,
- isEnabled, autoTransact, autoTransactPatterns);
- }
-
- @Override
- public ApduServiceInfo[] newArray(int size) {
- return new ApduServiceInfo[size];
- }
- };
-
- /**
- * Dump contents for debugging.
- * @param fd parcelfiledescriptor instance
- * @param pw printwriter instance
- * @param args args for dumping
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
- @NonNull String[] args) {
- pw.println(" " + getComponent()
- + " (Description: " + getDescription() + ")"
- + " (UID: " + getUid() + ")");
- if (mOnHost) {
- pw.println(" On Host Service");
- } else {
- pw.println(" Off-host Service");
- pw.println(" " + "Current off-host SE:" + mOffHostName
- + " static off-host SE:" + mStaticOffHostName);
- }
- pw.println(" Static AID groups:");
- for (AidGroup group : mStaticAidGroups.values()) {
- pw.println(" Category: " + group.getCategory()
- + "(enabled: " + mCategoryOtherServiceEnabled + ")");
- for (String aid : group.getAids()) {
- pw.println(" AID: " + aid);
- }
- }
- pw.println(" Dynamic AID groups:");
- for (AidGroup group : mDynamicAidGroups.values()) {
- pw.println(" Category: " + group.getCategory()
- + "(enabled: " + mCategoryOtherServiceEnabled + ")");
- for (String aid : group.getAids()) {
- pw.println(" AID: " + aid);
- }
- }
- pw.println(" Settings Activity: " + mSettingsActivityName);
- pw.println(" Requires Device Unlock: " + mRequiresDeviceUnlock);
- pw.println(" Requires Device ScreenOn: " + mRequiresDeviceScreenOn);
- pw.println(" Should Default to Observe Mode: " + mShouldDefaultToObserveMode);
- pw.println(" Auto-Transact Mapping: " + mAutoTransact);
- pw.println(" Auto-Transact Patterns: " + mAutoTransactPatterns);
- }
-
-
- /**
- * Enable or disable this CATEGORY_OTHER service.
- *
- * @param enabled true to indicate if user has enabled this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setCategoryOtherServiceEnabled(boolean enabled) {
- mCategoryOtherServiceEnabled = enabled;
- }
-
-
- /**
- * Returns whether this CATEGORY_OTHER service is enabled or not.
- *
- * @return true to indicate if user has enabled this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public boolean isCategoryOtherServiceEnabled() {
- return mCategoryOtherServiceEnabled;
- }
-
- /**
- * Dump debugging info as ApduServiceInfoProto.
- *
- * If the output belongs to a sub message, the caller is responsible for wrapping this function
- * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
- * See proto definition in frameworks/base/core/proto/android/nfc/apdu_service_info.proto
- *
- * @param proto the ProtoOutputStream to write to
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void dumpDebug(@NonNull ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
- proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
- proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
- if (!mOnHost) {
- proto.write(ApduServiceInfoProto.OFF_HOST_NAME, mOffHostName);
- proto.write(ApduServiceInfoProto.STATIC_OFF_HOST_NAME, mStaticOffHostName);
- }
- for (AidGroup group : mStaticAidGroups.values()) {
- long token = proto.start(ApduServiceInfoProto.STATIC_AID_GROUPS);
- group.dump(proto);
- proto.end(token);
- }
- for (AidGroup group : mDynamicAidGroups.values()) {
- long token = proto.start(ApduServiceInfoProto.STATIC_AID_GROUPS);
- group.dump(proto);
- proto.end(token);
- }
- proto.write(ApduServiceInfoProto.SETTINGS_ACTIVITY_NAME, mSettingsActivityName);
- proto.write(ApduServiceInfoProto.SHOULD_DEFAULT_TO_OBSERVE_MODE,
- mShouldDefaultToObserveMode);
- {
- long token = proto.start(ApduServiceInfoProto.AUTO_TRANSACT_MAPPING);
- for (Map.Entry<String, Boolean> entry : mAutoTransact.entrySet()) {
- proto.write(ApduServiceInfoProto.AutoTransactMapping.AID, entry.getKey());
- proto.write(ApduServiceInfoProto.AutoTransactMapping.SHOULD_AUTO_TRANSACT,
- entry.getValue());
- }
- proto.end(token);
- }
- {
- long token = proto.start(ApduServiceInfoProto.AUTO_TRANSACT_PATTERNS);
- for (Map.Entry<Pattern, Boolean> entry : mAutoTransactPatterns.entrySet()) {
- proto.write(ApduServiceInfoProto.AutoTransactPattern.REGEXP_PATTERN,
- entry.getKey().pattern());
- proto.write(ApduServiceInfoProto.AutoTransactPattern.SHOULD_AUTO_TRANSACT,
- entry.getValue());
- }
- proto.end(token);
- }
- }
-
- private static final Pattern AID_PATTERN = Pattern.compile("[0-9A-Fa-f]{10,32}\\*?\\#?");
- /**
- * Copied over from {@link CardEmulation#isValidAid(String)}
- * @hide
- */
- private static boolean isValidAid(String aid) {
- if (aid == null)
- return false;
-
- // If a prefix/subset AID, the total length must be odd (even # of AID chars + '*')
- if ((aid.endsWith("*") || aid.endsWith("#")) && ((aid.length() % 2) == 0)) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- // If not a prefix/subset AID, the total length must be even (even # of AID chars)
- if ((!(aid.endsWith("*") || aid.endsWith("#"))) && ((aid.length() % 2) != 0)) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- // Verify hex characters
- if (!AID_PATTERN.matcher(aid).matches()) {
- Log.e(TAG, "AID " + aid + " is not a valid AID.");
- return false;
- }
-
- return true;
- }
-}
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.aidl b/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.aidl
deleted file mode 100644
index 56b98ebd90fa..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2015 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.cardemulation;
-
-parcelable NfcFServiceInfo;
diff --git a/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.java b/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.java
deleted file mode 100644
index 33bc16978721..000000000000
--- a/nfc-non-updatable/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-
-/**********************************************************************
- * This file is not a part of the NFC mainline module *
- * *******************************************************************/
-
-package android.nfc.cardemulation;
-
-import android.annotation.FlaggedApi;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.SystemApi;
-import android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.graphics.drawable.Drawable;
-import android.nfc.Flags;
-import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Xml;
-import android.util.proto.ProtoOutputStream;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-/**
- * Class to hold NfcF service info.
- *
- * @hide
- */
-@SystemApi
-@FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
-public final class NfcFServiceInfo implements Parcelable {
- static final String TAG = "NfcFServiceInfo";
-
- private static final String DEFAULT_T3T_PMM = "FFFFFFFFFFFFFFFF";
-
- /**
- * The service that implements this
- */
- private final ResolveInfo mService;
-
- /**
- * Description of the service
- */
- private final String mDescription;
-
- /**
- * System Code of the service
- */
- private final String mSystemCode;
-
- /**
- * System Code of the service registered by API
- */
- private String mDynamicSystemCode;
-
- /**
- * NFCID2 of the service
- */
- private final String mNfcid2;
-
- /**
- * NFCID2 of the service registered by API
- */
- private String mDynamicNfcid2;
-
- /**
- * The uid of the package the service belongs to
- */
- private final int mUid;
-
- /**
- * LF_T3T_PMM of the service
- */
- private final String mT3tPmm;
-
- /**
- * @hide
- */
- public NfcFServiceInfo(ResolveInfo info, String description,
- String systemCode, String dynamicSystemCode, String nfcid2, String dynamicNfcid2,
- int uid, String t3tPmm) {
- this.mService = info;
- this.mDescription = description;
- this.mSystemCode = systemCode;
- this.mDynamicSystemCode = dynamicSystemCode;
- this.mNfcid2 = nfcid2;
- this.mDynamicNfcid2 = dynamicNfcid2;
- this.mUid = uid;
- this.mT3tPmm = t3tPmm;
- }
-
- /**
- * Creates a new NfcFServiceInfo object.
- *
- * @param pm packageManager instance
- * @param info app component info
- * @throws XmlPullParserException If an error occurs parsing the element.
- * @throws IOException If an error occurs reading the element.
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public NfcFServiceInfo(@NonNull PackageManager pm, @NonNull ResolveInfo info)
- throws XmlPullParserException, IOException {
- ServiceInfo si = info.serviceInfo;
- XmlResourceParser parser = null;
- try {
- parser = si.loadXmlMetaData(pm, HostNfcFService.SERVICE_META_DATA);
- if (parser == null) {
- throw new XmlPullParserException("No " + HostNfcFService.SERVICE_META_DATA +
- " meta-data");
- }
-
- int eventType = parser.getEventType();
- while (eventType != XmlPullParser.START_TAG &&
- eventType != XmlPullParser.END_DOCUMENT) {
- eventType = parser.next();
- }
-
- String tagName = parser.getName();
- if (!"host-nfcf-service".equals(tagName)) {
- throw new XmlPullParserException(
- "Meta-data does not start with <host-nfcf-service> tag");
- }
-
- Resources res = pm.getResourcesForApplication(si.applicationInfo);
- AttributeSet attrs = Xml.asAttributeSet(parser);
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.HostNfcFService);
- mService = info;
- mDescription = sa.getString(
- com.android.internal.R.styleable.HostNfcFService_description);
- mDynamicSystemCode = null;
- mDynamicNfcid2 = null;
- sa.recycle();
-
- String systemCode = null;
- String nfcid2 = null;
- String t3tPmm = null;
- final int depth = parser.getDepth();
-
- while (((eventType = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > depth) && eventType != XmlPullParser.END_DOCUMENT) {
- tagName = parser.getName();
- if (eventType == XmlPullParser.START_TAG &&
- "system-code-filter".equals(tagName) && systemCode == null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.SystemCodeFilter);
- systemCode = a.getString(
- com.android.internal.R.styleable.SystemCodeFilter_name).toUpperCase();
- if (!isValidSystemCode(systemCode) &&
- !systemCode.equalsIgnoreCase("NULL")) {
- Log.e(TAG, "Invalid System Code: " + systemCode);
- systemCode = null;
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG &&
- "nfcid2-filter".equals(tagName) && nfcid2 == null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.Nfcid2Filter);
- nfcid2 = a.getString(
- com.android.internal.R.styleable.Nfcid2Filter_name).toUpperCase();
- if (!nfcid2.equalsIgnoreCase("RANDOM") &&
- !nfcid2.equalsIgnoreCase("NULL") &&
- !isValidNfcid2(nfcid2)) {
- Log.e(TAG, "Invalid NFCID2: " + nfcid2);
- nfcid2 = null;
- }
- a.recycle();
- } else if (eventType == XmlPullParser.START_TAG && tagName.equals("t3tPmm-filter")
- && t3tPmm == null) {
- final TypedArray a = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.T3tPmmFilter);
- t3tPmm = a.getString(
- com.android.internal.R.styleable.T3tPmmFilter_name).toUpperCase();
- a.recycle();
- }
- }
- mSystemCode = (systemCode == null ? "NULL" : systemCode);
- mNfcid2 = (nfcid2 == null ? "NULL" : nfcid2);
- mT3tPmm = (t3tPmm == null ? DEFAULT_T3T_PMM : t3tPmm);
- } catch (NameNotFoundException e) {
- throw new XmlPullParserException("Unable to create context for: " + si.packageName);
- } finally {
- if (parser != null) parser.close();
- }
- // Set uid
- mUid = si.applicationInfo.uid;
- }
-
- /**
- * Returns the app component corresponding to this NFCF service.
- *
- * @return app component for this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public ComponentName getComponent() {
- return new ComponentName(mService.serviceInfo.packageName,
- mService.serviceInfo.name);
- }
-
- /**
- * Returns the system code corresponding to this service.
- *
- * @return system code for this service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getSystemCode() {
- return (mDynamicSystemCode == null ? mSystemCode : mDynamicSystemCode);
- }
-
- /**
- * Add or replace a system code to this service.
- * @param systemCode system code to set or replace
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setDynamicSystemCode(@NonNull String systemCode) {
- mDynamicSystemCode = systemCode;
- }
-
- /**
- * Returns NFC ID2.
- *
- * @return nfc id2 to return
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getNfcid2() {
- return (mDynamicNfcid2 == null ? mNfcid2 : mDynamicNfcid2);
- }
-
- /**
- * Set or replace NFC ID2
- *
- * @param nfcid2 NFC ID2 string
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void setDynamicNfcid2(@NonNull String nfcid2) {
- mDynamicNfcid2 = nfcid2;
- }
-
- /**
- * Returns description of service.
- * @return user readable description of service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getDescription() {
- return mDescription;
- }
-
- /**
- * Returns uid of service.
- * @return uid of the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public int getUid() {
- return mUid;
- }
-
- /**
- * Returns LF_T3T_PMM of the service
- * @return returns LF_T3T_PMM of the service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public String getT3tPmm() {
- return mT3tPmm;
- }
-
- /**
- * Load application label for this service.
- * @param pm packagemanager instance
- * @return label name corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public CharSequence loadLabel(@NonNull PackageManager pm) {
- return mService.loadLabel(pm);
- }
-
- /**
- * Load application icon for this service.
- * @param pm packagemanager instance
- * @return app icon corresponding to service
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @NonNull
- public Drawable loadIcon(@NonNull PackageManager pm) {
- return mService.loadIcon(pm);
- }
-
- @Override
- public String toString() {
- StringBuilder out = new StringBuilder("NfcFService: ");
- out.append(getComponent());
- out.append(", UID: " + mUid);
- out.append(", description: " + mDescription);
- out.append(", System Code: " + mSystemCode);
- if (mDynamicSystemCode != null) {
- out.append(", dynamic System Code: " + mDynamicSystemCode);
- }
- out.append(", NFCID2: " + mNfcid2);
- if (mDynamicNfcid2 != null) {
- out.append(", dynamic NFCID2: " + mDynamicNfcid2);
- }
- out.append(", T3T PMM:" + mT3tPmm);
- return out.toString();
- }
-
- @Override
- public boolean equals(@Nullable Object o) {
- if (this == o) return true;
- if (!(o instanceof NfcFServiceInfo)) return false;
- NfcFServiceInfo thatService = (NfcFServiceInfo) o;
-
- if (!thatService.getComponent().equals(this.getComponent())) return false;
- if (thatService.getUid() != this.getUid()) return false;
- if (!thatService.mSystemCode.equalsIgnoreCase(this.mSystemCode)) return false;
- if (!thatService.mNfcid2.equalsIgnoreCase(this.mNfcid2)) return false;
- if (!thatService.mT3tPmm.equalsIgnoreCase(this.mT3tPmm)) return false;
- return true;
- }
-
- @Override
- public int hashCode() {
- return getComponent().hashCode();
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public int describeContents() {
- return 0;
- }
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- mService.writeToParcel(dest, flags);
- dest.writeString(mDescription);
- dest.writeString(mSystemCode);
- dest.writeInt(mDynamicSystemCode != null ? 1 : 0);
- if (mDynamicSystemCode != null) {
- dest.writeString(mDynamicSystemCode);
- }
- dest.writeString(mNfcid2);
- dest.writeInt(mDynamicNfcid2 != null ? 1 : 0);
- if (mDynamicNfcid2 != null) {
- dest.writeString(mDynamicNfcid2);
- }
- dest.writeInt(mUid);
- dest.writeString(mT3tPmm);
- };
-
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public static final @NonNull Parcelable.Creator<NfcFServiceInfo> CREATOR =
- new Parcelable.Creator<NfcFServiceInfo>() {
- @Override
- public NfcFServiceInfo createFromParcel(Parcel source) {
- ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
- String description = source.readString();
- String systemCode = source.readString();
- String dynamicSystemCode = null;
- if (source.readInt() != 0) {
- dynamicSystemCode = source.readString();
- }
- String nfcid2 = source.readString();
- String dynamicNfcid2 = null;
- if (source.readInt() != 0) {
- dynamicNfcid2 = source.readString();
- }
- int uid = source.readInt();
- String t3tPmm = source.readString();
- NfcFServiceInfo service = new NfcFServiceInfo(info, description,
- systemCode, dynamicSystemCode, nfcid2, dynamicNfcid2, uid, t3tPmm);
- return service;
- }
-
- @Override
- public NfcFServiceInfo[] newArray(int size) {
- return new NfcFServiceInfo[size];
- }
- };
-
- /**
- * Dump contents of the service for debugging.
- * @param fd parcelfiledescriptor instance
- * @param pw printwriter instance
- * @param args args for dumping
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void dump(@NonNull ParcelFileDescriptor fd, @NonNull PrintWriter pw,
- @NonNull String[] args) {
- pw.println(" " + getComponent()
- + " (Description: " + getDescription() + ")"
- + " (UID: " + getUid() + ")");
- pw.println(" System Code: " + getSystemCode());
- pw.println(" NFCID2: " + getNfcid2());
- pw.println(" T3tPmm: " + getT3tPmm());
- }
-
- /**
- * Dump debugging info as NfcFServiceInfoProto.
- *
- * If the output belongs to a sub message, the caller is responsible for wrapping this function
- * between {@link ProtoOutputStream#start(long)} and {@link ProtoOutputStream#end(long)}.
- *
- * @param proto the ProtoOutputStream to write to
- */
- @FlaggedApi(Flags.FLAG_ENABLE_NFC_MAINLINE)
- public void dumpDebug(@NonNull ProtoOutputStream proto) {
- getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
- proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
- proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
- proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
- proto.write(NfcFServiceInfoProto.T3T_PMM, getT3tPmm());
- }
-
- /**
- * Copied over from {@link NfcFCardEmulation#isValidSystemCode(String)}
- * @hide
- */
- private static boolean isValidSystemCode(String systemCode) {
- if (systemCode == null) {
- return false;
- }
- if (systemCode.length() != 4) {
- Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
- return false;
- }
- // check if the value is between "4000" and "4FFF" (excluding "4*FF")
- if (!systemCode.startsWith("4") || systemCode.toUpperCase().endsWith("FF")) {
- Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
- return false;
- }
- try {
- Integer.parseInt(systemCode, 16);
- } catch (NumberFormatException e) {
- Log.e(TAG, "System Code " + systemCode + " is not a valid System Code.");
- return false;
- }
- return true;
- }
-
- /**
- * Copied over from {@link NfcFCardEmulation#isValidNfcid2(String)}
- * @hide
- */
- private static boolean isValidNfcid2(String nfcid2) {
- if (nfcid2 == null) {
- return false;
- }
- if (nfcid2.length() != 16) {
- Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
- return false;
- }
- // check if the the value starts with "02FE"
- if (!nfcid2.toUpperCase().startsWith("02FE")) {
- Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
- return false;
- }
- try {
- Long.parseLong(nfcid2, 16);
- } catch (NumberFormatException e) {
- Log.e(TAG, "NFCID2 " + nfcid2 + " is not a valid NFCID2.");
- return false;
- }
- return true;
- }
-}