From ecdc6a3e7d109ce2a11027adeba510ca40968324 Mon Sep 17 00:00:00 2001 From: Alisher Alikhodjaev Date: Sat, 1 Oct 2022 12:15:19 -0700 Subject: [PATCH 1/2] Get PackageManager from Context The ActiveThread.getPackageManager() is a hidden API Bug: 244264995 Test: build ok Change-Id: Ie0606e5dc2e3eb6e24694ff280aa234fd1a79bcb --- core/java/android/nfc/NfcAdapter.java | 105 ++++-------------- .../nfc/cardemulation/CardEmulation.java | 13 +-- .../nfc/cardemulation/NfcFCardEmulation.java | 13 +-- 3 files changed, 29 insertions(+), 102 deletions(-) diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 64c1211949321..c38626cf67dd5 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -29,7 +29,6 @@ import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.IntentFilter; -import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.net.Uri; import android.nfc.tech.MifareClassic; @@ -524,66 +523,6 @@ public final class NfcAdapter { public boolean onUnlockAttempted(Tag tag); } - /** - * Helper to check if this device has FEATURE_NFC_BEAM, but without using - * a context. - * Equivalent to - * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC_BEAM) - */ - private static boolean hasBeamFeature() { - IPackageManager pm = ActivityThread.getPackageManager(); - if (pm == null) { - Log.e(TAG, "Cannot get package manager, assuming no Android Beam feature"); - return false; - } - try { - return pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM, 0); - } catch (RemoteException e) { - Log.e(TAG, "Package manager query failed, assuming no Android Beam feature", e); - return false; - } - } - - /** - * Helper to check if this device has FEATURE_NFC, but without using - * a context. - * Equivalent to - * context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC) - */ - private static boolean hasNfcFeature() { - IPackageManager pm = ActivityThread.getPackageManager(); - if (pm == null) { - Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); - return false; - } - try { - return pm.hasSystemFeature(PackageManager.FEATURE_NFC, 0); - } catch (RemoteException e) { - Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); - return false; - } - } - - /** - * Helper to check if this device is NFC HCE capable, by checking for - * FEATURE_NFC_HOST_CARD_EMULATION and/or FEATURE_NFC_HOST_CARD_EMULATION_NFCF, - * but without using a context. - */ - private static boolean hasNfcHceFeature() { - IPackageManager pm = ActivityThread.getPackageManager(); - if (pm == null) { - Log.e(TAG, "Cannot get package manager, assuming no NFC feature"); - return false; - } - try { - return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0) - || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0); - } catch (RemoteException e) { - Log.e(TAG, "Package manager query failed, assuming no NFC feature", e); - return false; - } - } - /** * Return list of Secure Elements which support off host card emulation. * @@ -593,23 +532,21 @@ public final class NfcAdapter { * @hide */ public @NonNull List getSupportedOffHostSecureElements() { + if (mContext == null) { + throw new UnsupportedOperationException("You need a context on NfcAdapter to use the " + + " getSupportedOffHostSecureElements APIs"); + } List offHostSE = new ArrayList(); - IPackageManager pm = ActivityThread.getPackageManager(); + PackageManager pm = mContext.getPackageManager(); if (pm == null) { Log.e(TAG, "Cannot get package manager, assuming no off-host CE feature"); return offHostSE; } - try { - if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC, 0)) { - offHostSE.add("SIM"); - } - if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE, 0)) { - offHostSE.add("eSE"); - } - } catch (RemoteException e) { - Log.e(TAG, "Package manager query failed, assuming no off-host CE feature", e); - offHostSE.clear(); - return offHostSE; + if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)) { + offHostSE.add("SIM"); + } + if (pm.hasSystemFeature(PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE)) { + offHostSE.add("eSE"); } return offHostSE; } @@ -621,10 +558,20 @@ public final class NfcAdapter { */ @UnsupportedAppUsage public static synchronized NfcAdapter getNfcAdapter(Context context) { + if (context == null) { + if (sNullContextNfcAdapter == null) { + sNullContextNfcAdapter = new NfcAdapter(null); + } + return sNullContextNfcAdapter; + } if (!sIsInitialized) { - sHasNfcFeature = hasNfcFeature(); - sHasBeamFeature = hasBeamFeature(); - boolean hasHceFeature = hasNfcHceFeature(); + PackageManager pm; + pm = context.getPackageManager(); + sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC); + sHasBeamFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM); + boolean hasHceFeature = + pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) + || pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF); /* is this device meant to have NFC */ if (!sHasNfcFeature && !hasHceFeature) { Log.v(TAG, "this device does not have NFC support"); @@ -660,12 +607,6 @@ public final class NfcAdapter { sIsInitialized = true; } - if (context == null) { - if (sNullContextNfcAdapter == null) { - sNullContextNfcAdapter = new NfcAdapter(null); - } - return sNullContextNfcAdapter; - } NfcAdapter adapter = sNfcAdapters.get(context); if (adapter == null) { adapter = new NfcAdapter(context); diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 0b56d19201fbc..6a4209135c66d 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -22,11 +22,9 @@ import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Activity; -import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.nfc.INfcCardEmulation; import android.nfc.NfcAdapter; @@ -158,18 +156,13 @@ public final class CardEmulation { throw new UnsupportedOperationException(); } if (!sIsInitialized) { - IPackageManager pm = ActivityThread.getPackageManager(); + PackageManager pm = context.getPackageManager(); if (pm == null) { Log.e(TAG, "Cannot get PackageManager"); throw new UnsupportedOperationException(); } - try { - if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION, 0)) { - Log.e(TAG, "This device does not support card emulation"); - throw new UnsupportedOperationException(); - } - } catch (RemoteException e) { - Log.e(TAG, "PackageManager query failed."); + if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { + Log.e(TAG, "This device does not support card emulation"); throw new UnsupportedOperationException(); } sIsInitialized = true; diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java index 3c924556365e3..48bbf5b610520 100644 --- a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java +++ b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java @@ -17,10 +17,8 @@ package android.nfc.cardemulation; import android.app.Activity; -import android.app.ActivityThread; import android.content.ComponentName; import android.content.Context; -import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.nfc.INfcFCardEmulation; import android.nfc.NfcAdapter; @@ -70,18 +68,13 @@ public final class NfcFCardEmulation { throw new UnsupportedOperationException(); } if (!sIsInitialized) { - IPackageManager pm = ActivityThread.getPackageManager(); + PackageManager pm = context.getPackageManager(); if (pm == null) { Log.e(TAG, "Cannot get PackageManager"); throw new UnsupportedOperationException(); } - try { - if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF, 0)) { - Log.e(TAG, "This device does not support NFC-F card emulation"); - throw new UnsupportedOperationException(); - } - } catch (RemoteException e) { - Log.e(TAG, "PackageManager query failed."); + if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF)) { + Log.e(TAG, "This device does not support NFC-F card emulation"); throw new UnsupportedOperationException(); } sIsInitialized = true; From a8c470fb712a05252755d5df0eb02370fc249148 Mon Sep 17 00:00:00 2001 From: Alisher Alikhodjaev Date: Mon, 7 Nov 2022 15:53:22 -0800 Subject: [PATCH 2/2] Use waitForService() istead of getService() SystemManager.waitForService() is a system interface Bug: 244264995 Test: read a tag, on/off Change-Id: Ifcde87f4021238b4ebc67466f2d9b2e363586707 --- core/java/android/nfc/NfcAdapter.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index c38626cf67dd5..3282d567d369f 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -565,8 +565,7 @@ public final class NfcAdapter { return sNullContextNfcAdapter; } if (!sIsInitialized) { - PackageManager pm; - pm = context.getPackageManager(); + PackageManager pm = context.getPackageManager(); sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC); sHasBeamFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM); boolean hasHceFeature = @@ -617,8 +616,12 @@ public final class NfcAdapter { /** get handle to NFC service interface */ private static INfcAdapter getServiceInterface() { + if (!sHasNfcFeature) { + /* NFC is not supported */ + return null; + } /* get a handle to NFC service */ - IBinder b = ServiceManager.getService("nfc"); + IBinder b = ServiceManager.waitForService("nfc"); if (b == null) { return null; } @@ -648,6 +651,15 @@ public final class NfcAdapter { "context not associated with any application (using a mock context?)"); } + synchronized (NfcAdapter.class) { + if (!sIsInitialized) { + PackageManager pm = context.getPackageManager(); + sHasNfcFeature = pm.hasSystemFeature(PackageManager.FEATURE_NFC); + } + if (!sHasNfcFeature) { + return null; + } + } if (getServiceInterface() == null) { // NFC is not available return null;