Merge "Call OffHostAidSelected only when RF_NFCEE_ACTION_NTF is triggered with AID" into main
diff --git a/NfcNci/nci/jni/NativeNfcManager.cpp b/NfcNci/nci/jni/NativeNfcManager.cpp
index 1bb5d86..6d4ce1d 100644
--- a/NfcNci/nci/jni/NativeNfcManager.cpp
+++ b/NfcNci/nci/jni/NativeNfcManager.cpp
@@ -151,7 +151,7 @@
static bool sIsNfaEnabled = false;
static bool sDiscoveryEnabled = false; // is polling or listening
static bool sPollingEnabled = false; // is polling for tag?
-static bool sIsDisabling = false;
+bool sIsDisabling = false;
static bool sRfEnabled = false; // whether RF discovery is enabled
static bool sSeRfActive = false; // whether RF with SE is likely active
static bool sReaderModeEnabled = false; // whether we're only reading tags, not allowing card emu
@@ -1787,28 +1787,22 @@
}
static tNFA_STATUS setTechAPollingLoopAnnotation(JNIEnv* env, jobject o,
- jbyteArray tech_a_polling_loop_annotation) {
+ const uint8_t* annotation_data,
+ size_t annotation_size) {
std::vector<uint8_t> command;
command.push_back(NCI_ANDROID_SET_TECH_A_POLLING_LOOP_ANNOTATION);
- if (tech_a_polling_loop_annotation == NULL) {
- // Annotation is null, setting 0 annotations
+ if (annotation_data == NULL || annotation_size == 0) {
+ // Annotation is null or size is 0, setting 0 annotations
command.push_back(0x00);
} else {
- ScopedByteArrayRO annotationBytes(env, tech_a_polling_loop_annotation);
- if (annotationBytes.size() > 0) {
- command.push_back(0x01);
- command.push_back(0x00);
- command.push_back(annotationBytes.size() + 3);
- command.push_back(0x0a);
- command.insert(command.end(), &annotationBytes[0],
- &annotationBytes[annotationBytes.size()]);
- } else {
- // Annotation is zero length, setting 0 annotations"
- command.push_back(0x00);
- }
+ command.push_back(0x01); // Number of frame entries.
+ command.push_back(0x21); // Position and type.
+ command.push_back(annotation_size + 3); // Length
+ command.push_back(0x0a); // Waiting time
+ command.insert(command.end(), annotation_data, annotation_data + annotation_size);
+ command.push_back(0x00);
+ command.push_back(0x00);
}
- command.push_back(0x00);
- command.push_back(0x00);
SyncEventGuard guard(gNfaVsCommand);
tNFA_STATUS status =
NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, command.size(), command.data(), nfaVSCallback);
@@ -1872,7 +1866,19 @@
if (tech_mask != 0) {
stopPolling_rfDiscoveryDisabled();
if (isReaderModeAnnotationSupported(e, o)) {
- setTechAPollingLoopAnnotation(e, o, tech_a_polling_loop_annotation);
+ if (reader_mode) {
+ if (tech_a_polling_loop_annotation == NULL) {
+ setTechAPollingLoopAnnotation(e, o, NULL, 0);
+ } else {
+ ScopedByteArrayRO annotationBytes(e, tech_a_polling_loop_annotation);
+ setTechAPollingLoopAnnotation(e, o,
+ (const uint8_t*)annotationBytes.get(),
+ annotationBytes.size());
+ }
+ } else {
+ uint8_t ignoreFrame[] = {0x6a, 0x01, 0xcf, 0x00, 0x00};
+ setTechAPollingLoopAnnotation(e, 0, ignoreFrame, 5);
+ }
}
startPolling_rfDiscoveryDisabled(tech_mask);
@@ -2062,6 +2068,35 @@
LOG(DEBUG) << StringPrintf("%s: deregister VS callbacks", __func__);
NFA_RegVSCback(false, &nfaVSCallback);
+ // abort any active waits
+ {
+ SyncEventGuard guard(sNfaSetPowerSubState);
+ sNfaSetPowerSubState.notifyOne();
+ }
+ {
+ SyncEventGuard guard(sNfaEnableDisablePollingEvent);
+ sNfaEnableDisablePollingEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(gNfaSetConfigEvent);
+ gNfaSetConfigEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(gNfaGetConfigEvent);
+ gNfaGetConfigEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(gNfaVsCommand);
+ gNfaVsCommand.notifyOne();
+ }
+ {
+ SyncEventGuard guard(gSendRawVsCmdEvent);
+ gSendRawVsCmdEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(gNfaRemoveEpEvent);
+ gNfaRemoveEpEvent.notifyOne();
+ }
NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
theInstance.Finalize();
diff --git a/NfcNci/nci/jni/NativeNfcTag.cpp b/NfcNci/nci/jni/NativeNfcTag.cpp
index e01f1f1..168fe4d 100644
--- a/NfcNci/nci/jni/NativeNfcTag.cpp
+++ b/NfcNci/nci/jni/NativeNfcTag.cpp
@@ -42,6 +42,7 @@
namespace android {
extern nfc_jni_native_data* getNative(JNIEnv* e, jobject o);
extern bool nfcManager_isNfcActive();
+extern bool sIsDisabling;
} // namespace android
extern bool gActivated;
@@ -130,6 +131,7 @@
static bool sReselectTagIdle = false;
static int sPresCheckStatus = 0;
+static bool sIsDisconnecting = false;
static int reSelect(tNFA_INTF_TYPE rfInterface, bool fSwitchIfNeeded);
extern bool gIsDtaEnabled;
@@ -546,9 +548,18 @@
int retCode = NFCSTATUS_SUCCESS;
tNFA_INTF_TYPE intfType = NFA_INTERFACE_FRAME;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return NFCSTATUS_FAILED;
+ }
sIsoDepPresCheckCnt = 0;
sPresCheckErrCnt = 0;
sIsoDepPresCheckAlternate = false;
+ if (sIsDisconnecting) {
+ LOG(ERROR) << StringPrintf("%s: Disconnect in progress", __func__);
+ retCode = NFCSTATUS_FAILED;
+ goto TheEnd;
+ }
if (i >= NfcTag::MAX_NUM_TECHNOLOGY) {
LOG(ERROR) << StringPrintf("%s: Handle not found", __func__);
@@ -738,7 +749,7 @@
}
/*Retry logic in case of core Generic error while selecting a tag*/
- if (sConnectOk == false) {
+ if ((sConnectOk == false) && !sIsDisabling) {
LOG(ERROR) << StringPrintf("%s: waiting for Card to be activated",
__func__);
int retry = 0;
@@ -797,6 +808,15 @@
int retCode = NFCSTATUS_SUCCESS;
NfcTag& natTag = NfcTag::getInstance();
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return NFCSTATUS_FAILED;
+ }
+ if (sIsDisconnecting) {
+ LOG(ERROR) << StringPrintf("%s: Disconnect in progress", __func__);
+ retCode = NFCSTATUS_FAILED;
+ goto TheEnd;
+ }
if (natTag.getActivationState() != NfcTag::Active) {
LOG(ERROR) << StringPrintf("%s: tag already deactivated", __func__);
retCode = NFCSTATUS_FAILED;
@@ -856,6 +876,11 @@
LOG(DEBUG) << StringPrintf("%s: enter", __func__);
tNFA_STATUS nfaStat = NFA_STATUS_OK;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return JNI_FALSE;
+ }
+ sIsDisconnecting = true;
NfcTag::getInstance().resetAllTransceiveTimeouts();
sReselectTagIdle = false;
@@ -871,6 +896,7 @@
nfaStat);
TheEnd:
+ sIsDisconnecting = false;
LOG(DEBUG) << StringPrintf("%s: exit", __func__);
return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
}
@@ -939,6 +965,10 @@
bool isNack = false;
jint* targetLost = NULL;
tNFA_STATUS status;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return nullptr;
+ }
if (NfcTag::getInstance().getActivationState() != NfcTag::Active) {
if (statusTargetLost) {
@@ -1192,6 +1222,10 @@
tNFA_STATUS status = NFA_STATUS_FAILED;
jint* ndef = NULL;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return NFA_STATUS_FAILED;
+ }
LOG(DEBUG) << StringPrintf("%s: enter", __func__);
// special case for Kovio
@@ -1329,6 +1363,10 @@
LOG(DEBUG) << StringPrintf("%s", __func__);
tNFA_STATUS status = NFA_STATUS_OK;
bool isPresent = false;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return JNI_FALSE;
+ }
// Special case for Kovio. The deactivation would have already occurred
// but was ignored so that normal tag opertions could complete. Now we
@@ -1579,6 +1617,10 @@
LOG(DEBUG) << StringPrintf("%s: enter", __func__);
tNFA_STATUS status = NFA_STATUS_OK;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return JNI_FALSE;
+ }
// Do not try to format if tag is already deactivated.
if (NfcTag::getInstance().isActivated() == false) {
LOG(DEBUG) << StringPrintf("%s: tag already deactivated(no need to format)",
@@ -1645,6 +1687,10 @@
static jboolean nativeNfcTag_doMakeReadonly(JNIEnv* e, jobject o, jbyteArray) {
jboolean result = JNI_FALSE;
tNFA_STATUS status;
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return JNI_FALSE;
+ }
LOG(DEBUG) << StringPrintf("%s", __func__);
diff --git a/NfcNci/nci/jni/RoutingManager.cpp b/NfcNci/nci/jni/RoutingManager.cpp
index 4e6270d..37a565e 100755
--- a/NfcNci/nci/jni/RoutingManager.cpp
+++ b/NfcNci/nci/jni/RoutingManager.cpp
@@ -461,6 +461,27 @@
} else {
LOG(DEBUG) << fn << ": No active EEs found";
}
+ //release waits
+ {
+ SyncEventGuard guard(mEeRegisterEvent);
+ mEeRegisterEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(mRoutingEvent);
+ mRoutingEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(mEeSetModeEvent);
+ mEeSetModeEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(mEePwrAndLinkCtrlEvent);
+ mEePwrAndLinkCtrlEvent.notifyOne();
+ }
+ {
+ SyncEventGuard guard(mAidAddRemoveEvent);
+ mAidAddRemoveEvent.notifyOne();
+ }
}
/*******************************************************************************
diff --git a/NfcNci/res/values/overlayable.xml b/NfcNci/res/values/overlayable.xml
index b500405..cb2ecce 100644
--- a/NfcNci/res/values/overlayable.xml
+++ b/NfcNci/res/values/overlayable.xml
@@ -26,6 +26,7 @@
<item name="polling_disable_allowed" type="bool" />
<item name="nfcc_always_on_allowed" type="bool" />
<item name="enable_reader_option_support" type="bool" />
+ <item name="enable_service_for_category_other" type="bool" />
<item name="payment_foreground_preference" type="bool" />
<item name="tag_intent_app_pref_supported" type="bool" />
<item name="max_antenna_blocked_failure_count" type="integer" />
diff --git a/NfcNci/src/com/android/nfc/DeviceConfigFacade.java b/NfcNci/src/com/android/nfc/DeviceConfigFacade.java
index 1e14404..8c0a40e 100644
--- a/NfcNci/src/com/android/nfc/DeviceConfigFacade.java
+++ b/NfcNci/src/com/android/nfc/DeviceConfigFacade.java
@@ -49,11 +49,24 @@
private boolean mReaderOptionDefault;
private boolean mSecureNfcCapable;
private boolean mSecureNfcDefault;
+ private boolean mEnableAutoPlay;
+ private boolean mPollingDisableAllowed;
+ private boolean mNfccAlwaysOnAllowed;
+ private boolean mEnableServiceOther;
+ private boolean mTagIntentAppPrefSupported;
+ private boolean mProprietaryGetcapsSupported;
+ private boolean mEnableOemExtension;
+ private boolean mEnableDeveloperNotification;
+ private boolean mCheckDisplayStateForScreenState;
+ private boolean mIndicateUserActivityForHce;
private String mDefaultRoute;
private String mDefaultIsoDepRoute;
private String mDefaultOffHostRoute;
private String mDefaultScRoute;
private int mSlowTapThresholdMillis;
+ private int mUnknownTagPollingDelay;
+ private int mUnknownTagPollingDelayMax;
+ private int mUnknownTagPollingDelayLong;
private static DeviceConfigFacade sInstance;
public static DeviceConfigFacade getInstance(Context context, Handler handler) {
@@ -101,6 +114,46 @@
KEY_SECURE_NFC_DEFAULT,
mContext.getResources().getBoolean(R.bool.secure_nfc_default));
+ mEnableAutoPlay = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "enable_auto_play",
+ mContext.getResources().getBoolean(R.bool.enable_auto_play));
+
+ mPollingDisableAllowed = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "polling_disable_allowed",
+ mContext.getResources().getBoolean(R.bool.polling_disable_allowed));
+
+ mNfccAlwaysOnAllowed = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "nfcc_always_on_allowed",
+ mContext.getResources().getBoolean(R.bool.nfcc_always_on_allowed));
+
+ mEnableServiceOther = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "enable_service_for_category_other",
+ mContext.getResources().getBoolean(R.bool.enable_service_for_category_other));
+
+ mTagIntentAppPrefSupported = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "tag_intent_app_pref_supported",
+ mContext.getResources().getBoolean(R.bool.tag_intent_app_pref_supported));
+
+ mProprietaryGetcapsSupported = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "nfc_proprietary_getcaps_supported",
+ mContext.getResources().getBoolean(R.bool.nfc_proprietary_getcaps_supported));
+
+ mEnableOemExtension = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "enable_oem_extension",
+ mContext.getResources().getBoolean(R.bool.enable_oem_extension));
+
+ mEnableDeveloperNotification = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "enable_developer_option_notification",
+ mContext.getResources().getBoolean(R.bool.enable_developer_option_notification));
+
+ mCheckDisplayStateForScreenState = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "check_display_state_for_screen_state",
+ mContext.getResources().getBoolean(R.bool.check_display_state_for_screen_state));
+
+ mIndicateUserActivityForHce = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_NFC,
+ "indicate_user_activity_for_hce",
+ mContext.getResources().getBoolean(R.bool.indicate_user_activity_for_hce));
+
mDefaultRoute = DeviceConfig.getString(DEVICE_CONFIG_NAMESPACE_NFC,
"nfc_default_route",
mContext.getResources().getString(R.string.nfc_default_route));
@@ -120,6 +173,19 @@
mSlowTapThresholdMillis = DeviceConfig.getInt(DEVICE_CONFIG_NAMESPACE_NFC,
KEY_SLOW_TAP_THRESHOLD_MILLIS,
mContext.getResources().getInteger(R.integer.slow_tap_threshold_millis));
+
+ mUnknownTagPollingDelay = DeviceConfig.getInt(DEVICE_CONFIG_NAMESPACE_NFC,
+ "unknown_tag_polling_delay",
+ mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay));
+
+ mUnknownTagPollingDelayMax = DeviceConfig.getInt(DEVICE_CONFIG_NAMESPACE_NFC,
+ "unknown_tag_polling_delay_count_max",
+ mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay_count_max));
+
+ mUnknownTagPollingDelayLong = DeviceConfig.getInt(DEVICE_CONFIG_NAMESPACE_NFC,
+ "unknown_tag_polling_delay_long",
+ mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay_long));
+
}
private boolean isSecureNfcCapableDefault() {
@@ -158,6 +224,16 @@
public boolean getDefaultSecureNfcState() {
return mSecureNfcDefault;
}
+ public boolean getEnableAutoPlay() { return mEnableAutoPlay; }
+ public boolean getPollingDisableAllowed() { return mPollingDisableAllowed; }
+ public boolean getNfccAlwaysOnAllowed() { return mNfccAlwaysOnAllowed; }
+ public boolean getEnableServiceOther() { return mEnableServiceOther; }
+ public boolean getTagIntentAppPrefSupported() { return mTagIntentAppPrefSupported; }
+ public boolean getProprietaryGetcapsSupported() { return mProprietaryGetcapsSupported; }
+ public boolean getEnableOemExtension() { return mEnableOemExtension; }
+ public boolean getEnableDeveloperNotification() { return mEnableDeveloperNotification; }
+ public boolean getCheckDisplayStateForScreenState() { return mCheckDisplayStateForScreenState; }
+ public boolean getIndicateUserActivityForHce() { return mIndicateUserActivityForHce; }
public String getDefaultRoute() {
return mDefaultRoute;
}
@@ -173,4 +249,7 @@
public int getSlowTapThresholdMillis() {
return mSlowTapThresholdMillis;
}
+ public int getUnknownTagPollingDelay() { return mUnknownTagPollingDelay; }
+ public int getUnknownTagPollingDelayMax() { return mUnknownTagPollingDelayMax; }
+ public int getUnknownTagPollingDelayLong() { return mUnknownTagPollingDelayLong; }
}
diff --git a/NfcNci/src/com/android/nfc/NfcDispatcher.java b/NfcNci/src/com/android/nfc/NfcDispatcher.java
index 69566ea..bf7f929 100644
--- a/NfcNci/src/com/android/nfc/NfcDispatcher.java
+++ b/NfcNci/src/com/android/nfc/NfcDispatcher.java
@@ -115,6 +115,7 @@
private final Handler mMessageHandler = new MessageHandler();
private final Messenger mMessenger = new Messenger(mMessageHandler);
private final AtomicBoolean mBluetoothEnabledByNfc;
+ private final DeviceConfigFacade mDeviceConfigFacade;
// Locked on this
private PendingIntent mOverrideIntent;
@@ -131,7 +132,7 @@
NfcDispatcher(Context context,
HandoverDataParser handoverDataParser,
NfcInjector nfcInjector,
- boolean provisionOnly) {
+ boolean provisionOnly, DeviceConfigFacade deviceConfigFacade) {
mContext = context;
mTechListFilters = new RegisteredComponentCache(mContext,
NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
@@ -144,6 +145,7 @@
mForegroundUid = Process.INVALID_UID;
mForegroundUtils = ForegroundUtils.getInstance(
context.getSystemService(ActivityManager.class));
+ mDeviceConfigFacade = deviceConfigFacade;
synchronized (this) {
mProvisioningOnly = provisionOnly;
}
@@ -596,8 +598,7 @@
boolean screenUnlocked = false;
if (!provisioningOnly &&
mScreenStateHelper.checkScreenState(
- mContext.getResources().getBoolean(
- R.bool.check_display_state_for_screen_state))
+ mDeviceConfigFacade.getCheckDisplayStateForScreenState())
== ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
screenUnlocked = handleNfcUnlock(tag);
if (!screenUnlocked)
diff --git a/NfcNci/src/com/android/nfc/NfcInjector.java b/NfcNci/src/com/android/nfc/NfcInjector.java
index 3abd3e0..8611ed2 100644
--- a/NfcNci/src/com/android/nfc/NfcInjector.java
+++ b/NfcNci/src/com/android/nfc/NfcInjector.java
@@ -110,7 +110,8 @@
mHandoverDataParser = new HandoverDataParser();
mDeviceConfigFacade = new DeviceConfigFacade(mContext, new Handler(mainLooper));
mNfcDispatcher =
- new NfcDispatcher(mContext, mHandoverDataParser, this, isInProvisionMode());
+ new NfcDispatcher(mContext, mHandoverDataParser, this,
+ isInProvisionMode(), mDeviceConfigFacade);
mVibrationEffect = VibrationEffect.createOneShot(200, VibrationEffect.DEFAULT_AMPLITUDE);
mBackupManager = new BackupManager(mContext);
mFeatureFlags = new com.android.nfc.flags.FeatureFlagsImpl();
diff --git a/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java b/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java
index 4079b09..9c87e2f 100644
--- a/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java
+++ b/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java
@@ -140,6 +140,8 @@
+ mIsPowerSavingModeSupported
+ ", isAutotransactPollingLoopFilterSupported="
+ mIsAutotransactPollingLoopFilterSupported
+ + ", mIsReaderModeAnnotationSupported="
+ + mIsReaderModeAnnotationSupported
+ '}';
}
}
diff --git a/NfcNci/src/com/android/nfc/NfcService.java b/NfcNci/src/com/android/nfc/NfcService.java
index a2940f5..4397aab 100644
--- a/NfcNci/src/com/android/nfc/NfcService.java
+++ b/NfcNci/src/com/android/nfc/NfcService.java
@@ -1157,8 +1157,7 @@
mAlarmManager = mContext.getSystemService(AlarmManager.class);
- mCheckDisplayStateForScreenState =
- mContext.getResources().getBoolean(R.bool.check_display_state_for_screen_state);
+ mCheckDisplayStateForScreenState = mDeviceConfigFacade.getCheckDisplayStateForScreenState();
if (mInProvisionMode) {
mScreenState = mScreenStateHelper.checkScreenStateProvisionMode();
} else {
@@ -1246,13 +1245,11 @@
}
// Polling delay count for switching from stage one to stage two.
- mPollDelayCountMax =
- mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay_count_max);
+ mPollDelayCountMax = mDeviceConfigFacade.getUnknownTagPollingDelayMax();
// Stage one: polling delay time for the first few unknown tag detections
- mPollDelayTime = mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay);
+ mPollDelayTime = mDeviceConfigFacade.getUnknownTagPollingDelay();
// Stage two: longer polling delay time after max_poll_delay_count
- mPollDelayTimeLong =
- mContext.getResources().getInteger(R.integer.unknown_tag_polling_delay_long);
+ mPollDelayTimeLong = mDeviceConfigFacade.getUnknownTagPollingDelayLong();
// Polling delay if read error found more than max count.
mReadErrorCountMax =
mContext.getResources().getInteger(R.integer.unknown_tag_read_error_count_max);
@@ -1260,7 +1257,7 @@
mNotifyDispatchFailed = mContext.getResources().getBoolean(R.bool.enable_notify_dispatch_failed);
mNotifyReadFailed = mContext.getResources().getBoolean(R.bool.enable_notify_read_failed);
- mPollingDisableAllowed = mContext.getResources().getBoolean(R.bool.polling_disable_allowed);
+ mPollingDisableAllowed = mDeviceConfigFacade.getPollingDisableAllowed();
mAppInActivityDetectionTime =
mContext.getResources().getInteger(R.integer.inactive_presence_check_allowed_time);
mTagRemovalDetectionWaitTime =
@@ -1268,8 +1265,7 @@
// Make sure this is only called when object construction is complete.
mNfcInjector.getNfcManagerRegisterer().register(mNfcAdapter);
- mIsAlwaysOnSupported =
- mContext.getResources().getBoolean(R.bool.nfcc_always_on_allowed);
+ mIsAlwaysOnSupported = mDeviceConfigFacade.getNfccAlwaysOnAllowed();
mIsTagAppPrefSupported =
mContext.getResources().getBoolean(R.bool.tag_intent_app_pref_supported);
@@ -1351,8 +1347,8 @@
executeTaskBoot(); // do blocking boot tasks
if ((NFC_SNOOP_LOG_MODE.equals(NfcProperties.snoop_log_mode_values.FULL) ||
- NFC_VENDOR_DEBUG_ENABLED) && mContext.getResources().getBoolean(
- R.bool.enable_developer_option_notification)) {
+ NFC_VENDOR_DEBUG_ENABLED) &&
+ mDeviceConfigFacade.getEnableDeveloperNotification()) {
new NfcDeveloperOptionNotification(mContext).startNotification();
}
@@ -1366,7 +1362,7 @@
private void executeTaskBoot() {
// If overlay is set, delay the NFC boot up until the OEM extension indicates it is ready to
// proceed with NFC bootup.
- if (mContext.getResources().getBoolean(R.bool.enable_oem_extension)) {
+ if (mDeviceConfigFacade.getEnableOemExtension()) {
// Send intent for OEM extension to initialize.
Intent intent = new Intent(NfcOemExtension.ACTION_OEM_EXTENSION_INIT);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT, BIND_NFC_SERVICE);
@@ -4745,6 +4741,8 @@
public int commitRouting(boolean isOverrideOrRecover) {
if (!isOverrideOrRecover) {
+ // Clear the Handler queue, only last commit_msg is relevant
+ mHandler.removeMessages(MSG_COMMIT_ROUTING);
mHandler.sendEmptyMessage(MSG_COMMIT_ROUTING);
return STATUS_OK;
}
@@ -5848,8 +5846,8 @@
applyScreenState(mScreenStateHelper.checkScreenState(mCheckDisplayStateForScreenState));
if ((NFC_SNOOP_LOG_MODE.equals(NfcProperties.snoop_log_mode_values.FULL) ||
- NFC_VENDOR_DEBUG_ENABLED) && mContext.getResources().getBoolean(
- R.bool.enable_developer_option_notification)) {
+ NFC_VENDOR_DEBUG_ENABLED) &&
+ mDeviceConfigFacade.getEnableDeveloperNotification()){
new NfcDeveloperOptionNotification(mContext.createContextAsUser(
UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0))
.startNotification();
@@ -5863,8 +5861,8 @@
setPaymentForegroundPreference(userId);
if ((NFC_SNOOP_LOG_MODE.equals(NfcProperties.snoop_log_mode_values.FULL) ||
- NFC_VENDOR_DEBUG_ENABLED) && mContext.getResources().getBoolean(
- R.bool.enable_developer_option_notification)) {
+ NFC_VENDOR_DEBUG_ENABLED) &&
+ mDeviceConfigFacade.getEnableDeveloperNotification()) {
new NfcDeveloperOptionNotification(mContext.createContextAsUser(
UserHandle.of(ActivityManager.getCurrentUser()), /*flags=*/0))
.startNotification();
diff --git a/NfcNci/src/com/android/nfc/NfcShellCommand.java b/NfcNci/src/com/android/nfc/NfcShellCommand.java
index 2825f46..0f77f92 100644
--- a/NfcNci/src/com/android/nfc/NfcShellCommand.java
+++ b/NfcNci/src/com/android/nfc/NfcShellCommand.java
@@ -77,7 +77,10 @@
@VisibleForTesting
@Override
public PrintWriter getOutPrintWriter() {
- return mPrintWriter;
+ if( mPrintWriter != null )
+ return mPrintWriter;
+ else
+ return super.getOutPrintWriter();
}
@Override
diff --git a/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java b/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java
index 08ff9b6..fea52e8 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java
@@ -68,6 +68,7 @@
import com.android.nfc.NfcPermissions;
import com.android.nfc.NfcService;
import com.android.nfc.R;
+import com.android.nfc.cardemulation.util.StatsdUtils;
import com.android.nfc.cardemulation.util.TelephonyUtils;
import com.android.nfc.flags.Flags;
import com.android.nfc.proto.NfcEventProto;
@@ -155,6 +156,9 @@
private final int mVendorApiLevel;
private PreferredSubscriptionService mPreferredSubscriptionService = null;
private TelephonyUtils mTelephonyUtils = null;
+ @Nullable
+ private final StatsdUtils mStatsdUtils;
+ private final DeviceConfigFacade mDeviceConfigFacade;
// TODO: Move this object instantiation and dependencies to NfcInjector.
public CardEmulationManager(Context context, NfcInjector nfcInjector,
@@ -191,6 +195,8 @@
mVendorApiLevel = SystemProperties.getInt(
"ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
mPreferredSubscriptionService = new PreferredSubscriptionService(mContext, this);
+ mStatsdUtils = nfcInjector.getStatsdUtils();
+ mDeviceConfigFacade = deviceConfigFacade;
initialize();
}
@@ -209,7 +215,9 @@
RoutingOptionManager routingOptionManager,
PowerManager powerManager,
NfcEventLog nfcEventLog,
- PreferredSubscriptionService preferredSubscriptionService) {
+ PreferredSubscriptionService preferredSubscriptionService,
+ StatsdUtils statsdUtils,
+ DeviceConfigFacade deviceConfigFacade) {
mContext = context;
mCardEmulationInterface = new CardEmulationInterface();
mNfcFCardEmulationInterface = new NfcFCardEmulationInterface();
@@ -231,6 +239,8 @@
mVendorApiLevel = SystemProperties.getInt(
"ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
mPreferredSubscriptionService = preferredSubscriptionService;
+ mStatsdUtils = statsdUtils;
+ mDeviceConfigFacade = deviceConfigFacade;
initialize();
}
@@ -287,7 +297,7 @@
Log.e(TAG, "onHostCardEmulationActivated: failed", e);
}
}
- if (mContext.getResources().getBoolean(R.bool.indicate_user_activity_for_hce)
+ if (mDeviceConfigFacade.getIndicateUserActivityForHce()
&& mPowerManager != null) {
// Use USER_ACTIVITY_FLAG_INDIRECT to applying power hints without resets
// the screen timeout
@@ -903,11 +913,6 @@
.setPollingLoopFilter(pollingLoopFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -943,11 +948,6 @@
.setPollingLoopFilter(pollingLoopFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -983,11 +983,6 @@
.setPollingLoopFilter(pollingLoopPatternFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -1023,11 +1018,6 @@
.setPollingLoopFilter(pollingLoopPatternFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -1152,7 +1142,7 @@
@Override
public int setServiceEnabledForCategoryOther(int userId,
ComponentName app, boolean status) throws RemoteException {
- if (!mContext.getResources().getBoolean(R.bool.enable_service_for_category_other))
+ if (!mDeviceConfigFacade.getEnableServiceOther())
return SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED;
NfcPermissions.enforceUserPermissions(mContext);
@@ -1732,6 +1722,10 @@
callNfcEventCallbacks(listener -> listener.onObserveModeDisabledInFirmware(exitFrame));
}
mHostEmulationManager.onObserveModeDisabledInFirmware(exitFrame);
+
+ if (mStatsdUtils != null) {
+ mStatsdUtils.logAutoTransactReported(StatsdUtils.PROCESSOR_NFCC, exitFrame.getData());
+ }
}
@Override
diff --git a/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java b/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 3a76b80..506d199 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -252,7 +252,12 @@
@Override
public void run() {
synchronized (mLock) {
- unbindInactiveServicesLocked();
+ if (isHostCardEmulationActivated()) {
+ // Skip in active state
+ rescheduleInactivityChecks();
+ } else {
+ unbindInactiveServicesLocked();
+ }
}
}
diff --git a/NfcNci/src/com/android/nfc/cardemulation/RegisteredServicesCache.java b/NfcNci/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
index 1cf3ba1..b273741 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/RegisteredServicesCache.java
@@ -1266,6 +1266,9 @@
Log.e(TAG, "removePollingLoopFilterForService: UID mismatch");
return false;
}
+ DynamicSettings dynamicSettings =
+ getOrCreateSettings(services, componentName, serviceInfo.getUid());
+ dynamicSettings.pollingLoopFilters.remove(pollingLoopFilter);
serviceInfo.removePollingLoopFilter(pollingLoopFilter);
newServices = new ArrayList<ApduServiceInfo>(services.services.values());
}
@@ -1328,6 +1331,9 @@
Log.e(TAG, "removePollingLoopPatternFilterForService: UID mismatch");
return false;
}
+ DynamicSettings dynamicSettings =
+ getOrCreateSettings(services, componentName, serviceInfo.getUid());
+ dynamicSettings.pollingLoopPatternFilters.remove(pollingLoopPatternFilter);
serviceInfo.removePollingLoopPatternFilter(pollingLoopPatternFilter);
newServices = new ArrayList<ApduServiceInfo>(services.services.values());
}
diff --git a/NfcNci/src/com/android/nfc/handover/BluetoothPeripheralHandover.java b/NfcNci/src/com/android/nfc/handover/BluetoothPeripheralHandover.java
index 7648f51..ae9c808 100644
--- a/NfcNci/src/com/android/nfc/handover/BluetoothPeripheralHandover.java
+++ b/NfcNci/src/com/android/nfc/handover/BluetoothPeripheralHandover.java
@@ -43,6 +43,8 @@
import androidx.annotation.VisibleForTesting;
+import com.android.nfc.DeviceConfigFacade;
+import com.android.nfc.NfcInjector;
import com.android.nfc.R;
import java.lang.reflect.Method;
@@ -102,6 +104,7 @@
final int mTransport;
final boolean mProvisioning;
final AudioManager mAudioManager;
+ private DeviceConfigFacade mDeviceConfigFacade;
final Object mLock = new Object();
@@ -177,6 +180,8 @@
mAudioManager = mContext.getSystemService(AudioManager.class);
+ mDeviceConfigFacade = NfcInjector.getInstance().getDeviceConfigFacade();
+
mState = STATE_INIT;
}
@@ -608,7 +613,7 @@
}
void startTheMusic() {
- if (!mContext.getResources().getBoolean(R.bool.enable_auto_play) && !mIsMusicActive) {
+ if (!mDeviceConfigFacade.getEnableAutoPlay() && !mIsMusicActive) {
return;
}
diff --git a/NfcNci/tests/testcases/hostsidetests/exitframes/nfc_exit_frame_multi_device_test.py b/NfcNci/tests/testcases/hostsidetests/exitframes/nfc_exit_frame_multi_device_test.py
index 5efa715..793a2a7 100644
--- a/NfcNci/tests/testcases/hostsidetests/exitframes/nfc_exit_frame_multi_device_test.py
+++ b/NfcNci/tests/testcases/hostsidetests/exitframes/nfc_exit_frame_multi_device_test.py
@@ -228,7 +228,7 @@
self.emulator.nfc_emulator.turnScreenOn()
self.emulator.nfc_emulator.pressMenu()
- """Tests the autotransact functionality.
+ """Tests the autotransact functionality with exit frames.
Test Steps:
1. Start emulator activity and set up payment HCE Service.
@@ -239,16 +239,14 @@
Verifies:
1. Observe mode is disabled and a transaction occurs.
- 2. After the first transaction, verifies that observe mode is reenabled.
- 3. After observe mode is reenabled, verifies that the tag is not
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
detected.
-
- TODO(johnrjohn) Add methods to register unique polling frames so we can
- test different filters
"""
- def test_exit_frames(self):
+ def test_exit_frames_manifest_filter(self):
self._set_up_emulator(
- "41fbc7b9",
+ "41fbc7b9", [], True,
start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
service_list=[_PAYMENT_SERVICE_1],
expected_service=_PAYMENT_SERVICE_1,
@@ -290,11 +288,347 @@
self.pn532, command_apdus, response_apdus)
asserts.assert_false(
tag_detected,
- "Reader detected emulator even though observemode was enabled."
+ "Reader detected emulator even though observe mode was enabled."
)
self.emulator.nfc_emulator.setObserveModeEnabled(False)
+ """Tests the autotransact functionality with exit frames.
+
+ Test Steps:
+ 1. Start emulator activity and set up payment HCE Service.
+ 2. Enable observe mode.
+ 3. Poll with a broadcast frame, and attempt to transact.
+ 4. Wait for observe mode to be reenabled.
+ 5. Poll again and verify that the tag is not detected.
+
+ Verifies:
+ 1. Observe mode is disabled and a transaction occurs.
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
+ detected.
+ """
+ def test_exit_frames_registered_filters(self):
+ self._set_up_emulator(
+ "12345678", ["12345678", "aaaa"], True,
+ start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
+ service_list=[_PAYMENT_SERVICE_1],
+ expected_service=_PAYMENT_SERVICE_1,
+ is_payment=True,
+ payment_default_service=_PAYMENT_SERVICE_1
+ )
+ asserts.skip_if(
+ not self.emulator.nfc_emulator.isObserveModeSupported(),
+ f"{self.emulator} observe mode not supported",
+ )
+ asserts.assert_true(
+ self.emulator.nfc_emulator.setObserveModeEnabled(True),
+ f"{self.emulator} could not set observe mode",
+ )
+
+ command_apdus, response_apdus = get_apdus(self.emulator.nfc_emulator,
+ _PAYMENT_SERVICE_1)
+ test_pass_handler = self.emulator.nfc_emulator.asyncWaitForTestPass(
+ 'ExitFrameListenerSuccess'
+ )
+ tag_detected, transacted = poll_and_transact(
+ self.pn532, command_apdus, response_apdus, "12345678")
+ asserts.assert_true(
+ tag_detected, _FAILED_TAG_MSG
+ )
+ asserts.assert_true(transacted, _FAILED_TRANSACTION_MSG)
+ test_pass_handler.waitAndGet('ExitFrameListenerSuccess', _NFC_TIMEOUT_SEC)
+
+
+ time.sleep(_NFC_TIMEOUT_SEC)
+
+ # Poll again and see if tag is detected, observe mode should be enabled
+ # by now.
+ asserts.assert_true(
+ self.emulator.nfc_emulator.isObserveModeEnabled(),
+ f"{self.emulator} isObserveModeEnabled did not return True",
+ )
+ tag_detected, _ = poll_and_transact(
+ self.pn532, command_apdus, response_apdus)
+ asserts.assert_false(
+ tag_detected,
+ "Reader detected emulator even though observe mode was enabled."
+ )
+
+ self.emulator.nfc_emulator.setObserveModeEnabled(False)
+
+ """Tests the autotransact functionality with exit frames.
+
+ Test Steps:
+ 1. Start emulator activity and set up payment HCE Service.
+ 2. Enable observe mode.
+ 3. Poll with a broadcast frame, and attempt to transact.
+ 4. Wait for observe mode to be reenabled.
+ 5. Poll again and verify that the tag is not detected.
+
+ Verifies:
+ 1. Observe mode is disabled and a transaction occurs.
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
+ detected.
+ """
+ def test_exit_frames_prefix_match(self):
+ self._set_up_emulator(
+ "dd1234", ["12345678", "dd.*", "ee.*", "ff.."], True,
+ start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
+ service_list=[_PAYMENT_SERVICE_1],
+ expected_service=_PAYMENT_SERVICE_1,
+ is_payment=True,
+ payment_default_service=_PAYMENT_SERVICE_1
+ )
+ asserts.skip_if(
+ not self.emulator.nfc_emulator.isObserveModeSupported(),
+ f"{self.emulator} observe mode not supported",
+ )
+ asserts.assert_true(
+ self.emulator.nfc_emulator.setObserveModeEnabled(True),
+ f"{self.emulator} could not set observe mode",
+ )
+
+ command_apdus, response_apdus = get_apdus(self.emulator.nfc_emulator,
+ _PAYMENT_SERVICE_1)
+ test_pass_handler = self.emulator.nfc_emulator.asyncWaitForTestPass(
+ 'ExitFrameListenerSuccess'
+ )
+ tag_detected, transacted = poll_and_transact(
+ self.pn532, command_apdus, response_apdus, "dd1234")
+ asserts.assert_true(
+ tag_detected, _FAILED_TAG_MSG
+ )
+ asserts.assert_true(transacted, _FAILED_TRANSACTION_MSG)
+ test_pass_handler.waitAndGet('ExitFrameListenerSuccess', _NFC_TIMEOUT_SEC)
+
+
+ time.sleep(_NFC_TIMEOUT_SEC)
+
+ # Poll again and see if tag is detected, observe mode should be enabled
+ # by now.
+ asserts.assert_true(
+ self.emulator.nfc_emulator.isObserveModeEnabled(),
+ f"{self.emulator} isObserveModeEnabled did not return True",
+ )
+ tag_detected, _ = poll_and_transact(
+ self.pn532, command_apdus, response_apdus)
+ asserts.assert_false(
+ tag_detected,
+ "Reader detected emulator even though observe mode was enabled."
+ )
+
+ self.emulator.nfc_emulator.setObserveModeEnabled(False)
+
+ """Tests the autotransact functionality with exit frames.
+
+ Test Steps:
+ 1. Start emulator activity and set up payment HCE Service.
+ 2. Enable observe mode.
+ 3. Poll with a broadcast frame, and attempt to transact.
+ 4. Wait for observe mode to be reenabled.
+ 5. Poll again and verify that the tag is not detected.
+
+ Verifies:
+ 1. Observe mode is disabled and a transaction occurs.
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
+ detected.
+ """
+ def test_exit_frames_mask_match(self):
+ self._set_up_emulator(
+ "ff11", ["12345678", "ff.."], True,
+ start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
+ service_list=[_PAYMENT_SERVICE_1],
+ expected_service=_PAYMENT_SERVICE_1,
+ is_payment=True,
+ payment_default_service=_PAYMENT_SERVICE_1
+ )
+ asserts.skip_if(
+ not self.emulator.nfc_emulator.isObserveModeSupported(),
+ f"{self.emulator} observe mode not supported",
+ )
+ asserts.assert_true(
+ self.emulator.nfc_emulator.setObserveModeEnabled(True),
+ f"{self.emulator} could not set observe mode",
+ )
+
+ command_apdus, response_apdus = get_apdus(self.emulator.nfc_emulator,
+ _PAYMENT_SERVICE_1)
+ test_pass_handler = self.emulator.nfc_emulator.asyncWaitForTestPass(
+ 'ExitFrameListenerSuccess'
+ )
+ tag_detected, transacted = poll_and_transact(
+ self.pn532, command_apdus, response_apdus, "ff11")
+ asserts.assert_true(
+ tag_detected, _FAILED_TAG_MSG
+ )
+ asserts.assert_true(transacted, _FAILED_TRANSACTION_MSG)
+ test_pass_handler.waitAndGet('ExitFrameListenerSuccess', _NFC_TIMEOUT_SEC)
+
+
+ time.sleep(_NFC_TIMEOUT_SEC)
+
+ # Poll again and see if tag is detected, observe mode should be enabled
+ # by now.
+ asserts.assert_true(
+ self.emulator.nfc_emulator.isObserveModeEnabled(),
+ f"{self.emulator} isObserveModeEnabled did not return True",
+ )
+ tag_detected, _ = poll_and_transact(
+ self.pn532, command_apdus, response_apdus)
+ asserts.assert_false(
+ tag_detected,
+ "Reader detected emulator even though observe mode was enabled."
+ )
+
+ self.emulator.nfc_emulator.setObserveModeEnabled(False)
+
+ """Tests the autotransact functionality with exit frames.
+
+ Test Steps:
+ 1. Start emulator activity and set up payment HCE Service.
+ 2. Enable observe mode.
+ 3. Poll with a broadcast frame, and attempt to transact.
+ 4. Wait for observe mode to be reenabled.
+ 5. Poll again and verify that the tag is not detected.
+
+ Verifies:
+ 1. Observe mode is disabled and a transaction occurs.
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
+ detected.
+ """
+ def test_exit_frames_mask_and_prefix_match(self):
+ self._set_up_emulator(
+ "ddfe1134", ["12345678", "dd..11.*", "ee.*", "ff.."], True,
+ start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
+ service_list=[_PAYMENT_SERVICE_1],
+ expected_service=_PAYMENT_SERVICE_1,
+ is_payment=True,
+ payment_default_service=_PAYMENT_SERVICE_1
+ )
+ asserts.skip_if(
+ not self.emulator.nfc_emulator.isObserveModeSupported(),
+ f"{self.emulator} observe mode not supported",
+ )
+ asserts.assert_true(
+ self.emulator.nfc_emulator.setObserveModeEnabled(True),
+ f"{self.emulator} could not set observe mode",
+ )
+
+ command_apdus, response_apdus = get_apdus(self.emulator.nfc_emulator,
+ _PAYMENT_SERVICE_1)
+ test_pass_handler = self.emulator.nfc_emulator.asyncWaitForTestPass(
+ 'ExitFrameListenerSuccess'
+ )
+ tag_detected, transacted = poll_and_transact(
+ self.pn532, command_apdus, response_apdus, "ddfe1134")
+ asserts.assert_true(
+ tag_detected, _FAILED_TAG_MSG
+ )
+ asserts.assert_true(transacted, _FAILED_TRANSACTION_MSG)
+ test_pass_handler.waitAndGet('ExitFrameListenerSuccess', _NFC_TIMEOUT_SEC)
+
+
+ time.sleep(_NFC_TIMEOUT_SEC)
+
+ # Poll again and see if tag is detected, observe mode should be enabled
+ # by now.
+ asserts.assert_true(
+ self.emulator.nfc_emulator.isObserveModeEnabled(),
+ f"{self.emulator} isObserveModeEnabled did not return True",
+ )
+ tag_detected, _ = poll_and_transact(
+ self.pn532, command_apdus, response_apdus)
+ asserts.assert_false(
+ tag_detected,
+ "Reader detected emulator even though observe mode was enabled."
+ )
+
+ self.emulator.nfc_emulator.setObserveModeEnabled(False)
+
+ """Tests the autotransact functionality with exit frames.
+
+ Test Steps:
+ 1. Start emulator activity and set up payment HCE Service.
+ 2. Enable observe mode.
+ 3. Poll with a broadcast frame, don't transact though.
+ 4. Wait for observe mode to be reenabled.
+ 5. Poll again and verify that the tag is not detected.
+
+ Verifies:
+ 1. Observe mode is disabled.
+ 2. Verify correct exit frame was used for transaction.
+ 3. After the first transaction, verifies that observe mode is reenabled.
+ 4. After observe mode is reenabled, verifies that the tag is not
+ detected.
+ """
+ def test_exit_frames_no_transaction_observe_mode_reenabled(self):
+ self._set_up_emulator(
+ "12345678", ["12345678", "aaaa"], False,
+ start_emulator_fun=self.emulator.nfc_emulator.startExitFrameActivity,
+ service_list=[_PAYMENT_SERVICE_1],
+ expected_service=_PAYMENT_SERVICE_1,
+ is_payment=True,
+ payment_default_service=_PAYMENT_SERVICE_1
+ )
+ asserts.skip_if(
+ not self.emulator.nfc_emulator.isObserveModeSupported(),
+ f"{self.emulator} observe mode not supported",
+ )
+ asserts.assert_true(
+ self.emulator.nfc_emulator.setObserveModeEnabled(True),
+ f"{self.emulator} could not set observe mode",
+ )
+
+ command_apdus, response_apdus = get_apdus(self.emulator.nfc_emulator,
+ _PAYMENT_SERVICE_1)
+ test_pass_handler = self.emulator.nfc_emulator.asyncWaitForTestPass(
+ 'ExitFrameListenerSuccess'
+ )
+ tag_detected, transacted = poll_and_transact(
+ self.pn532, [], [], "12345678")
+ asserts.assert_true(
+ tag_detected, _FAILED_TAG_MSG
+ )
+ test_pass_handler.waitAndGet('ExitFrameListenerSuccess', _NFC_TIMEOUT_SEC)
+
+
+ time.sleep(_NFC_TIMEOUT_SEC)
+
+ # Poll again and see if tag is detected, observe mode should be enabled
+ # by now.
+ asserts.assert_true(
+ self.emulator.nfc_emulator.isObserveModeEnabled(),
+ f"{self.emulator} isObserveModeEnabled did not return True",
+ )
+ tag_detected, _ = poll_and_transact(
+ self.pn532, [], [])
+ asserts.assert_false(
+ tag_detected,
+ "Reader detected emulator even though observe mode was enabled."
+ )
+
+ self.emulator.nfc_emulator.setObserveModeEnabled(False)
+
+ def teardown_test(self):
+ if hasattr(self, 'emulator') and hasattr(self.emulator, 'nfc_emulator'):
+ self.emulator.nfc_emulator.closeActivity()
+ self.emulator.nfc_emulator.logInfo(
+ "*** TEST END: " + self.current_test_info.name + " ***")
+ self.pn532.reset_buffers()
+ self.pn532.mute()
+ param_list = [[self.emulator]]
+ utils.concurrent_exec(lambda d: d.services.create_output_excerpts_all(
+ self.current_test_info),
+ param_list=param_list,
+ raise_on_exception=True)
if __name__ == '__main__':
# Take test args
diff --git a/NfcNci/tests/unit/src/com/android/nfc/NfcDispatcherTest.java b/NfcNci/tests/unit/src/com/android/nfc/NfcDispatcherTest.java
index a347930..9b98ad8 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/NfcDispatcherTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/NfcDispatcherTest.java
@@ -116,6 +116,8 @@
ForegroundUtils mForegroundUtils;
@Mock
AtomicBoolean mAtomicBoolean;
+ @Mock
+ DeviceConfigFacade mDeviceConfigFacade;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
@@ -152,7 +154,7 @@
when(mNfcInjector.createAtomicBoolean()).thenReturn(mAtomicBoolean);
mNfcDispatcher = new NfcDispatcher(mockContext,
- new HandoverDataParser(), mNfcInjector, true);
+ new HandoverDataParser(), mNfcInjector, true, mDeviceConfigFacade);
mLooper.dispatchAll();
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java b/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java
index dcfb92d..82c0d4f 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java
@@ -133,7 +133,8 @@
"passiveObserveMode=SUPPORT_WITHOUT_RF_DEACTIVATION, " +
"isPollingFrameNotificationSupported=true, " +
"isPowerSavingModeSupported=false, " +
- "isAutotransactPollingLoopFilterSupported=true}";
+ "isAutotransactPollingLoopFilterSupported=true, " +
+ "mIsReaderModeAnnotationSupported=false}";
assertEquals(expected, caps.toString());
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/NfcReaderConflictOccurredTest.java b/NfcNci/tests/unit/src/com/android/nfc/NfcReaderConflictOccurredTest.java
index 8f1218e..d8a6e4d 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/NfcReaderConflictOccurredTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/NfcReaderConflictOccurredTest.java
@@ -61,6 +61,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
@@ -70,6 +71,8 @@
private static final String TAG = NfcReaderConflictOccurredTest.class.getSimpleName();
private NfcInjector mNfcInjector;
AtomicBoolean mAtomicBoolean;
+ @Mock
+ DeviceConfigFacade mDeviceConfigFacade;
private MockitoSession mStaticMockSession;
private NfcDispatcher mNfcDispatcher;
@@ -80,7 +83,8 @@
.mockStatic(NfcStatsLog.class)
.strictness(Strictness.LENIENT)
.startMocking();
- Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ MockitoAnnotations.initMocks(this);
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
PackageManager mockPackageManager = Mockito.mock(PackageManager.class);
// multiple resolveInfos for Tag
when(mockPackageManager.queryIntentActivitiesAsUser(
@@ -128,7 +132,8 @@
when(mNfcInjector.createAtomicBoolean()).thenReturn(mAtomicBoolean);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mNfcDispatcher = new NfcDispatcher(
- mockContext, new HandoverDataParser(), mNfcInjector, false));
+ mockContext, new HandoverDataParser(), mNfcInjector, false,
+ mDeviceConfigFacade));
Assert.assertNotNull(mNfcDispatcher);
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/NfcServiceTest.java b/NfcNci/tests/unit/src/com/android/nfc/NfcServiceTest.java
index 69b51cd..98b53f1 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/NfcServiceTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/NfcServiceTest.java
@@ -254,7 +254,7 @@
when(mApplication.getSystemService(KeyguardManager.class)).thenReturn(mKeyguardManager);
when(mApplication.getSystemService(AlarmManager.class)).thenReturn(mAlarmManager);
when(mApplication.getPackageManager()).thenReturn(mPackageManager);
- when(mResources.getBoolean(R.bool.check_display_state_for_screen_state)).thenReturn(true);
+ when(mDeviceConfigFacade.getCheckDisplayStateForScreenState()).thenReturn(true);
when(mApplication.getResources()).thenReturn(mResources);
when(mApplication.createContextAsUser(any(), anyInt())).thenReturn(mApplication);
when(mApplication.getContentResolver()).thenReturn(mContentResolver);
@@ -264,7 +264,7 @@
when(mUserManager.getUserRestrictions()).thenReturn(mUserRestrictions);
when(mResources.getStringArray(R.array.nfc_allow_list)).thenReturn(new String[0]);
when(mResources.getBoolean(R.bool.tag_intent_app_pref_supported)).thenReturn(true);
- when(mResources.getBoolean(R.bool.nfcc_always_on_allowed)).thenReturn(true);
+ when(mDeviceConfigFacade.getNfccAlwaysOnAllowed()).thenReturn(true);
when(mPreferences.edit()).thenReturn(mPreferencesEditor);
when(mPowerManager.newWakeLock(anyInt(), anyString()))
.thenReturn(mock(PowerManager.WakeLock.class));
@@ -344,7 +344,7 @@
@Test
public void testEnable_WheOemExtensionEnabledAndNotInitialized() throws Exception {
- when(mResources.getBoolean(R.bool.enable_oem_extension)).thenReturn(true);
+ when(mDeviceConfigFacade.getEnableOemExtension()).thenReturn(true);
when(NfcProperties.initialized()).thenReturn(Optional.of(Boolean.FALSE));
createNfcService();
@@ -371,7 +371,7 @@
@Test
public void testBootupWithNfcOn_WhenOemExtensionEnabled() throws Exception {
- when(mResources.getBoolean(R.bool.enable_oem_extension)).thenReturn(true);
+ when(mDeviceConfigFacade.getEnableOemExtension()).thenReturn(true);
createNfcService();
verifyNoMoreInteractions(mDeviceHost);
diff --git a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java
index bfe1f62..fbf52a7 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java
@@ -71,6 +71,7 @@
import android.util.proto.ProtoOutputStream;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.nfc.DeviceConfigFacade;
import com.android.nfc.ExitFrame;
import com.android.nfc.ForegroundUtils;
import com.android.nfc.NfcEventLog;
@@ -78,6 +79,7 @@
import com.android.nfc.NfcPermissions;
import com.android.nfc.NfcService;
import com.android.nfc.R;
+import com.android.nfc.cardemulation.util.StatsdUtils;
import com.android.nfc.cardemulation.util.TelephonyUtils;
import com.android.nfc.flags.Flags;
@@ -185,6 +187,10 @@
private NfcEventLog mNfcEventLog;
@Mock
private PreferredSubscriptionService mPreferredSubscriptionService;
+ @Mock
+ private StatsdUtils mStatsdUtils;
+ @Mock
+ private DeviceConfigFacade mDeviceConfigFacade;
@Captor
private ArgumentCaptor<List<PollingFrame>> mPollingLoopFrameCaptor;
@Captor
@@ -220,7 +226,7 @@
when(mContext.createContextAsUser(any(), anyInt())).thenReturn(mContext);
when(mContext.getResources()).thenReturn(mResources);
when(mContext.getSystemService(eq(UserManager.class))).thenReturn(mUserManager);
- when(mResources.getBoolean(R.bool.indicate_user_activity_for_hce)).thenReturn(true);
+ when(mDeviceConfigFacade.getIndicateUserActivityForHce()).thenReturn(true);
when(android.nfc.Flags.nfcEventListener()).thenReturn(true);
when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(true);
mCardEmulationManager = createInstanceWithMockParams();
@@ -439,6 +445,9 @@
@Test
public void testOnServicesUpdated_walletEnabledPollingLoopEnabled() {
when(mWalletRoleObserver.isWalletRoleFeatureEnabled()).thenReturn(true);
+ when(Flags.exitFrames()).thenReturn(true);
+ when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
+ when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
mCardEmulationManager.onServicesUpdated(USER_ID, UPDATED_SERVICES, false);
@@ -447,6 +456,7 @@
verify(mPreferredServices).onServicesUpdated();
verify(mHostEmulationManager)
.updatePollingLoopFilters(eq(USER_ID), mServiceListCaptor.capture());
+ verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
verify(mNfcService).onPreferredPaymentChanged(eq(NfcAdapter.PREFERRED_PAYMENT_UPDATED));
assertEquals(UPDATED_SERVICES, mServiceListCaptor.getAllValues().getFirst());
assertEquals(UPDATED_SERVICES, mServiceListCaptor.getAllValues().getLast());
@@ -1500,7 +1510,7 @@
@Test
public void testCardEmulationSetServiceEnabledForCategoryOther_resourceTrue()
throws RemoteException {
- when(mResources.getBoolean(R.bool.enable_service_for_category_other)).thenReturn(true);
+ when(mDeviceConfigFacade.getEnableServiceOther()).thenReturn(true);
when(mRegisteredServicesCache.registerOtherForService(anyInt(), any(), anyBoolean()))
.thenReturn(SET_SERVICE_ENABLED_STATUS_OK);
@@ -1523,7 +1533,7 @@
@Test
public void testCardEmulationSetServiceEnabledForCategoryOther_resourceFalse()
throws RemoteException {
- when(mResources.getBoolean(R.bool.enable_service_for_category_other)).thenReturn(false);
+ when(mDeviceConfigFacade.getEnableServiceOther()).thenReturn(false);
when(mRegisteredServicesCache.registerOtherForService(anyInt(), any(), anyBoolean()))
.thenReturn(SET_SERVICE_ENABLED_STATUS_OK);
@@ -2265,7 +2275,9 @@
mRoutingOptionManager,
mPowerManager,
mNfcEventLog,
- mPreferredSubscriptionService);
+ mPreferredSubscriptionService,
+ mStatsdUtils,
+ mDeviceConfigFacade);
}
@Test
@@ -2514,8 +2526,7 @@
assertThat(iNfcCardEmulation).isNotNull();
ComponentName componentName = ComponentName
.unflattenFromString("com.android.test.component/.Component");
- when(mResources.getBoolean(R.bool.enable_service_for_category_other))
- .thenReturn(true);
+ when(mDeviceConfigFacade.getEnableServiceOther()).thenReturn(true);
when(mRegisteredServicesCache.registerOtherForService(1,
componentName, true)).thenReturn(1);
int result = iNfcCardEmulation
@@ -2713,167 +2724,6 @@
}
@Test
- public void registerPollingLoopFilterForService_roleService_setsExitFrames() throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.registerPollingLoopFilterForService(anyInt(), anyInt(), any(),
- any(), anyBoolean())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq(WALLET_PAYMENT_SERVICE.getPackageName()), eq(USER_ID))).thenReturn(true);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface().registerPollingLoopFilterForService(
- USER_ID, WALLET_PAYMENT_SERVICE, "aa", true);
-
- verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void registerPollingLoopFilterForService_notRoleService_doesNotSetExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.registerPollingLoopFilterForService(anyInt(), anyInt(), any(),
- any(), anyBoolean())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq("com.android.test"), eq(USER_ID))).thenReturn(false);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface().registerPollingLoopFilterForService(
- USER_ID, new ComponentName("com.android.test", "com.android.test.Service"), "aa",
- true);
-
- verify(mNfcService, never()).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void removePollingLoopFilterForService_roleService_setsExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.removePollingLoopFilterForService(anyInt(), anyInt(), any(),
- any())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq(WALLET_PAYMENT_SERVICE.getPackageName()), eq(USER_ID))).thenReturn(true);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface().removePollingLoopFilterForService(
- USER_ID, WALLET_PAYMENT_SERVICE, "aa");
-
- verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void removePollingLoopFilterForService_notRoleService_doesNotSetExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.removePollingLoopFilterForService(anyInt(), anyInt(), any(),
- any())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq("com.android.test"), eq(USER_ID))).thenReturn(false);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface().removePollingLoopFilterForService(
- USER_ID, new ComponentName("com.android.test", "com.android.test.Service"), "aa");
-
- verify(mNfcService, never()).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void registerPollingLoopPatternFilterForService_roleService_setsExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.registerPollingLoopPatternFilterForService(anyInt(), anyInt(),
- any(), any(), anyBoolean())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq(WALLET_PAYMENT_SERVICE.getPackageName()), eq(USER_ID))).thenReturn(true);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface()
- .registerPollingLoopPatternFilterForService(
- USER_ID, WALLET_PAYMENT_SERVICE, "aa", true);
-
- verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void registerPollingLoopPatternFilterForService_notRoleService_doesNotSetExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.registerPollingLoopPatternFilterForService(anyInt(), anyInt(),
- any(), any(), anyBoolean())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq("com.android.test"), eq(USER_ID))).thenReturn(false);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface()
- .registerPollingLoopPatternFilterForService(
- USER_ID,
- new ComponentName("com.android.test", "com.android.test.Service"),
- "aa",
- true);
-
- verify(mNfcService, never()).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void removePollingLoopPatternFilterForService_roleService_setsExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.removePollingLoopPatternFilterForService(anyInt(), anyInt(),
- any(), any())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq(WALLET_PAYMENT_SERVICE.getPackageName()), eq(USER_ID))).thenReturn(true);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface()
- .removePollingLoopPatternFilterForService(
- USER_ID, WALLET_PAYMENT_SERVICE, "aa");
-
- verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
- public void removePollingLoopPatternFilterForService_notRoleService_doesNotSetExitFrames()
- throws Exception {
- when(Flags.exitFrames()).thenReturn(true);
- when(mNfcService.isFirmwareExitFramesSupported()).thenReturn(true);
- when(mNfcService.getNumberOfFirmwareExitFramesSupported()).thenReturn(5);
- when(mRegisteredServicesCache.hasService(eq(USER_ID), any())).thenReturn(true);
- when(mRegisteredServicesCache.removePollingLoopPatternFilterForService(anyInt(), anyInt(),
- any(), any())).thenReturn(true);
- when(mRegisteredAidCache.isDefaultOrAssociatedWalletPackage(
- eq("com.android.test"), eq(USER_ID))).thenReturn(false);
- when(mRegisteredServicesCache.getServices(USER_ID)).thenReturn(List.of());
-
- mCardEmulationManager.getNfcCardEmulationInterface()
- .removePollingLoopPatternFilterForService(
- USER_ID,
- new ComponentName("com.android.test", "com.android.test.Service"),
- "aa");
-
- verify(mNfcService, never()).setFirmwareExitFrameTable(any(), anyInt());
- }
-
- @Test
public void testDump() {
FileDescriptor fd = mock(FileDescriptor.class);
PrintWriter pw = mock(PrintWriter.class);
@@ -3367,4 +3217,20 @@
verify(mContext).createPackageContextAsUser("android", 0, userHandle);
verify(pm, never()).getApplicationInfo(anyString(), eq(0));
}
+
+ @Test
+ public void testOnObserveModeDisabledInFirmware() {
+ PollingFrame exitFrame = new PollingFrame(
+ PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
+ HexFormat.of().parseHex("42123456"),
+ 0,
+ 0,
+ true);
+
+ mCardEmulationManager.onObserveModeDisabledInFirmware(exitFrame);
+
+ verify(mHostEmulationManager).onObserveModeDisabledInFirmware(exitFrame);
+ verify(mStatsdUtils).logAutoTransactReported(StatsdUtils.PROCESSOR_NFCC,
+ exitFrame.getData());
+ }
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/handover/BluetoothPeripheralHandoverTest.java b/NfcNci/tests/unit/src/com/android/nfc/handover/BluetoothPeripheralHandoverTest.java
index 1d88fe3..d8aeb8a 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/handover/BluetoothPeripheralHandoverTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/handover/BluetoothPeripheralHandoverTest.java
@@ -69,6 +69,8 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.nfc.DeviceConfigFacade;
+import com.android.nfc.NfcInjector;
import org.junit.After;
import org.junit.Before;
@@ -114,18 +116,25 @@
Intent mockIntent;
@Mock
BluetoothA2dp mockA2dp;
+ @Mock
+ DeviceConfigFacade mDeviceConfigFacade;
private MockitoSession mStaticMockSession;
BluetoothPeripheralHandover bluetoothPeripheralHandover;
@Before
public void setUp() {
- mStaticMockSession = ExtendedMockito.mockitoSession().mockStatic(
- Settings.Global.class).mockStatic(Toast.class).strictness(
- Strictness.LENIENT).startMocking();
+ mStaticMockSession = ExtendedMockito.mockitoSession()
+ .mockStatic(Settings.Global.class)
+ .mockStatic(Toast.class)
+ .mockStatic(NfcInjector.class)
+ .strictness(Strictness.LENIENT).startMocking();
MockitoAnnotations.initMocks(this);
when(mockContext.getSystemService(AudioManager.class)).thenReturn(mockAudioManager);
when(mockContext.getContentResolver()).thenReturn(mockContentResolver);
when(mockContext.getResources()).thenReturn(mockResources);
+ NfcInjector nfcInjector = mock(NfcInjector.class);
+ when(NfcInjector.getInstance()).thenReturn(nfcInjector);
+ when(nfcInjector.getDeviceConfigFacade()).thenReturn(mDeviceConfigFacade);
when(Toast.makeText(any(), anyString(), anyInt())).thenReturn(mockToast);
bluetoothPeripheralHandover = createBluetoothPerHandOvrInstance(
BluetoothDevice.TRANSPORT_LE);
diff --git a/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java b/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java
index d66ebf3..143cae2 100644
--- a/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java
+++ b/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java
@@ -22,32 +22,44 @@
import android.util.Log;
import com.android.nfc.service.PaymentService1;
-import com.android.nfc.service.TransportService1;
+import java.util.ArrayList;
import java.util.HexFormat;
+import java.util.List;
+import java.util.regex.Pattern;
public class ExitFrameEmulatorActivity extends BaseEmulatorActivity {
private static final String TAG = "ExitFrameEmulatorActivity";
public static final String EXIT_FRAME_KEY = "EXIT_FRAME";
+ public static final String REGISTER_PATTERNS_KEY = "REGISTER_PATTERNS";
+ public static final String WAIT_FOR_TRANSACTION_KEY = "WAIT_FOR_TRANSACTION";
private String mReceivedExitFrame = null;
private String mIntendedExitFrameData = null;
+ private final List<String> mRegisteredPatterns = new ArrayList<>();
+ private boolean mWaitForTransaction = true;
+ private ComponentName mServiceName = null;
private final CardEmulation.NfcEventCallback mEventListener =
new CardEmulation.NfcEventCallback() {
- public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
- if (exitFrame != null) {
- mReceivedExitFrame = HexFormat.of().formatHex(exitFrame.getData());
- Log.d(TAG, "Received exit frame: " + mReceivedExitFrame);
- }
- }
- };
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
+ if (exitFrame != null) {
+ mReceivedExitFrame = HexFormat.of().formatHex(exitFrame.getData());
+ Log.d(TAG, "Received exit frame: " + mReceivedExitFrame);
+ }
+
+ if (!mWaitForTransaction) {
+ verifyExitFrameAndPassTest();
+ }
+ }
+ };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mIntendedExitFrameData = getIntent().getStringExtra(EXIT_FRAME_KEY);
+ mWaitForTransaction = getIntent().getBooleanExtra(WAIT_FOR_TRANSACTION_KEY, true);
setupServices(PaymentService1.COMPONENT);
makeDefaultWalletRoleHolder();
@@ -55,29 +67,38 @@
public void onResume() {
super.onResume();
- ComponentName serviceName =
+ mServiceName =
new ComponentName(this.getApplicationContext(), PaymentService1.class);
- mCardEmulation.setPreferredService(this, serviceName);
+ mCardEmulation.setPreferredService(this, mServiceName);
waitForPreferredService();
mReceivedExitFrame = null;
registerEventListener(mEventListener);
+
+ if (getIntent().hasExtra(REGISTER_PATTERNS_KEY)) {
+ getIntent().getStringArrayListExtra(REGISTER_PATTERNS_KEY).forEach(
+ plpf -> {
+ mCardEmulation.registerPollingLoopPatternFilterForService(mServiceName,
+ plpf, true);
+ mRegisteredPatterns.add(plpf);
+ }
+ );
+ }
}
@Override
public void onPause() {
super.onPause();
+ mRegisteredPatterns.forEach(
+ plpf -> mCardEmulation.removePollingLoopPatternFilterForService(mServiceName,
+ plpf));
mCardEmulation.unsetPreferredService(this);
}
@Override
public void onApduSequenceComplete(ComponentName component, long duration) {
- boolean success = mIntendedExitFrameData.equals(mReceivedExitFrame);
-
- if (success) {
- setTestPassed();
- }
+ verifyExitFrameAndPassTest();
}
@Override
@@ -87,7 +108,20 @@
}
@Override
- public ComponentName getPreferredServiceComponent(){
- return TransportService1.COMPONENT;
+ public ComponentName getPreferredServiceComponent() {
+ return PaymentService1.COMPONENT;
+ }
+
+ private void verifyExitFrameAndPassTest() {
+ if (mIntendedExitFrameData == null || mReceivedExitFrame == null) {
+ return;
+ }
+
+ boolean success =
+ Pattern.compile(mIntendedExitFrameData).matcher(mReceivedExitFrame).matches();
+
+ if (success) {
+ setTestPassed();
+ }
}
}
\ No newline at end of file
diff --git a/NfcNci/testutils/src/com/android/nfc/emulator/NfcEmulatorDeviceSnippet.java b/NfcNci/testutils/src/com/android/nfc/emulator/NfcEmulatorDeviceSnippet.java
index dba810d..832c803 100644
--- a/NfcNci/testutils/src/com/android/nfc/emulator/NfcEmulatorDeviceSnippet.java
+++ b/NfcNci/testutils/src/com/android/nfc/emulator/NfcEmulatorDeviceSnippet.java
@@ -29,6 +29,7 @@
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
+import com.android.compatibility.common.util.CommonTestUtils;
import com.android.nfc.service.AccessServiceTurnObserveModeOnProcessApdu;
import com.android.nfc.utils.CommandApdu;
import com.android.nfc.utils.HceUtils;
@@ -413,7 +414,8 @@
}
@Rpc(description = "Opens the Exit Frame Activity")
- public void startExitFrameActivity(String intendedExitFrame) {
+ public void startExitFrameActivity(String intendedExitFrame, String[] plpfs,
+ boolean waitForTransaction) {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -421,6 +423,9 @@
intent.setClassName(instrumentation.getTargetContext(),
ExitFrameEmulatorActivity.class.getName());
intent.putExtra(ExitFrameEmulatorActivity.EXIT_FRAME_KEY, intendedExitFrame);
+ intent.putStringArrayListExtra(ExitFrameEmulatorActivity.REGISTER_PATTERNS_KEY,
+ new ArrayList<>(Arrays.asList(plpfs)));
+ intent.putExtra(ExitFrameEmulatorActivity.WAIT_FOR_TRANSACTION_KEY, waitForTransaction);
mActivity = (ExitFrameEmulatorActivity) instrumentation.startActivitySync(intent);
}
@@ -559,6 +564,14 @@
public void closeActivity() {
if (mActivity != null) {
mActivity.finish();
+ try {
+ CommonTestUtils.waitUntil(
+ "Activity didn't finish in 5 seconds",
+ 5,
+ () -> mActivity.isDestroyed()
+ );
+ } catch (InterruptedException | AssertionError e) {
+ }
}
}
diff --git a/libnfc-nci/src/adaptation/NfcAdaptation.cc b/libnfc-nci/src/adaptation/NfcAdaptation.cc
index 62b7df0..2cb10dc 100644
--- a/libnfc-nci/src/adaptation/NfcAdaptation.cc
+++ b/libnfc-nci/src/adaptation/NfcAdaptation.cc
@@ -1005,6 +1005,9 @@
void NfcAdaptation::HalClose() {
const char* func = "NfcAdaptation::HalClose";
LOG(VERBOSE) << StringPrintf("%s", func);
+ if (sVndExtnsPresent) {
+ sNfcVendorExtn->processEvent(HANDLE_NFC_HAL_CLOSE, HAL_NFC_STATUS_OK);
+ }
if (mAidlHal != nullptr) {
mAidlHal->close(NfcCloseType::DISABLE);
} else if (mHal != nullptr) {
@@ -1056,6 +1059,10 @@
uint8_t* p_core_init_rsp_params) {
const char* func = "NfcAdaptation::HalCoreInitialized";
LOG(VERBOSE) << StringPrintf("%s", func);
+ if (sVndExtnsPresent) {
+ sNfcVendorExtn->processEvent(HANDLE_NFC_HAL_CORE_INITIALIZE,
+ HAL_NFC_STATUS_OK);
+ }
if (mAidlHal != nullptr) {
// AIDL coreInitialized doesn't send data to HAL.
mAidlHal->coreInitialized();
@@ -1140,6 +1147,9 @@
void NfcAdaptation::HalPowerCycle() {
const char* func = "NfcAdaptation::HalPowerCycle";
LOG(VERBOSE) << StringPrintf("%s", func);
+ if (sVndExtnsPresent) {
+ sNfcVendorExtn->processEvent(HANDLE_NFC_HAL_POWER_CYCLE, HAL_NFC_STATUS_OK);
+ }
if (mAidlHal != nullptr) {
mAidlHal->powerCycle();
} else if (mHal != nullptr) {
@@ -1159,7 +1169,9 @@
uint8_t NfcAdaptation::HalGetMaxNfcee() {
const char* func = "NfcAdaptation::HalGetMaxNfcee";
LOG(VERBOSE) << StringPrintf("%s", func);
-
+ if (sVndExtnsPresent) {
+ sNfcVendorExtn->processEvent(HANDLE_NFC_GET_MAX_NFCEE, HAL_NFC_STATUS_OK);
+ }
return nfa_ee_max_ee_cfg;
}
diff --git a/libnfc-nci/src/gki/common/gki_buffer.cc b/libnfc-nci/src/gki/common/gki_buffer.cc
index 5a69ca6..b461382 100644
--- a/libnfc-nci/src/gki/common/gki_buffer.cc
+++ b/libnfc-nci/src/gki/common/gki_buffer.cc
@@ -120,7 +120,10 @@
**
*******************************************************************************/
void gki_buffer_init(void) {
- uint8_t i, tt, mb;
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ uint8_t i;
+#endif
+ uint8_t tt, mb;
tGKI_COM_CB* p_cb = &gki_cb.com;
/* Initialize mailboxes */
@@ -211,10 +214,12 @@
gki_init_free_queue(15, GKI_BUF15_SIZE, GKI_BUF15_MAX, p_cb->bufpool15);
#endif
- /* add pools to the pool_list which is arranged in the order of size */
+/* add pools to the pool_list which is arranged in the order of size */
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
for (i = 0; i < GKI_NUM_FIXED_BUF_POOLS; i++) {
p_cb->pool_list[i] = i;
}
+#endif
p_cb->curr_total_no_of_pools = GKI_NUM_FIXED_BUF_POOLS;
diff --git a/libnfc-nci/src/nfa/hci/nfa_hci_utils.cc b/libnfc-nci/src/nfa/hci/nfa_hci_utils.cc
index 98f7822..ca2f119 100644
--- a/libnfc-nci/src/nfa/hci/nfa_hci_utils.cc
+++ b/libnfc-nci/src/nfa/hci/nfa_hci_utils.cc
@@ -303,6 +303,10 @@
bool first_pkt = true;
uint16_t data_len;
tNFA_STATUS status = NFA_STATUS_OK;
+ if ((msg_len != 0) && (p_msg == nullptr)) {
+ LOG(ERROR) << StringPrintf("%s: msg_len is 0 and p_msg is null", __func__);
+ return NFA_STATUS_FAILED;
+ }
uint16_t max_seg_hcp_pkt_size;
if (nfa_hci_cb.buff_size > (NCI_DATA_HDR_SIZE + 2)) {
max_seg_hcp_pkt_size = nfa_hci_cb.buff_size - NCI_DATA_HDR_SIZE;
diff --git a/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc b/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc
index 76af1cc..602f43f 100644
--- a/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc
+++ b/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc
@@ -16,22 +16,19 @@
#include "NfcVendorExtn.h"
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android/log.h>
#include <dlfcn.h>
#include <error.h>
#include <log/log.h>
+#include <string>
using android::base::StringPrintf;
#define UNUSED_PROP(X) (void)(X);
-std::string mLibName = "libnfc_vendor_extn.so";
-#if (defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64))
-std::string mLibPathName = "/system/lib64/" + mLibName;
-#else
-std::string mLibPathName = "/system/lib/" + mLibName;
-#endif
const std::string vendor_nfc_init_name = "vendor_nfc_init";
const std::string vendor_nfc_de_init_name = "vendor_nfc_de_init";
const std::string vendor_nfc_handle_event_name = "vendor_nfc_handle_event";
@@ -52,9 +49,47 @@
fp_extn_on_config_update_t fp_extn_on_config_update = NULL;
NfcExtEventData_t mNfcExtEventData;
+std::string mLibPathName = "";
void* p_oem_extn_handle = NULL;
+namespace {
+ std::string searchLibPath(std::string file_name) {
+ const std::vector<std::string> search_path = {
+ "/system/lib/", "/system/lib64/"
+ };
+ for (std::string path : search_path) {
+ path.append(file_name);
+ struct stat file_stat;
+ if (stat(path.c_str(), &file_stat) != 0) continue;
+ if (S_ISREG(file_stat.st_mode)) return path;
+ }
+ return "";
+ }
+ // Extension library file Search sequence
+ // 1. If prop_lib_file_name is defined.(where prop_config_file_name is the
+ // value of the property persist.nfc_vendor_extn.lib_file_name)
+ // Search a file matches prop_lib_file_name.
+ // 2. If SKU is defined (where SKU is the value of the property
+ // ro.boot.product.hardware.sku)
+ // Search a file matches libnfc_vendor_extn-SKU.so
+ // 3. If none of 1,2 is defined, search a default file name "libnfc_vendor_extn.so".
+ std::string findLibPath() {
+ std::string f_path = searchLibPath(
+ android::base::GetProperty("persist.nfc_vendor_extn.lib_file_name", ""));
+ if (!f_path.empty()) return f_path;
+
+ // Search for libnfc_vendor_extn-SKU.so
+ f_path = searchLibPath(
+ "libnfc_vendor_extn-" +
+ android::base::GetProperty("ro.boot.product.hardware.sku", "") + ".so");
+ if (!f_path.empty()) return f_path;
+
+ // load default file if the desired file not found.
+ return searchLibPath("libnfc_vendor_extn.so");
+ }
+} // namespace
+
NfcVendorExtn::NfcVendorExtn() {}
NfcVendorExtn::~NfcVendorExtn() { sNfcVendorExtn = nullptr; }
@@ -78,6 +113,12 @@
bool NfcExtn_LibSetup() {
LOG(VERBOSE) << __func__;
+ mLibPathName = findLibPath();
+ if (mLibPathName.empty()) {
+ LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
+ mLibPathName.c_str());
+ return false;
+ }
p_oem_extn_handle = dlopen(mLibPathName.c_str(), RTLD_NOW);
if (p_oem_extn_handle == NULL) {
LOG(DEBUG) << StringPrintf(
@@ -209,7 +250,7 @@
}
}
if (p_oem_extn_handle != NULL) {
- LOG(DEBUG) << StringPrintf("%s: Closing %s!!", __func__, mLibName.c_str());
+ LOG(DEBUG) << StringPrintf("%s: Closing %s!!", __func__, mLibPathName.c_str());
dlclose(p_oem_extn_handle);
p_oem_extn_handle = NULL;
}
diff --git a/libnfc-nci/src/nfc_vendor_extn/include/NfcVendorExtn.h b/libnfc-nci/src/nfc_vendor_extn/include/NfcVendorExtn.h
index 95ab51b..7d35fa8 100644
--- a/libnfc-nci/src/nfc_vendor_extn/include/NfcVendorExtn.h
+++ b/libnfc-nci/src/nfc_vendor_extn/include/NfcVendorExtn.h
@@ -90,6 +90,10 @@
HANDLE_DOWNLOAD_FIRMWARE_REQUEST,
HANDLE_NFC_ADAPTATION_INIT,
HANDLE_NFC_PRE_DISCOVER,
+ HANDLE_NFC_HAL_CORE_INITIALIZE,
+ HANDLE_NFC_HAL_POWER_CYCLE,
+ HANDLE_NFC_GET_MAX_NFCEE,
+ HANDLE_NFC_HAL_CLOSE,
} NfcExtEvent_t;
typedef enum {