Merge "[nfc] Standardized interface declaration definition in packages/modules/Nfc/apex/hiddenapi/hiddenapi-max-target-o.txt for NfcAdapter.java" into main
diff --git a/NfcNci/nci/jni/NativeNfcManager.cpp b/NfcNci/nci/jni/NativeNfcManager.cpp
index 704e827..f6c769f 100644
--- a/NfcNci/nci/jni/NativeNfcManager.cpp
+++ b/NfcNci/nci/jni/NativeNfcManager.cpp
@@ -114,6 +114,8 @@
jmethodID gCachedNfcManagerNotifyEeTechSelected;
jmethodID gCachedNfcManagerNotifyEeListenActivated;
jmethodID gCachedNfcManagerOnRestartRfDiscovery;
+jmethodID gCachedNfcManagerOnObserveModeDisabledInFirmware;
+jmethodID gCachedNfcManagerOnObserveModeEnabledInFirmware;
jmethodID gCachedNfcManagerNotifyEndpointRemoved;
const char* gNativeNfcTagClassName = "com/android/nfc/dhimpl/NativeNfcTag";
@@ -149,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
@@ -269,6 +271,16 @@
LOG(DEBUG) << StringPrintf("%s: ", __func__);
+ if (gIsSelectingRfInterface && !natTag.getMultiProtocolTagSupport()) {
+ if (discoveredDevice->more == NCI_DISCOVER_NTF_MORE) return;
+ LOG(WARNING) << StringPrintf(
+ "%s: reselecting, mismatch in nb of detected interfaces, "
+ "restarting discovery",
+ __func__);
+ nativeNfcTag_doConnectStatus(false);
+ natTag.setReselect(false);
+ NFA_Deactivate(FALSE);
+ }
if (discoveredDevice->protocol != NFA_PROTOCOL_NFC_DEP) {
natTag.setNumDiscNtf(natTag.getNumDiscNtf() + 1);
}
@@ -410,6 +422,9 @@
LOG(ERROR) << StringPrintf(
"%s: NFA_SELECT_RESULT_EVT error: status = %d", __func__,
eventData->status);
+ if (NfcTag::getInstance().retrySelect() == NFA_STATUS_OK) {
+ break;
+ }
NFA_Deactivate(FALSE);
}
break;
@@ -421,6 +436,7 @@
case NFA_ACTIVATED_EVT: // NFC link/protocol activated
{
+ bool notListen = !isListenMode(eventData->activated);
LOG(DEBUG) << StringPrintf(
"%s: NFA_ACTIVATED_EVT: gIsSelectingRfInterface=%d, sIsDisabling=%d",
__func__, gIsSelectingRfInterface, sIsDisabling);
@@ -434,6 +450,7 @@
/* T5T doesn't support multiproto detection logic */
NfcTag::getInstance().setNumDiscNtf(0);
}
+ NfcTag::getInstance().clearSelectRetryCount();
if ((eventData->activated.activate_ntf.protocol !=
NFA_PROTOCOL_NFC_DEP) &&
(!isListenMode(eventData->activated))) {
@@ -442,47 +459,48 @@
nativeNfcTag_setActivatedRfProtocol(activatedProtocol);
nativeNfcTag_setActivatedRfMode(activatedMode);
}
- NfcTag::getInstance().setActive(true);
+ NfcTag::getInstance().setActive(notListen);
if (sIsDisabling || !sIsNfaEnabled) break;
gActivated = true;
- updateNfcID0Param(
- eventData->activated.activate_ntf.rf_tech_param.param.pb.nfcid0);
- NfcTag::getInstance().setActivationState();
- if (gIsSelectingRfInterface) {
- nativeNfcTag_doConnectStatus(true);
- break;
- }
-
- nativeNfcTag_resetPresenceCheck();
- if (!isListenMode(eventData->activated) &&
- (prevScreenState == NFA_SCREEN_STATE_OFF_LOCKED ||
- prevScreenState == NFA_SCREEN_STATE_OFF_UNLOCKED)) {
- if (!sIsAlwaysPolling) {
- NFA_Deactivate(FALSE);
+ if (notListen) {
+ updateNfcID0Param(
+ eventData->activated.activate_ntf.rf_tech_param.param.pb.nfcid0);
+ NfcTag::getInstance().setActivationState();
+ if (gIsSelectingRfInterface) {
+ nativeNfcTag_doConnectStatus(true);
+ break;
}
- }
- NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
- if (NfcTag::getInstance().getNumDiscNtf()) {
- /*If its multiprotocol tag, deactivate tag with current selected
- protocol to sleep . Select tag with next supported protocol after
- deactivation event is received*/
- if (((tNFA_INTF_TYPE)eventData->activated.activate_ntf.intf_param
- .type == NFA_INTERFACE_FRAME)) {
- uint8_t RW_TAG_SLP_REQ[] = {0x50, 0x00};
- SyncEvent waitSome;
- SyncEventGuard g(waitSome);
- NFA_SendRawFrame(RW_TAG_SLP_REQ, sizeof(RW_TAG_SLP_REQ), 0);
- waitSome.wait(4);
+ nativeNfcTag_resetPresenceCheck();
+ if (!isListenMode(eventData->activated) &&
+ (prevScreenState == NFA_SCREEN_STATE_OFF_LOCKED ||
+ prevScreenState == NFA_SCREEN_STATE_OFF_UNLOCKED)) {
+ if (!sIsAlwaysPolling) {
+ NFA_Deactivate(FALSE);
+ }
}
- NFA_Deactivate(true);
- }
- // If it activated in
- // listen mode then it is likely for an SE transaction.
- // Send the RF Event.
- if (isListenMode(eventData->activated)) {
+ NfcTag::getInstance().connectionEventHandler(connEvent, eventData);
+ if (NfcTag::getInstance().getNumDiscNtf()) {
+ /*If its multiprotocol tag, deactivate tag with current selected
+ protocol to sleep . Select tag with next supported protocol after
+ deactivation event is received*/
+ if (((tNFA_INTF_TYPE)eventData->activated.activate_ntf.intf_param
+ .type == NFA_INTERFACE_FRAME)) {
+ uint8_t RW_TAG_SLP_REQ[] = {0x50, 0x00};
+ SyncEvent waitSome;
+ SyncEventGuard g(waitSome);
+ NFA_SendRawFrame(RW_TAG_SLP_REQ, sizeof(RW_TAG_SLP_REQ), 0);
+ waitSome.wait(4);
+ }
+ NFA_Deactivate(true);
+ }
+
+ } else {
+ // If it activated in
+ // listen mode then it is likely for an SE transaction.
+ // Send the RF Event.
sSeRfActive = true;
struct nfc_jni_native_data* nat = getNative(NULL, NULL);
if (!nat) {
@@ -505,7 +523,7 @@
"%s: NFA_DEACTIVATED_EVT Type=%u, gIsTagDeactivating=%d", __func__,
eventData->deactivated.type, gIsTagDeactivating);
NfcTag::getInstance().setDeactivationState(eventData->deactivated);
- NfcTag::getInstance().selectNextTagIfExists();
+
if (eventData->deactivated.type != NFA_DEACTIVATE_TYPE_SLEEP) {
{
SyncEventGuard g(gDeactivatedEvent);
@@ -519,6 +537,8 @@
} else if (gIsTagDeactivating) {
NfcTag::getInstance().setActive(false);
nativeNfcTag_doDeactivateStatus(0);
+ } else if (!sIsDisabling) {
+ NfcTag::getInstance().selectNextTagIfExists();
}
// If RF is activated for what we think is a Secure Element transaction
@@ -806,6 +826,12 @@
gCachedNfcManagerOnRestartRfDiscovery =
e->GetMethodID(cls.get(), "onRestartRfDiscovery", "()V");
+ gCachedNfcManagerOnObserveModeDisabledInFirmware =
+ e->GetMethodID(cls.get(), "onObserveModeDisabledInFirmware", "(I[B)V");
+
+ gCachedNfcManagerOnObserveModeEnabledInFirmware =
+ e->GetMethodID(cls.get(), "onObserveModeEnabledInFirmware", "()V");
+
if (nfc_jni_cache_object(e, gNativeNfcTagClassName, &(nat->cached_NfcTag)) ==
-1) {
LOG(ERROR) << StringPrintf("%s: fail cache NativeNfcTag", __func__);
@@ -1209,7 +1235,64 @@
e->CallVoidMethod(nat->manager,
android::gCachedNfcManagerNotifyPollingLoopFrame,
(jint)param_len, dataJavaArray.get());
-
+ } break;
+ case NCI_ANDROID_PASSIVE_OBSERVER_SUSPENDED_NTF: {
+ LOG(INFO) << "Observe mode suspended NTF received";
+ gObserveModeEnabled = false;
+ struct nfc_jni_native_data* nat = getNative(NULL, NULL);
+ if (!nat) {
+ LOG(ERROR) << StringPrintf("cached nat is null");
+ return;
+ }
+ JNIEnv* e = NULL;
+ ScopedAttach attach(nat->vm, &e);
+ if (e == NULL) {
+ LOG(ERROR) << StringPrintf("jni env is null");
+ return;
+ }
+ if (param_len <= 2) {
+ LOG(ERROR) <<
+ "Cannot parse exit frame from NCI_ANDROID_PASSIVE_OBSERVER_SUSPENDED_NTF";
+ return;
+ }
+ jint exit_frame_type = (jint) p_param[4];
+ uint16_t exit_frame_len = p_param[5];
+ ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(exit_frame_len));
+ if (dataJavaArray.get() == NULL) {
+ LOG(ERROR) << "fail allocate array";
+ return;
+ }
+ if (exit_frame_len > 0) {
+ e->SetByteArrayRegion((jbyteArray)dataJavaArray.get(), 0, exit_frame_len,
+ (jbyte*)(p_param + 6));
+ if (e->ExceptionCheck()) {
+ e->ExceptionClear();
+ LOG(ERROR) << "failed to fill array";
+ return;
+ }
+ }
+ e->CallVoidMethod(nat->manager,
+ android::gCachedNfcManagerOnObserveModeDisabledInFirmware,
+ exit_frame_type, dataJavaArray.get());
+ return;
+ } break;
+ case NCI_ANDROID_PASSIVE_OBSERVER_RESUMED_NTF: {
+ LOG(INFO) << "Observe mode resumed NTF received";
+ gObserveModeEnabled = true;
+ struct nfc_jni_native_data *nat = getNative(NULL, NULL);
+ if (!nat) {
+ LOG(ERROR) << StringPrintf("cached nat is null");
+ return;
+ }
+ JNIEnv *e = NULL;
+ ScopedAttach attach(nat->vm, &e);
+ if (e == NULL) {
+ LOG(ERROR) << StringPrintf("jni env is null");
+ return;
+ }
+ e->CallVoidMethod(nat->manager,
+ android::gCachedNfcManagerOnObserveModeEnabledInFirmware);
+ return;
} break;
case NCI_ANDROID_RESTART_RF_DISCOVERY_REQUEST_NTF: {
struct nfc_jni_native_data* nat = getNative(NULL, NULL);
@@ -1698,26 +1781,30 @@
}
}
+static bool isReaderModeAnnotationSupported(JNIEnv* e, jobject o) {
+ ScopedLocalRef<jclass> cls(e, e->GetObjectClass(o));
+ jmethodID isSupported =
+ e->GetMethodID(cls.get(), "isReaderModeAnnotationSupportedCaps", "()Z");
+ return e->CallBooleanMethod(o, isSupported);
+}
+
static tNFA_STATUS setTechAPollingLoopAnnotation(JNIEnv* env, jobject o,
- jbyteArray tech_a_polling_loop_annotation) {
- if (tech_a_polling_loop_annotation == NULL) {
- LOG(WARNING) << __func__ << ": annotation is null, returning early";
- return STATUS_SUCCESS;
- }
+ 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);
- command.push_back(0x01);
- command.push_back(0x00);
-
- ScopedByteArrayRO annotationBytes(env, tech_a_polling_loop_annotation);
- command.push_back(annotationBytes.size() + 3);
- command.push_back(0x0a);
- if (annotationBytes.size() > 0) {
- command.insert(command.end(), &annotationBytes[0],
- &annotationBytes[annotationBytes.size()]);
+ if (annotation_data == NULL || annotation_size == 0) {
+ // Annotation is null or size is 0, setting 0 annotations
+ command.push_back(0x00);
+ } else {
+ 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);
@@ -1728,6 +1815,8 @@
__FUNCTION__);
gVSCmdStatus = NFA_STATUS_FAILED;
}
+ } else {
+ gVSCmdStatus = status;
}
return gVSCmdStatus;
}
@@ -1778,7 +1867,21 @@
// Check polling configuration
if (tech_mask != 0) {
stopPolling_rfDiscoveryDisabled();
- setTechAPollingLoopAnnotation(e, o, tech_a_polling_loop_annotation);
+ if (isReaderModeAnnotationSupported(e, o)) {
+ 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);
@@ -1917,7 +2020,8 @@
*******************************************************************************/
static jboolean nfcManager_doDeinitialize(JNIEnv*, jobject) {
if (sIsShuttingDown) return false;
- LOG(DEBUG) << StringPrintf("%s: enter", __func__);
+ LOG(DEBUG) << StringPrintf("%s: enter, sIsRecovering=%d", __func__,
+ sIsRecovering);
if (gPartialInitMode != ENABLE_MODE_DEFAULT) {
return doPartialDeinit();
}
@@ -1938,10 +2042,13 @@
NFA_DisableDtamode();
}
- tNFA_STATUS stat = NFA_Disable(TRUE /* graceful */);
+ tNFA_STATUS stat = NFA_Disable(!sIsRecovering);
if (stat == NFA_STATUS_OK) {
LOG(DEBUG) << StringPrintf("%s: wait for completion", __func__);
- sNfaDisableEvent.wait(); // wait for NFA command to finish
+ if (!sNfaDisableEvent.wait(5000)) {
+ LOG(ERROR) << StringPrintf(
+ "%s: NFA_Disable() timeout, keep disabling anyway", __func__);
+ }
} else {
LOG(ERROR) << StringPrintf("%s: fail disable; error=0x%X", __func__,
stat);
@@ -1957,6 +2064,7 @@
sIsDisabling = false;
sReaderModeEnabled = false;
gActivated = false;
+ sRfEnabled = false;
sLfT3tMax = 0;
{
@@ -1967,6 +2075,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();
@@ -2052,7 +2189,7 @@
static void nfcManager_doResetTimeouts(JNIEnv*, jobject) {
if (sIsShuttingDown) return;
LOG(DEBUG) << StringPrintf("%s", __func__);
- NfcTag::getInstance().resetAllTransceiveTimeouts();
+ NfcTag::getInstance().resetAllTransceiveTimeouts(true);
}
/*******************************************************************************
@@ -2997,6 +3134,12 @@
std::vector<uint8_t> command;
command.push_back(NCI_ANDROID_SET_PASSIVE_OBSERVER_EXIT_FRAME);
+ // TODO(b/380455428)
+ // Support more than 5 exit frames if firmware allows it. If we do so, might need to send second
+ // NCI command if one is too large.
+ uint8_t more = 0x00;
+ command.push_back(more);
+
uint8_t timeout_len = env->GetArrayLength(timeout);
auto* timeout_arr = (uint8_t*)env->GetByteArrayElements(timeout, nullptr);
@@ -3006,6 +3149,12 @@
env->ReleaseByteArrayElements(timeout, (jbyte*)timeout_arr, JNI_ABORT);
uint8_t num_exit_frames = env->GetArrayLength(exit_frames);
+ if (num_exit_frames > 5) {
+ LOG(INFO)
+ << "Truncating exit frame table to 5 frames so it fits in a single NCI command. "
+ << "Original size was " << num_exit_frames;
+ num_exit_frames = 5;
+ }
command.push_back(num_exit_frames);
if (num_exit_frames > 0) {
diff --git a/NfcNci/nci/jni/NativeNfcTag.cpp b/NfcNci/nci/jni/NativeNfcTag.cpp
index 2222172..896889c 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__);
@@ -716,6 +727,9 @@
if (!sReselectTagIdle) {
LOG(DEBUG) << StringPrintf("%s: select interface 0x%x", __func__,
rfInterface);
+ natTag.setLastSelectedTag(
+ natTag.mTechHandles[sCurrentConnectedTargetIdx],
+ natTag.mTechLibNfcTypes[sCurrentConnectedTargetIdx]);
if (NFA_STATUS_OK !=
(status =
NFA_Select(natTag.mTechHandles[sCurrentConnectedTargetIdx],
@@ -735,12 +749,14 @@
}
/*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;
- sConnectWaitingForComplete = JNI_TRUE;
do {
+ // Nci retries on failures by restarting discovery, extend recovery
+ // duration till time out
+ sConnectWaitingForComplete = JNI_TRUE;
SyncEventGuard reselectEvent(sReconnectEvent);
if (sReconnectEvent.wait(500) == false) { // if timeout occurred
LOG(ERROR) << StringPrintf("%s: timeout ", __func__);
@@ -792,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;
@@ -851,7 +876,12 @@
LOG(DEBUG) << StringPrintf("%s: enter", __func__);
tNFA_STATUS nfaStat = NFA_STATUS_OK;
- NfcTag::getInstance().resetAllTransceiveTimeouts();
+ if (sIsDisabling) {
+ LOG(ERROR) << StringPrintf("%s: NFC disabling in progress", __func__);
+ return JNI_FALSE;
+ }
+ sIsDisconnecting = true;
+ NfcTag::getInstance().resetAllTransceiveTimeouts(false);
sReselectTagIdle = false;
if (NfcTag::getInstance().getActivationState() != NfcTag::Active &&
@@ -866,6 +896,7 @@
nfaStat);
TheEnd:
+ sIsDisconnecting = false;
LOG(DEBUG) << StringPrintf("%s: exit", __func__);
return (nfaStat == NFA_STATUS_OK) ? JNI_TRUE : JNI_FALSE;
}
@@ -934,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) {
@@ -1187,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
@@ -1324,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
@@ -1574,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)",
@@ -1640,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/NfcTag.cpp b/NfcNci/nci/jni/NfcTag.cpp
index 8d9239c..a20fda4 100755
--- a/NfcNci/nci/jni/NfcTag.cpp
+++ b/NfcNci/nci/jni/NfcTag.cpp
@@ -776,7 +776,11 @@
pollBytes.reset(e->NewByteArray(2));
e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*)data);
} else {
- LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn);
+ if (NFC_DISCOVERY_TYPE_POLL_KOVIO == mTechParams[i].mode) {
+ LOG(DEBUG) << StringPrintf("%s: Thinfilm", fn);
+ } else {
+ LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn);
+ }
pollBytes.reset(e->NewByteArray(0));
} // switch: every type of technology
e->SetObjectArrayElement(techPollBytes.get(), i, pollBytes.get());
@@ -1075,13 +1079,14 @@
mNumDiscTechList = 0;
mTechListTail = 0;
mIsMultiProtocolTag = false;
+ mSelectRetryCount = 0;
memset(mTechList, 0, sizeof(mTechList));
memset(mTechHandles, 0, sizeof(mTechHandles));
memset(mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
memset(mTechParams, 0, sizeof(mTechParams));
mIsDynamicTagId = false;
mIsFelicaLite = false;
- resetAllTransceiveTimeouts();
+ resetAllTransceiveTimeouts(true);
}
/*******************************************************************************
@@ -1097,7 +1102,6 @@
void NfcTag::selectFirstTag() {
static const char fn[] = "NfcTag::selectFirstTag";
int foundIdx = -1;
- tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
for (int i = 0; i < mNumDiscTechList; i++) {
LOG(DEBUG) << StringPrintf("%s: nfa target idx=%d h=0x%X; protocol=0x%X",
@@ -1111,15 +1115,7 @@
}
if (foundIdx != -1) {
- if (mTechLibNfcTypesDiscData[foundIdx] == NFA_PROTOCOL_ISO_DEP) {
- rf_intf = NFA_INTERFACE_ISO_DEP;
- } else if (mTechLibNfcTypesDiscData[foundIdx] == NFC_PROTOCOL_MIFARE) {
- rf_intf = NFA_INTERFACE_MIFARE;
- } else
- rf_intf = NFA_INTERFACE_FRAME;
-
- tNFA_STATUS stat = NFA_Select(mTechHandlesDiscData[foundIdx],
- mTechLibNfcTypesDiscData[foundIdx], rf_intf);
+ tNFA_STATUS stat = selectTagAtIndex(foundIdx);
if (stat != NFA_STATUS_OK)
LOG(ERROR) << StringPrintf("%s: fail select; error=0x%X", fn, stat);
} else
@@ -1139,7 +1135,6 @@
void NfcTag::selectNextTagIfExists() {
static const char fn[] = "NfcTag::selectNextTagIfExists";
int foundIdx = -1;
- tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
tNFA_STATUS stat = NFA_STATUS_FAILED;
if (mNumDiscNtf == 0) {
@@ -1164,16 +1159,7 @@
}
if (foundIdx != -1) {
- if (mTechLibNfcTypesDiscData[foundIdx] == NFA_PROTOCOL_ISO_DEP) {
- rf_intf = NFA_INTERFACE_ISO_DEP;
- } else if (mTechLibNfcTypesDiscData[foundIdx] == NFC_PROTOCOL_MIFARE) {
- rf_intf = NFA_INTERFACE_MIFARE;
- } else {
- rf_intf = NFA_INTERFACE_FRAME;
- }
-
- stat = NFA_Select(mTechHandlesDiscData[foundIdx],
- mTechLibNfcTypesDiscData[foundIdx], rf_intf);
+ stat = selectTagAtIndex(foundIdx);
if (stat == NFA_STATUS_OK) {
LOG(ERROR) << StringPrintf("%s: Select Success, wait for activated ntf",
fn);
@@ -1187,6 +1173,107 @@
/*******************************************************************************
**
+** Function: selectTagAtIndex
+**
+** Description: When multiple tags are discovered, selects a tag at
+** specified index
+**
+** Returns: Select result
+**
+*******************************************************************************/
+tNFA_STATUS NfcTag::selectTagAtIndex(int index) {
+ static const char fn[] = "NfcTag::selectTagAtIndex";
+
+ tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
+ if (index < 0 || index >= MAX_NUM_TECHNOLOGY) {
+ LOG(ERROR) << StringPrintf("%s: Invalid index passed", fn);
+ return NFA_STATUS_FAILED;
+ }
+ if (mTechLibNfcTypesDiscData[index] == NFA_PROTOCOL_ISO_DEP) {
+ rf_intf = NFA_INTERFACE_ISO_DEP;
+ } else if (mTechLibNfcTypesDiscData[index] == NFC_PROTOCOL_MIFARE) {
+ rf_intf = NFA_INTERFACE_MIFARE;
+ } else
+ rf_intf = NFA_INTERFACE_FRAME;
+
+ return NFA_Select(mTechHandlesDiscData[index],
+ mTechLibNfcTypesDiscData[index], rf_intf);
+}
+
+/*******************************************************************************
+**
+** Function: setLastSelectedTag
+**
+** Description: Set the last selected tag in case of multiprotocol tag
+**
+** Returns: NFA_STATUS_FAILED if tag is not found.
+**
+*******************************************************************************/
+tNFA_STATUS NfcTag::setLastSelectedTag(int targetHandle, int nfcType) {
+ static const char fn[] = "NfcTag::setLastSelectedTag";
+
+ if (!mIsMultiProtocolTag) {
+ LOG(INFO) << StringPrintf("%s: Not a multiprotocol tag, returning", fn);
+ return NFA_STATUS_OK;
+ }
+ for (int i = 0; i < mNumDiscTechList; i++) {
+ if (mTechHandlesDiscData[i] == targetHandle &&
+ mTechLibNfcTypesDiscData[i] == nfcType) {
+ sLastSelectedTagId = i;
+ return NFA_STATUS_OK;
+ }
+ }
+ LOG(ERROR) << StringPrintf("%s: Couldn't find target Handle (%d)", fn,
+ targetHandle);
+ return NFA_STATUS_FAILED;
+}
+
+/*******************************************************************************
+**
+** Function: retrySelect
+**
+** Description: Retry select last tag in case of multiprotocol tag
+**
+** Returns: NFA_STATUS_FAILED if it is not a multiprotocol tag or
+** retry is already done. Otherwise it returns Select status.
+**
+*******************************************************************************/
+
+tNFA_STATUS NfcTag::retrySelect() {
+ static const char fn[] = "NfcTag::retrySelect";
+ tNFA_STATUS stat = NFA_STATUS_FAILED;
+
+ if (mSelectRetryCount != 0) {
+ LOG(ERROR) << StringPrintf("%s: Select retry already done, returning", fn);
+ return NFA_STATUS_FAILED;
+ }
+ if (!mIsMultiProtocolTag) {
+ LOG(INFO) << StringPrintf("%s: Not a multiprotocol tag, returning", fn);
+ return NFA_STATUS_FAILED;
+ }
+ stat = selectTagAtIndex(sLastSelectedTagId);
+ if (stat == NFA_STATUS_OK) {
+ LOG(INFO) << StringPrintf("%s: Select Success, wait for activated ntf", fn);
+ } else {
+ LOG(ERROR) << StringPrintf("%s: fail select; error=0x%X", fn, stat);
+ }
+ mSelectRetryCount++;
+ return stat;
+}
+
+/*******************************************************************************
+**
+** Function: clearSelectRetryCount
+**
+** Description: Clear select retry count.
+**
+** Returns: None.
+**
+*******************************************************************************/
+void NfcTag::clearSelectRetryCount() { mSelectRetryCount = 0; }
+
+/*******************************************************************************
+**
** Function: getT1tMaxMessageSize
**
** Description: Get the maximum size (octet) that a T1T can store.
@@ -1509,11 +1596,13 @@
** Returns: none
**
*******************************************************************************/
-void NfcTag::resetAllTransceiveTimeouts() {
+void NfcTag::resetAllTransceiveTimeouts(bool includeType4) {
mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3A] = 618; // NfcA
mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3B] = 1000; // NfcB
- mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_4] = 618; // ISO-DEP
mTechnologyTimeoutsTable[TARGET_TYPE_FELICA] = 255; // Felica
+ if (includeType4) {
+ mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_4] = 618; // ISO-DEP
+ }
mTechnologyTimeoutsTable[TARGET_TYPE_V] = 1000; // NfcV
mTechnologyTimeoutsTable[TARGET_TYPE_NDEF] = 1000;
mTechnologyTimeoutsTable[TARGET_TYPE_NDEF_FORMATABLE] = 1000;
@@ -1645,6 +1734,18 @@
/*******************************************************************************
**
+** Function: getMultiProtocolTagSupport
+**
+** Description: get mIsMultiProtocolTag
+**
+** Returns: mIsMultiProtocolTag
+**
+*******************************************************************************/
+
+bool NfcTag::getMultiProtocolTagSupport() { return mIsMultiProtocolTag; }
+
+/*******************************************************************************
+**
** Function: setNumDiscNtf
**
** Description: Update number of Discovery NTF received
@@ -1653,8 +1754,10 @@
**
*******************************************************************************/
void NfcTag::setNumDiscNtf(int numDiscNtfValue) {
+ static const char fn[] = "NfcTag::setNumDiscNtf";
if (numDiscNtfValue < MAX_NUM_TECHNOLOGY) {
mNumDiscNtf = numDiscNtfValue;
+ LOG(DEBUG) << StringPrintf("%s: mNumDiscNtf=%u", fn, mNumDiscNtf);
}
}
diff --git a/NfcNci/nci/jni/NfcTag.h b/NfcNci/nci/jni/NfcTag.h
index 815b66d..0598070 100644
--- a/NfcNci/nci/jni/NfcTag.h
+++ b/NfcNci/nci/jni/NfcTag.h
@@ -200,6 +200,52 @@
/*******************************************************************************
**
+ ** Function: setLastSelectedTag
+ **
+ ** Description: Set the last selected tag in case of multiprotocol tag
+ **
+ ** Returns: NFA_STATUS_FAILED if tag is not found.
+ **
+ *******************************************************************************/
+ tNFA_STATUS setLastSelectedTag(int targetHandle, int nfcType);
+
+ /*******************************************************************************
+ **
+ ** Function: retrySelect
+ **
+ ** Description: Retry select last tag in case of multiprotocol tag
+ **
+ ** Returns: NFA_STATUS_FAILED if it is not a multiprotocol tag or
+ ** retry is already done. Otherwise it returns Select status.
+ **
+ *******************************************************************************/
+ tNFA_STATUS retrySelect();
+
+ /*******************************************************************************
+ **
+ ** Function: clearSelectRetryCount
+ **
+ ** Description: Clear select retry count.
+ **
+ ** Returns: None.
+ **
+ *******************************************************************************/
+ void clearSelectRetryCount();
+
+ /*******************************************************************************
+ **
+ ** Function: selectTagAtIndex
+ **
+ ** Description: When multiple tags are discovered, selects a tag at
+ ** specified index
+ **
+ ** Returns: Select result
+ **
+ *******************************************************************************/
+ tNFA_STATUS selectTagAtIndex(int index);
+
+ /*******************************************************************************
+ **
** Function: getT1tMaxMessageSize
**
** Description: Get the maximum size (octet) that a T1T can store.
@@ -312,7 +358,7 @@
** Returns: none
**
*******************************************************************************/
- void resetAllTransceiveTimeouts();
+ void resetAllTransceiveTimeouts(bool includeType4);
/*******************************************************************************
**
@@ -402,6 +448,17 @@
/*******************************************************************************
**
+ ** Function: getMultiProtocolTagSupport
+ **
+ ** Description: get mIsMultiProtocolTag
+ **
+ ** Returns: mIsMultiProtocolTag
+ **
+ *******************************************************************************/
+ bool getMultiProtocolTagSupport();
+
+ /*******************************************************************************
+ **
** Function: setNumDiscNtf
**
** Description: Update mNumDiscNtf
@@ -475,6 +532,7 @@
int mNumDiscTechList;
int mTechListTail; // Index of Last added entry in mTechList
bool mIsMultiProtocolTag;
+ int mSelectRetryCount = 0;
NfcStatsUtil* mNfcStatsUtil;
JNIEnv* mJniEnv = NULL;
diff --git a/NfcNci/nci/jni/NfceeManager.cpp b/NfcNci/nci/jni/NfceeManager.cpp
index 620c0c3..0484b10 100644
--- a/NfcNci/nci/jni/NfceeManager.cpp
+++ b/NfcNci/nci/jni/NfceeManager.cpp
@@ -40,6 +40,7 @@
mActualNumEe = MAX_NUM_NFCEE;
eseName = "eSE";
uiccName = "SIM";
+ ndefNfceeName = "NDEF-NFCEE";
memset(&mNfceeData_t, 0, sizeof(mNfceeData));
}
@@ -109,6 +110,14 @@
nfceeMap[uiccRoute[i]] = uiccName + std::to_string(i + 1);
}
+ if (NfcConfig::hasKey(NAME_T4T_NFCEE_ENABLE)) {
+ if (NfcConfig::getUnsigned(NAME_T4T_NFCEE_ENABLE)) {
+ uint8_t defaultNdefNfceeRoute =
+ NfcConfig::getUnsigned(NAME_DEFAULT_NDEF_NFCEE_ROUTE, 0x10);
+ nfceeMap[defaultNdefNfceeRoute] = ndefNfceeName;
+ }
+ }
+
for (int i = 0; i < mNfceeData_t.mNfceePresent; i++) {
uint8_t id = (mNfceeData_t.mNfceeID[i] & ~NFA_HANDLE_GROUP_EE);
uint8_t status = mNfceeData_t.mNfceeStatus[i];
diff --git a/NfcNci/nci/jni/NfceeManager.h b/NfcNci/nci/jni/NfceeManager.h
index bb49c8b..99d3393 100644
--- a/NfcNci/nci/jni/NfceeManager.h
+++ b/NfcNci/nci/jni/NfceeManager.h
@@ -103,6 +103,7 @@
static NfceeManager sNfceeManager;
string eseName;
string uiccName;
+ string ndefNfceeName;
tNFA_EE_INFO mEeInfo[MAX_NUM_NFCEE];
uint8_t mNumEePresent;
uint8_t mActualNumEe;
diff --git a/NfcNci/nci/jni/RoutingManager.cpp b/NfcNci/nci/jni/RoutingManager.cpp
index 4e6270d..50d79f1 100755
--- a/NfcNci/nci/jni/RoutingManager.cpp
+++ b/NfcNci/nci/jni/RoutingManager.cpp
@@ -71,6 +71,8 @@
static const uint8_t AID_ROUTE_QUAL_PREFIX = 0x10;
+static Mutex sEeInfoMutex;
+static Mutex sEeInfoChangedMutex;
/*******************************************************************************
**
@@ -225,7 +227,7 @@
LOG(ERROR) << fn << ": Failed to register wildcard AID for DH";
// Trigger RT update
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
mDefaultAidRouteAdded = false;
return true;
@@ -396,13 +398,16 @@
tNFA_STATUS RoutingManager::commitRouting() {
static const char fn[] = "RoutingManager::commitRouting";
tNFA_STATUS nfaStat = 0;
- if (mAidRoutingConfigured || mEeInfoChanged) {
+ sEeInfoChangedMutex.lock();
+ bool eeChanged = mEeInfoChanged;
+ mEeInfoChanged = false;
+ sEeInfoChangedMutex.unlock();
+ if (eeChanged) {
+ clearRoutingEntry(CLEAR_PROTOCOL_ENTRIES | CLEAR_TECHNOLOGY_ENTRIES);
+ updateRoutingTable();
+ }
+ if (mAidRoutingConfigured || eeChanged) {
LOG(DEBUG) << StringPrintf("%s: RT update needed", fn);
- if (mEeInfoChanged) {
- clearRoutingEntry(CLEAR_PROTOCOL_ENTRIES | CLEAR_TECHNOLOGY_ENTRIES);
- updateRoutingTable();
- mEeInfoChanged = false;
- }
{
SyncEventGuard guard(mEeUpdateEvent);
nfaStat = NFA_EeUpdateNow();
@@ -461,6 +466,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();
+ }
}
/*******************************************************************************
@@ -829,7 +855,7 @@
void RoutingManager::updateIsoDepProtocolRoute(int route) {
static const char fn[] = "RoutingManager::updateIsoDepProtocolRoute";
LOG(DEBUG) << StringPrintf("%s: New default ISO-DEP route=0x%x", fn, route);
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
mDefaultIsoDepRoute = route;
}
@@ -845,7 +871,7 @@
void RoutingManager::updateSystemCodeRoute(int route) {
static const char fn[] = "RoutingManager::updateSystemCodeRoute";
LOG(DEBUG) << StringPrintf("%s: New default SC route=0x%x", fn, route);
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
mDefaultSysCodeRoute = route;
updateDefaultRoute();
}
@@ -948,20 +974,18 @@
defaultAidRoute = NFC_DH_ID;
}
- // Default AID route should be added only if different from ISO-DEP route
- if ((defaultAidRoute != mDefaultIsoDepRoute) ||
- (mDefaultIsoDepRoute == NFC_DH_ID)) {
- removeAidRouting(nullptr, 0);
- uint8_t powerState = 0x01;
- if (!mSecureNfcEnabled)
- powerState =
- (defaultAidRoute != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
- nfaStat = NFA_EeAddAidRouting(defaultAidRoute, 0, NULL, powerState,
- AID_ROUTE_QUAL_PREFIX);
- if (nfaStat != NFA_STATUS_OK)
- LOG(ERROR) << fn << ": failed to register zero length AID";
- else
- mDefaultAidRouteAdded = true;
+ removeAidRouting(nullptr, 0);
+ uint8_t powerState = 0x01;
+ if (!mSecureNfcEnabled) {
+ powerState =
+ (defaultAidRoute != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
+ }
+ nfaStat = NFA_EeAddAidRouting(defaultAidRoute, 0, NULL, powerState,
+ AID_ROUTE_QUAL_PREFIX);
+ if (nfaStat != NFA_STATUS_OK) {
+ LOG(ERROR) << fn << ": failed to register zero length AID";
+ } else {
+ mDefaultAidRouteAdded = true;
}
}
}
@@ -999,7 +1023,13 @@
static const char fn[] = "RoutingManager::updateEeTechRouteSetting";
tNFA_TECHNOLOGY_MASK allSeTechMask = 0x00, hostTechMask = 0x00;
- LOG(DEBUG) << StringPrintf("%s: Default route A/B=0x%x", fn,
+ // Get content of mEeInfo as it can change if a NTF is received during update
+ // of RT
+ sEeInfoMutex.lock();
+ tNFA_EE_DISCOVER_REQ localEeInfo;
+ memcpy(&localEeInfo, &mEeInfo, sizeof(mEeInfo));
+ sEeInfoMutex.unlock();
+ LOG(DEBUG) << StringPrintf("%s: Default route A/B: 0x%x", fn,
mDefaultOffHostRoute);
LOG(DEBUG) << StringPrintf("%s: Default route F=0x%x", fn,
mDefaultFelicaRoute);
@@ -1008,31 +1038,31 @@
tNFA_STATUS nfaStat;
- for (uint8_t i = 0; i < mEeInfo.num_ee; i++) {
- tNFA_HANDLE eeHandle = mEeInfo.ee_disc_info[i].ee_handle;
+ for (uint8_t i = 0; i < localEeInfo.num_ee; i++) {
+ tNFA_HANDLE eeHandle = localEeInfo.ee_disc_info[i].ee_handle;
tNFA_TECHNOLOGY_MASK seTechMask = 0;
LOG(DEBUG) << StringPrintf(
- "%s EE[%u] Handle=0x%04x techA=0x%02x techB=0x%02x techF=0x%02x "
- "techBprime=0x%02x",
- fn, i, eeHandle, mEeInfo.ee_disc_info[i].la_protocol,
- mEeInfo.ee_disc_info[i].lb_protocol,
- mEeInfo.ee_disc_info[i].lf_protocol,
- mEeInfo.ee_disc_info[i].lbp_protocol);
+ "%s: EE[%u] Handle=0x%04x techA=0x%02x techB="
+ "0x%02x techF=0x%02x techBprime=0x%02x",
+ fn, i, eeHandle, localEeInfo.ee_disc_info[i].la_protocol,
+ localEeInfo.ee_disc_info[i].lb_protocol,
+ localEeInfo.ee_disc_info[i].lf_protocol,
+ localEeInfo.ee_disc_info[i].lbp_protocol);
if ((mDefaultOffHostRoute != NFC_DH_ID) &&
(eeHandle == (mDefaultOffHostRoute | NFA_HANDLE_GROUP_EE))) {
- if (mEeInfo.ee_disc_info[i].la_protocol != 0) {
+ if (localEeInfo.ee_disc_info[i].la_protocol != 0) {
seTechMask |= NFA_TECHNOLOGY_MASK_A;
}
- if (mEeInfo.ee_disc_info[i].lb_protocol != 0) {
+ if (localEeInfo.ee_disc_info[i].lb_protocol != 0) {
seTechMask |= NFA_TECHNOLOGY_MASK_B;
}
}
if ((mDefaultFelicaRoute != NFC_DH_ID) &&
(eeHandle == (mDefaultFelicaRoute | NFA_HANDLE_GROUP_EE))) {
- if (mEeInfo.ee_disc_info[i].lf_protocol != 0) {
+ if (localEeInfo.ee_disc_info[i].lf_protocol != 0) {
seTechMask |= NFA_TECHNOLOGY_MASK_F;
}
}
@@ -1195,20 +1225,22 @@
case NFA_EE_DISCOVER_REQ_EVT: {
SyncEventGuard guard(routingManager.mEeInfoEvent);
+ sEeInfoMutex.lock();
memcpy(&routingManager.mEeInfo, &eventData->discover_req,
sizeof(routingManager.mEeInfo));
for (int i = 0; i < eventData->discover_req.num_ee; i++) {
LOG(DEBUG) << StringPrintf(
- "%s; NFA_EE_DISCOVER_REQ_EVT; nfceeId=0x%X; la_proto=0x%X, "
+ "%s: NFA_EE_DISCOVER_REQ_EVT; nfceeId=0x%X; la_proto=0x%X, "
"lb_proto=0x%x, lf_proto=0x%x",
fn, eventData->discover_req.ee_disc_info[i].ee_handle,
eventData->discover_req.ee_disc_info[i].la_protocol,
eventData->discover_req.ee_disc_info[i].lb_protocol,
eventData->discover_req.ee_disc_info[i].lf_protocol);
}
+ sEeInfoMutex.unlock();
if (!routingManager.mIsRFDiscoveryOptimized) {
if (routingManager.mReceivedEeInfo && !routingManager.mDeinitializing) {
- routingManager.mEeInfoChanged = true;
+ routingManager.setEeInfoChangedFlag();
routingManager.notifyEeUpdated();
}
}
@@ -1222,7 +1254,7 @@
eventData->discover_req.status, eventData->discover_req.num_ee);
if (routingManager.mIsRFDiscoveryOptimized) {
if (routingManager.mReceivedEeInfo && !routingManager.mDeinitializing) {
- routingManager.mEeInfoChanged = true;
+ routingManager.setEeInfoChangedFlag();
routingManager.notifyEeUpdated();
}
}
@@ -1344,7 +1376,7 @@
return NFA_HANDLE_INVALID;
}
LOG(DEBUG) << StringPrintf("%s: Succeed to register system code on DH", fn);
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
// add handle and system code pair to the map
mMapScbrHandle.emplace(mNfcFOnDhHandle, systemCode);
} else {
@@ -1390,7 +1422,7 @@
tNFA_STATUS nfaStat = NFA_EeRemoveSystemCodeRouting(systemCode);
if (nfaStat == NFA_STATUS_OK) {
mRoutingEvent.wait();
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
LOG(DEBUG) << StringPrintf(
"%s: Succeeded in deregistering system Code on DH", fn);
} else {
@@ -1558,7 +1590,7 @@
// Setting flag for Ee info changed so that
// routing table can be updated
- mEeInfoChanged = true;
+ setEeInfoChangedFlag();
}
/*******************************************************************************
@@ -1577,6 +1609,23 @@
/*******************************************************************************
**
+** Function: setEeInfoChangedFlag
+**
+** Description: .
+**
+** Returns: None
+**
+*******************************************************************************/
+void RoutingManager::setEeInfoChangedFlag() {
+ static const char fn[] = "RoutingManager::setEeInfoChangedFlag";
+ LOG(DEBUG) << StringPrintf("%s", fn);
+ sEeInfoChangedMutex.lock();
+ mEeInfoChanged = true;
+ sEeInfoChangedMutex.unlock();
+}
+
+/*******************************************************************************
+**
** Function: registerJniFunctions
**
** Description: called at object creation to register JNI function
diff --git a/NfcNci/nci/jni/RoutingManager.h b/NfcNci/nci/jni/RoutingManager.h
index d38343c..d72351e 100755
--- a/NfcNci/nci/jni/RoutingManager.h
+++ b/NfcNci/nci/jni/RoutingManager.h
@@ -54,6 +54,7 @@
void notifyEeProtocolSelected(uint8_t protocol, tNFA_HANDLE ee_handle);
void notifyEeTechSelected(uint8_t tech, tNFA_HANDLE ee_handle);
bool getNameOfEe(tNFA_HANDLE ee_handle, std::string& eeName);
+ void setEeInfoChangedFlag();
static const int CLEAR_AID_ENTRIES = 0x01;
static const int CLEAR_PROTOCOL_ENTRIES = 0x02;
diff --git a/NfcNci/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/NfcNci/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
index 4de31c4..d525e8a 100644
--- a/NfcNci/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
+++ b/NfcNci/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
@@ -77,6 +77,9 @@
private static final int NCI_OID_INDEX = 1;
private static final int OP_CODE_INDEX = 3;
+ private static final int OBSERVE_MODE_SUSPENDED_FRAME_TYPE_A = 0x00;
+ private static final int OBSERVE_MODE_SUSPENDED_FRAME_TYPE_B = 0x01;
+
private void loadLibrary() {
System.loadLibrary("nfc_nci_jni");
}
@@ -529,21 +532,21 @@
Log.i(TAG, "notifyEeAidSelected: AID= " + HexFormat.of().formatHex(aid) + " selected by "
+ eventSrc);
if (com.android.nfc.flags.Flags.eeAidSelect()) {
- mListener.onSeSelected();
+ mListener.onSeSelected(NfcService.SE_SELECTED_AID);
}
}
private void notifyEeProtocolSelected(int protocol, String eventSrc) {
Log.i(TAG, "notifyEeProtocolSelected: Protocol: " + protocol + " selected by " + eventSrc);
if (com.android.nfc.flags.Flags.eeAidSelect()) {
- mListener.onSeSelected();
+ mListener.onSeSelected(NfcService.SE_SELECTED_PROTOCOL);
}
}
private void notifyEeTechSelected(int tech, String eventSrc) {
Log.i(TAG, "notifyEeTechSelected: Tech: " + tech + " selected by " + eventSrc);
if (com.android.nfc.flags.Flags.eeAidSelect()) {
- mListener.onSeSelected();
+ mListener.onSeSelected(NfcService.SE_SELECTED_TECH);
}
}
@@ -629,6 +632,22 @@
Trace.endSection();
}
+ private void onObserveModeEnabledInFirmware() {
+ mListener.onObserveModeEnabledInFirmware();
+ }
+
+ private void onObserveModeDisabledInFirmware(int type, byte[] data) {
+ int pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_UNKNOWN;
+ if (type == OBSERVE_MODE_SUSPENDED_FRAME_TYPE_A) {
+ pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_A;
+ } else if (type == OBSERVE_MODE_SUSPENDED_FRAME_TYPE_B) {
+ pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_B;
+ }
+
+ mListener.onObserveModeDisabledInFirmware(
+ new PollingFrame(pollingFrameType, data, -1, -1, true));
+ }
+
private native boolean doDetectEpRemoval(int waiting_time_int);
@Override
@@ -706,6 +725,15 @@
!= NfcProprietaryCaps.PassiveObserveMode.NOT_SUPPORTED;
}
+ private boolean isReaderModeAnnotationSupportedCaps() {
+ return mProprietaryCaps.isReaderModeAnnotationSupported();
+ }
+
+ @Override
+ public boolean isReaderModeAnnotationSupported() {
+ return isReaderModeAnnotationSupportedCaps();
+ }
+
private static void logProprietaryCaps(NfcProprietaryCaps proprietaryCaps) {
int observeModeStatsd = CAPS_OBSERVE_MODE_UNKNOWN;
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/res/values/strings.xml b/NfcNci/res/values/strings.xml
index 8a630df..47fc3f7 100755
--- a/NfcNci/res/values/strings.xml
+++ b/NfcNci/res/values/strings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_name">Nfc Service</string>
- <string name="nfcUserLabel">Nfc</string>
+ <string name="app_name">NFC Service</string>
+ <string name="nfcUserLabel">NFC</string>
<!-- Content description of the NFC enabled notification icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_nfc_enabled">NFC enabled.</string>
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/DeviceHost.java b/NfcNci/src/com/android/nfc/DeviceHost.java
index f08a41f..815bd90 100644
--- a/NfcNci/src/com/android/nfc/DeviceHost.java
+++ b/NfcNci/src/com/android/nfc/DeviceHost.java
@@ -48,6 +48,10 @@
public void onPollingLoopDetected(List<PollingFrame> pollingFrames);
+ public void onObserveModeEnabledInFirmware();
+
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame);
+
public void onWlcStopped(int wpt_end_condition);
public void onTagRfDiscovered(boolean discovered);
@@ -60,7 +64,7 @@
public void onEeListenActivated(boolean isActivated);
- public void onSeSelected();
+ public void onSeSelected(int type);
public void onCommandTimeout();
@@ -268,6 +272,8 @@
public boolean setNfcSecure(boolean enable);
+ public boolean isReaderModeAnnotationSupported();
+
public boolean isObserveModeSupported();
public boolean setObserveMode(boolean enable);
diff --git a/NfcNci/src/com/android/nfc/ExitFrame.java b/NfcNci/src/com/android/nfc/ExitFrame.java
index a840a51..1cc77d0 100644
--- a/NfcNci/src/com/android/nfc/ExitFrame.java
+++ b/NfcNci/src/com/android/nfc/ExitFrame.java
@@ -75,9 +75,9 @@
}
}
mData = HexFormat.of().parseHex(String.valueOf(filterChars));
- if (mData.length > 16) {
+ if (mData.length > 14) {
throw new IllegalArgumentException(
- "Filter too long, firmware exit frames only support 16 byte filters.");
+ "Filter too long, firmware exit frames only support 14 byte filters.");
}
mDataMask = HexFormat.of().parseHex(String.valueOf(maskChars));
diff --git a/NfcNci/src/com/android/nfc/NfcDispatcher.java b/NfcNci/src/com/android/nfc/NfcDispatcher.java
index 0604fd0..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;
}
@@ -359,18 +361,20 @@
String pkgName = activityInfo.packageName;
String appName = context.getPackageManager().getApplicationLabel(
activityInfo.applicationInfo).toString();
- if (DBG) Log.d(TAG, "checkPrefList: activityInfo.packageName= " + pkgName);
Map<String, Boolean> preflist =
mNfcAdapter.getTagIntentAppPreferenceForUser(userId);
if (preflist.containsKey(pkgName)) {
if (!preflist.get(pkgName)) {
- if (DBG) Log.d(TAG, "checkPrefList: mute pkg:" + pkgName);
+ if (DBG) Log.d(TAG, "checkPrefList: mute:" + pkgName);
muteAppCount++;
filtered.remove(resolveInfo);
logMuteApp(activityInfo.applicationInfo.uid);
+ } else {
+ if (DBG) Log.d(TAG, "checkPrefList: allow:" + pkgName);
}
} else {
// Default sets allow to the preference list
+ if (DBG) Log.d(TAG, "checkPrefList: add:" + pkgName);
mNfcAdapter.setTagIntentAppPreferenceForUser(userId, pkgName, true);
if (Flags.nfcAlertTagAppLaunch()) {
notifyAppNames.add(appName);
@@ -594,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)
@@ -1074,12 +1077,17 @@
matches.add(info.resolveInfo);
if (!preflist.containsKey(pkgName)) {
// Default sets allow to the preference list
+ if (DBG) Log.d(TAG, "tryTech: add:" + pkgName);
mNfcAdapter.setTagIntentAppPreferenceForUser(userId,
pkgName, true);
if (Flags.nfcAlertTagAppLaunch()) {
notifyAppNames.add(appName);
}
+ } else {
+ if (DBG) Log.d(TAG, "tryTech: allow:" + pkgName);
}
+ } else {
+ if (DBG) Log.d(TAG, "tryTech: mute:" + pkgName);
}
}
}
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 18f7336..9c87e2f 100644
--- a/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java
+++ b/NfcNci/src/com/android/nfc/NfcProprietaryCaps.java
@@ -10,7 +10,7 @@
* 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
+ * See the License for the specific language governing permIssions and
* limitations under the License.
*/
@@ -27,11 +27,13 @@
private static final int POWER_SAVING_MODE = 2;
private static final int AUTOTRANSACT_POLLING_LOOP_FILTER = 3;
private static final int NUMBER_OF_EXIT_FRAMES_SUPPORTED = 4;
+ private static final int READER_MODE_ANNOTATIONS_SUPPORTED = 5;
private final PassiveObserveMode mPassiveObserveMode;
private final boolean mIsPollingFrameNotificationSupported;
private final boolean mIsPowerSavingModeSupported;
private final boolean mIsAutotransactPollingLoopFilterSupported;
private final int mNumberOfExitFramesSupported;
+ private final boolean mIsReaderModeAnnotationSupported;
public enum PassiveObserveMode {
NOT_SUPPORTED,
@@ -59,14 +61,20 @@
return mNumberOfExitFramesSupported;
}
+ public boolean isReaderModeAnnotationSupported() {
+ return mIsReaderModeAnnotationSupported;
+ }
+
public NfcProprietaryCaps(PassiveObserveMode passiveObserveMode,
boolean isPollingFrameNotificationSupported, boolean isPowerSavingModeSupported,
- boolean isAutotransactPollingLoopFilterSupported, int numberOfExitFramesSupported) {
+ boolean isAutotransactPollingLoopFilterSupported, int numberOfExitFramesSupported,
+ boolean isReaderModeAnnotationSupported) {
mPassiveObserveMode = passiveObserveMode;
mIsPollingFrameNotificationSupported = isPollingFrameNotificationSupported;
mIsPowerSavingModeSupported = isPowerSavingModeSupported;
mIsAutotransactPollingLoopFilterSupported = isAutotransactPollingLoopFilterSupported;
mNumberOfExitFramesSupported = numberOfExitFramesSupported;
+ mIsReaderModeAnnotationSupported = isReaderModeAnnotationSupported;
}
public static NfcProprietaryCaps createFromByteArray(byte[] caps) {
@@ -76,6 +84,7 @@
boolean isPowerSavingModeSupported = false;
boolean isAutotransactPollingLoopFilterSupported = false;
int numberOfExitFramesSupported = 0;
+ boolean isReaderModeAnnotationSupported = false;
int offset = 0;
while ((offset + 2) < caps.length) {
int id = caps[offset++];
@@ -109,12 +118,15 @@
break;
case NUMBER_OF_EXIT_FRAMES_SUPPORTED:
numberOfExitFramesSupported = caps[value_offset];
+ case READER_MODE_ANNOTATIONS_SUPPORTED:
+ isReaderModeAnnotationSupported = caps[value_offset] == 0x1;
+ break;
}
}
return new NfcProprietaryCaps(passiveObserveMode, isPollingFrameNotificationSupported,
isPowerSavingModeSupported, isAutotransactPollingLoopFilterSupported,
- numberOfExitFramesSupported);
+ numberOfExitFramesSupported, isReaderModeAnnotationSupported);
}
@Override
@@ -128,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 04cd105..4065580 100644
--- a/NfcNci/src/com/android/nfc/NfcService.java
+++ b/NfcNci/src/com/android/nfc/NfcService.java
@@ -257,6 +257,11 @@
static final int TASK_ENABLE_ALWAYS_ON = 4;
static final int TASK_DISABLE_ALWAYS_ON = 5;
+ // SE selected types
+ public static final int SE_SELECTED_AID = 0x01;
+ public static final int SE_SELECTED_TECH = 0x02;
+ public static final int SE_SELECTED_PROTOCOL = 0x04;
+
// Polling technology masks
static final int NFC_POLL_A = 0x01;
static final int NFC_POLL_B = 0x02;
@@ -777,20 +782,35 @@
mRtUpdateScheduledTask =
mRtUpdateScheduler.schedule(
() -> {
- if (DBG) Log.d(TAG, "onEeUpdated: ApplyRoutingTask");
- new ApplyRoutingTask().execute();
+ if (mIsHceCapable) {
+ if (DBG) Log.d(TAG, "onEeUpdated: trigger routing table update");
+ mCardEmulationManager.onTriggerRoutingTableUpdate();
+ }
},
50,
TimeUnit.MILLISECONDS);
}
private void restartStack() {
+ synchronized (NfcService.this) {
+ if (DBG) {
+ Log.d(TAG, "restartStack: mIsRecovering=" + mIsRecovering);
+ }
+ if (!mIsRecovering) {
+ mIsRecovering = true;
+ } else {
+ return;
+ }
+ }
+
+ if (DBG) {
+ Log.d(TAG, "restartStack: Restarting NFC Service");
+ }
try {
mContext.unregisterReceiver(mReceiver);
} catch (IllegalArgumentException e) {
Log.w(TAG, "restartStack: Failed to unregisterScreenState BroadCastReceiver: " + e);
}
- mIsRecovering = true;
new EnableDisableTask().execute(TASK_DISABLE);
new EnableDisableTask().execute(TASK_ENABLE);
}
@@ -834,6 +854,17 @@
}
@Override
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
+ mCardEmulationManager.onObserveModeDisabledInFirmware(exitFrame);
+ onObserveModeStateChanged(false);
+ }
+
+ @Override
+ public void onObserveModeEnabledInFirmware() {
+ onObserveModeStateChanged(true);
+ }
+
+ @Override
public void onEeListenActivated(boolean isActivated) {
mEeListenActivated = isActivated;
mCardEmulationManager.onEeListenActivated(isActivated);
@@ -861,8 +892,8 @@
}
@Override
- public void onSeSelected() {
- sendMessage(MSG_SE_SELECTED_EVENT, null);
+ public void onSeSelected(int type) {
+ sendMessage(MSG_SE_SELECTED_EVENT, type);
}
@Override
@@ -1128,8 +1159,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 {
@@ -1217,13 +1247,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);
@@ -1231,7 +1259,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 =
@@ -1239,8 +1267,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);
@@ -1322,8 +1349,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();
}
@@ -1337,7 +1364,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);
@@ -2291,6 +2318,11 @@
}
@Override
+ public boolean isReaderModeAnnotationSupported() {
+ return mDeviceHost.isReaderModeAnnotationSupported();
+ }
+
+ @Override
public boolean isObserveModeSupported() {
if (!isNfcEnabled()) {
Log.e(TAG, "isObserveModeSupported: NFC must be enabled but is: " + mState);
@@ -2490,7 +2522,7 @@
}
if (mIsHceCapable) {
// update HCE/HCEF routing and commitRouting if Nfc is enabled
- mCardEmulationManager.onSecureNfcToggled();
+ mCardEmulationManager.onTriggerRoutingTableUpdate();
} else if (isNfcEnabled()) {
// commit only tech/protocol route without HCE support
mDeviceHost.commitRouting();
@@ -2791,6 +2823,12 @@
Log.e(TAG, "setReaderMode: called with invalid flag parameter.");
return;
}
+ if (extras != null
+ && extras.containsKey(NfcAdapter.EXTRA_READER_TECH_A_POLLING_LOOP_ANNOTATION)
+ && !isReaderModeAnnotationSupported()) {
+ Log.e(TAG, "setReaderMode() called with annotation on an unsupported device.");
+ return;
+ }
synchronized (NfcService.this) {
if (!isNfcEnabled() && !privilegedCaller) {
Log.e(TAG, "setReaderMode: called while NFC is not enabled.");
@@ -3536,6 +3574,11 @@
@Override
public int commitRouting() throws RemoteException {
+ if (isNfcDisabledOrDisabling()) {
+ Log.d(TAG, "Skip commit routing when NFCC is off "
+ + "or turning off");
+ return STATUS_UNKNOWN_ERROR;
+ }
if (DBG) Log.i(TAG, "commitRouting");
NfcPermissions.enforceAdminPermissions(mContext);
return mDeviceHost.commitRouting();
@@ -4248,6 +4291,12 @@
}
}
+ boolean isNfcDisabledOrDisabling() {
+ synchronized (this) {
+ return (mState == NfcAdapter.STATE_OFF || mState == NfcAdapter.STATE_TURNING_OFF);
+ }
+ }
+
boolean isNfcEnabled() {
synchronized (this) {
return mState == NfcAdapter.STATE_ON;
@@ -4705,6 +4754,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;
}
@@ -4887,8 +4938,7 @@
case MSG_COMMIT_ROUTING: {
Log.d(TAG, "handleMessage: MSG_COMMIT_ROUTING");
synchronized (NfcService.this) {
- if (mState == NfcAdapter.STATE_OFF
- || mState == NfcAdapter.STATE_TURNING_OFF) {
+ if (isNfcDisabledOrDisabling()) {
Log.d(TAG, "handleMessage: Skip commit routing when NFCC is off "
+ "or turning off");
if (mCommitRoutingCountDownLatch != null) {
@@ -5208,7 +5258,8 @@
case MSG_SE_SELECTED_EVENT:
Log.d(TAG, "handleMessage: MSG_SE_SELECTED_EVENT");
- if (mCardEmulationManager != null) {
+ int type = (int) msg.obj;
+ if (mCardEmulationManager != null && type == SE_SELECTED_AID) {
mCardEmulationManager.onOffHostAidSelected();
}
break;
@@ -5807,8 +5858,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();
@@ -5822,8 +5873,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/AidRoutingManager.java b/NfcNci/src/com/android/nfc/cardemulation/AidRoutingManager.java
index d7250e0..fc8b688 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/AidRoutingManager.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/AidRoutingManager.java
@@ -443,41 +443,34 @@
}
}
- // register default route in below cases:
- // 1. mDefaultRoute is different with mDefaultIsoDepRoute
- // 2. mDefaultRoute and mDefaultIsoDepRoute all equal to ROUTE_HOST
- // , which is used for screen off HCE scenarios
- if (mDefaultRoute != mDefaultIsoDepRoute || mDefaultIsoDepRoute == ROUTE_HOST) {
- if (NfcService.getInstance().getNciVersion()
- >= NfcService.getInstance().NCI_VERSION_2_0) {
- String emptyAid = "";
- AidEntry entry = new AidEntry();
- int default_route_power_state;
- entry.route = mDefaultRoute;
- if (mDefaultRoute == ROUTE_HOST) {
- entry.isOnHost = true;
- default_route_power_state = RegisteredAidCache.POWER_STATE_SWITCH_ON
- | RegisteredAidCache.POWER_STATE_SCREEN_ON_LOCKED;
- Set<String> aidsForDefaultRoute = mAidRoutingTable.get(mDefaultRoute);
- if (aidsForDefaultRoute != null) {
- for (String aid : aidsForDefaultRoute) {
- default_route_power_state |= aidMap.get(aid).power;
- }
+ if (NfcService.getInstance().getNciVersion()
+ >= NfcService.getInstance().NCI_VERSION_2_0) {
+ String emptyAid = "";
+ AidEntry entry = new AidEntry();
+ int default_route_power_state;
+ entry.route = mDefaultRoute;
+ if (mDefaultRoute == ROUTE_HOST) {
+ entry.isOnHost = true;
+ default_route_power_state = RegisteredAidCache.POWER_STATE_SWITCH_ON
+ | RegisteredAidCache.POWER_STATE_SCREEN_ON_LOCKED;
+ Set<String> aidsForDefaultRoute = mAidRoutingTable.get(mDefaultRoute);
+ if (aidsForDefaultRoute != null) {
+ for (String aid : aidsForDefaultRoute) {
+ default_route_power_state |= aidMap.get(aid).power;
}
- } else {
- entry.isOnHost = false;
- default_route_power_state = RegisteredAidCache.POWER_STATE_ALL;
}
- if (mPowerEmptyAid != default_route_power_state) {
- isPowerStateUpdated = true;
- }
- mPowerEmptyAid = default_route_power_state;
- entry.aidInfo = RegisteredAidCache.AID_ROUTE_QUAL_PREFIX;
- entry.power = default_route_power_state;
-
- aidRoutingTableCache.put(emptyAid, entry);
- if (DBG) Log.d(TAG, "configureRouting: Add emptyAid into AidRoutingTable");
+ } else {
+ entry.isOnHost = false;
+ default_route_power_state = RegisteredAidCache.POWER_STATE_ALL;
}
+ if (mPowerEmptyAid != default_route_power_state) {
+ isPowerStateUpdated = true;
+ }
+ mPowerEmptyAid = default_route_power_state;
+ entry.aidInfo = RegisteredAidCache.AID_ROUTE_QUAL_PREFIX;
+ entry.power = default_route_power_state;
+ aidRoutingTableCache.put(emptyAid, entry);
+ if (DBG) Log.d(TAG, "configureRouting: Add emptyAid into AidRoutingTable");
}
// Register additional offhost AIDs when their support power states are
diff --git a/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java b/NfcNci/src/com/android/nfc/cardemulation/CardEmulationManager.java
index b03725b..67ab85c 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
@@ -394,9 +404,10 @@
mEnabledNfcFServices.onNfcDisabled();
}
- public void onSecureNfcToggled() {
- mAidCache.onSecureNfcToggled();
- mT3tIdentifiersCache.onSecureNfcToggled();
+ public void onTriggerRoutingTableUpdate() {
+ if (DBG) Log.d(TAG, "onTriggerRoutingTableUpdate");
+ mAidCache.onTriggerRoutingTableUpdate();
+ mT3tIdentifiersCache.onTriggerRoutingTableUpdate();
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -465,6 +476,9 @@
// Update the preferred services list
mPreferredServices.onServicesUpdated();
mHostEmulationManager.updatePollingLoopFilters(userId, services);
+ if (Flags.exitFrames()) {
+ updateFirmwareExitFramesForWalletRole(userId);
+ }
NfcService.getInstance().onPreferredPaymentChanged(NfcAdapter.PREFERRED_PAYMENT_UPDATED);
}
@@ -900,11 +914,6 @@
.setPollingLoopFilter(pollingLoopFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -940,11 +949,6 @@
.setPollingLoopFilter(pollingLoopFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -980,11 +984,6 @@
.setPollingLoopFilter(pollingLoopPatternFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -1020,11 +1019,6 @@
.setPollingLoopFilter(pollingLoopPatternFilter)
.build())
.build());
- if (Flags.exitFrames()
- && mAidCache.isDefaultOrAssociatedWalletPackage(service.getPackageName(),
- userId)) {
- updateFirmwareExitFramesForWalletRole(userId);
- }
return true;
}
@@ -1149,7 +1143,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);
@@ -1724,6 +1718,17 @@
}
}
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
+ if (android.nfc.Flags.nfcEventListener()) {
+ callNfcEventCallbacks(listener -> listener.onObserveModeDisabledInFirmware(exitFrame));
+ }
+ mHostEmulationManager.onObserveModeDisabledInFirmware(exitFrame);
+
+ if (mStatsdUtils != null) {
+ mStatsdUtils.logAutoTransactReported(StatsdUtils.PROCESSOR_NFCC, exitFrame.getData());
+ }
+ }
+
@Override
public void onWalletRoleHolderChanged(String holder, int userId) {
mPreferredServices.onWalletRoleHolderChanged(holder, userId);
diff --git a/NfcNci/src/com/android/nfc/cardemulation/EnabledNfcFServices.java b/NfcNci/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
index f45519b..13918e9 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/EnabledNfcFServices.java
@@ -245,7 +245,7 @@
* {@link ProtoOutputStream#end(long)} after.
* Never reuse a proto field number. When removing a field, mark it as reserved.
*/
- void dumpDebug(ProtoOutputStream proto) {
+ public void dumpDebug(ProtoOutputStream proto) {
synchronized (mLock) {
if (mForegroundComponent != null) {
Utils.dumpDebugComponentName(
diff --git a/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java b/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
index 586bb24..506d199 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/HostEmulationManager.java
@@ -208,6 +208,7 @@
boolean mEnableObserveModeAfterTransaction = false;
boolean mEnableObserveModeOnFieldOff = false;
+ PollingFrame mFirmwareExitFrame = null;
ComponentName mPaymentServiceName = null;
@UserIdInt int mPaymentServiceUserId; // The userId of the payment service
ComponentName mLastBoundPaymentServiceName;
@@ -251,7 +252,12 @@
@Override
public void run() {
synchronized (mLock) {
- unbindInactiveServicesLocked();
+ if (isHostCardEmulationActivated()) {
+ // Skip in active state
+ rescheduleInactivityChecks();
+ } else {
+ unbindInactiveServicesLocked();
+ }
}
}
@@ -614,10 +620,21 @@
}
if (serviceInfo.getShouldAutoTransact(dataStr)) {
if (mStatsdUtils != null) {
+ mStatsdUtils.logAutoTransactReported(
+ StatsdUtils.PROCESSOR_HOST, data);
mStatsdUtils.setNextObserveModeTriggerSource(
StatsdUtils.TRIGGER_SOURCE_AUTO_TRANSACT);
}
- allowOneTransaction();
+ if (mFirmwareExitFrame != null && Arrays.equals(
+ mFirmwareExitFrame.getData(), pollingFrame.getData())) {
+ mFirmwareExitFrame = null;
+ mEnableObserveModeAfterTransaction = true;
+ Log.d(TAG,
+ "Polling frame matches exit frame, leaving observe mode "
+ + "disabled");
+ } else {
+ allowOneTransaction();
+ }
pollingFrame.setTriggeredAutoTransact(true);
}
UserHandle user = UserHandle.getUserHandleForUid(serviceInfo.getUid());
@@ -647,6 +664,7 @@
mStatsdUtils.logPollingFrames();
}
}
+ mFirmwareExitFrame = null;
if (mPollingLoopState == PollingLoopState.EVALUATING_POLLING_LOOP) {
if (mPendingPollingLoopFrames.size() >= 3) {
@@ -711,6 +729,15 @@
}
/**
+ * Observe mode was disabled in firmware, we shouldn't autotransact on the next frame.
+ *
+ * This assumes the exit frame will be in the next batch of processed polling frames.
+ */
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
+ mFirmwareExitFrame = exitFrame;
+ }
+
+ /**
* Preferred foreground service changed
*/
public void onPreferredForegroundServiceChanged(ComponentNameAndUser serviceAndUser) {
diff --git a/NfcNci/src/com/android/nfc/cardemulation/PreferredSubscriptionService.java b/NfcNci/src/com/android/nfc/cardemulation/PreferredSubscriptionService.java
index 1b88ce4..de741ab 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/PreferredSubscriptionService.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/PreferredSubscriptionService.java
@@ -15,7 +15,6 @@
*/
package com.android.nfc.cardemulation;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
@@ -32,13 +31,12 @@
static final String TAG = "PreferredSubscriptionService";
static final String PREF_SUBSCRIPTION = "SubscriptionPref";
static final String PREF_PREFERRED_SUB_ID = "pref_sub_id";
- private SharedPreferences mSubscriptionPrefs = null;;
+ private SharedPreferences mSubscriptionPrefs = null;
Context mContext;
Callback mCallback;
int mDefaultSubscriptionId = TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN;
- private final ContentResolver mContentResolver;
boolean mIsEuiccCapable;
boolean mIsUiccCapable;
TelephonyUtils mTelephonyUtils;
@@ -51,7 +49,6 @@
public PreferredSubscriptionService(Context context, Callback callback) {
mContext = context;
- mContentResolver = mContext.getContentResolver();
mCallback = callback;
mIsUiccCapable = context.getPackageManager().hasSystemFeature(
@@ -59,7 +56,7 @@
mIsEuiccCapable = mContext.getResources().getBoolean(R.bool.enable_euicc_support);
mTelephonyUtils = TelephonyUtils.getInstance(context);
- mSubscriptionPrefs = mContext.getSharedPreferences(
+ mSubscriptionPrefs = mContext.getSharedPreferences(
PREF_SUBSCRIPTION, Context.MODE_PRIVATE);
// Initialize default subscription to UICC if there is no preference
@@ -84,7 +81,7 @@
Log.d(TAG, "getPreferredSubscriptionId: " + mDefaultSubscriptionId);
return mSubscriptionPrefs.getInt(
PREF_PREFERRED_SUB_ID, TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN);
- }
+ }
public void setPreferredSubscriptionId(int subscriptionId, boolean force) {
Log.d(TAG, "setPreferredSubscriptionId: " + subscriptionId);
@@ -93,7 +90,7 @@
mSubscriptionPrefs.edit().putInt(PREF_PREFERRED_SUB_ID, subscriptionId).commit();
if (force) {
onDefaultSubscriptionChanged();
- }
+ }
}
}
@@ -112,8 +109,7 @@
if (isActivationStateChanged) {
mCallback.onPreferredSubscriptionChanged(mDefaultSubscriptionId,
mActiveSubscriptoinState == TelephonyUtils.SUBSCRIPTION_STATE_ACTIVATE);
- }
- else {
+ } else {
Log.i(TAG, "onActiveSubscriptionsUpdated: Active Subscription is not changed");
}
}
@@ -123,8 +119,8 @@
Log.d(TAG, "isSubscriptionActivated: get active subscriptions is "
+ "list because it's null");
mActiveSubscriptions = mTelephonyUtils.getActiveSubscriptions().stream().filter(
- TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_UICC.or(
- TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_EUICC))
+ TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_UICC.or(
+ TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_EUICC))
.collect(Collectors.toList());
}
boolean isEuiccSubscription = mTelephonyUtils.isEuiccSubscription(subscriptionId);
@@ -135,8 +131,8 @@
private boolean checkSubscriptionStateChanged(List<SubscriptionInfo> activeSubscriptionList) {
// filtered subscriptions
mActiveSubscriptions = activeSubscriptionList.stream().filter(
- TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_UICC.or(
- TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_EUICC))
+ TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_UICC.or(
+ TelephonyUtils.SUBSCRIPTION_ACTIVE_CONDITION_FOR_EUICC))
.collect(Collectors.toList());
int previousActiveSubscriptionState = mActiveSubscriptoinState;
int currentActiveSubscriptionState = isSubscriptionActivated(mDefaultSubscriptionId) ?
@@ -148,7 +144,6 @@
mActiveSubscriptoinState = currentActiveSubscriptionState;
return true;
}
-
return false;
}
}
diff --git a/NfcNci/src/com/android/nfc/cardemulation/RegisteredAidCache.java b/NfcNci/src/com/android/nfc/cardemulation/RegisteredAidCache.java
index 3082c8c..500b3a6 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/RegisteredAidCache.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/RegisteredAidCache.java
@@ -1516,7 +1516,7 @@
}
}
- public void onSecureNfcToggled() {
+ public void onTriggerRoutingTableUpdate() {
synchronized (mLock) {
updateRoutingLocked(true, false);
}
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/cardemulation/RegisteredT3tIdentifiersCache.java b/NfcNci/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
index 1f2cb08..41e8866 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCache.java
@@ -181,10 +181,10 @@
mRoutingManager.configureRouting(t3tIdentifiers);
}
- public void onSecureNfcToggled() {
+ public void onTriggerRoutingTableUpdate() {
synchronized(mLock) {
updateRoutingLocked(true);
- }
+ }
}
public void onServicesUpdated(int userId, List<NfcFServiceInfo> services) {
diff --git a/NfcNci/src/com/android/nfc/cardemulation/util/StatsdUtils.java b/NfcNci/src/com/android/nfc/cardemulation/util/StatsdUtils.java
index 1ebab76..b67679c 100644
--- a/NfcNci/src/com/android/nfc/cardemulation/util/StatsdUtils.java
+++ b/NfcNci/src/com/android/nfc/cardemulation/util/StatsdUtils.java
@@ -84,6 +84,13 @@
public static final int TRIGGER_SOURCE_AUTO_TRANSACT =
NfcStatsLog.NFC_OBSERVE_MODE_STATE_CHANGED__TRIGGER_SOURCE__AUTO_TRANSACT;
+ public static final int PROCESSOR_UNKNOWN =
+ NfcStatsLog.NFC_AUTO_TRANSACT_REPORTED__AUTO_TRANSACT_PROCESSOR__PROCESSOR_UNKNOWN;
+ public static final int PROCESSOR_HOST =
+ NfcStatsLog.NFC_AUTO_TRANSACT_REPORTED__AUTO_TRANSACT_PROCESSOR__HOST;
+ public static final int PROCESSOR_NFCC =
+ NfcStatsLog.NFC_AUTO_TRANSACT_REPORTED__AUTO_TRANSACT_PROCESSOR__NFCC;
+
/** Name of SE terminal to log in statsd */
private String mSeName = "";
/** Timestamp in millis when app binding starts */
@@ -333,6 +340,11 @@
NfcStatsLog.write(NfcStatsLog.NFC_EXIT_FRAME_TABLE_CHANGED, tableSize, timeoutMs);
}
+ public void logAutoTransactReported(int processor, byte[] data) {
+ NfcStatsLog.write(NfcStatsLog.NFC_AUTO_TRANSACT_REPORTED, processor, data.length,
+ getFrameType(data));
+ }
+
private final HashMap<String, PollingFrameLog> pollingFrameMap = new HashMap<>();
public void tallyPollingFrame(String frameDataHex, PollingFrame frame) {
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 40c5f6c..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
@@ -80,7 +80,7 @@
class NfcExitFrameMultiDeviceTestCases(base_test.BaseTestClass):
def _set_up_emulator(self, *args, start_emulator_fun=None, service_list=[],
expected_service=None, is_payment=False, preferred_service=None,
- payment_default_service=None):
+ payment_default_service=None, should_disable_services_on_destroy=True):
"""
Sets up emulator device for multidevice tests.
:param is_payment: bool
@@ -107,8 +107,9 @@
start_emulator_fun(*args)
else:
if preferred_service is None:
- self.emulator.nfc_emulator.startSimpleEmulatorActivity(service_list,
- expected_service, is_payment)
+ self.emulator.nfc_emulator.startSimpleEmulatorActivity(
+ service_list, expected_service, is_payment,
+ should_disable_services_on_destroy)
else:
self.emulator.nfc_emulator.startSimpleEmulatorActivityWithPreferredService(
service_list, expected_service, preferred_service, is_payment
@@ -156,7 +157,7 @@
self._setup_failure_should_block_tests = True
try:
- devices = self.register_controller(android_device)[:2]
+ devices = self.register_controller(android_device)[:1]
if len(devices) == 1:
self.emulator = devices[0]
else:
@@ -203,17 +204,6 @@
self._setup_failure_reason = 'Failed to connect to PN532 board.'
self.pn532 = pn532.PN532(pn532_serial_path)
self.pn532.mute()
- self._setup_failure_reason = (
- 'Cannot load reader snippet. Is NfcReaderTestApp.apk '
- 'installed on the reader?'
- )
- self.reader.load_snippet('nfc_reader', 'com.android.nfc.reader')
- self.reader.adb.shell(['svc', 'nfc', 'enable'])
- self.reader.debug_tag = 'reader'
- if not self.reader.nfc_reader.isNfcSupported():
- self._setup_failure_reason = f'NFC is not supported on {self.reader}'
- self._setup_failure_should_block_tests = False
- return
except Exception as e:
_LOG.warning('setup_class failed with error %s', e)
return
@@ -237,11 +227,8 @@
" ***")
self.emulator.nfc_emulator.turnScreenOn()
self.emulator.nfc_emulator.pressMenu()
- if not self.pn532:
- self.reader.nfc_reader.turnScreenOn()
- self.reader.nfc_reader.pressMenu()
- """Tests the autotransact functionality.
+ """Tests the autotransact functionality with exit frames.
Test Steps:
1. Start emulator activity and set up payment HCE Service.
@@ -252,20 +239,20 @@
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(
- service_list=[_PAYMENT_SERVICE_1],
- expected_service=_PAYMENT_SERVICE_1,
- is_payment=True,
- payment_default_service=_PAYMENT_SERVICE_1
- )
+ "41fbc7b9", [], 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",
@@ -277,12 +264,17 @@
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, "41fbc7b9")
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)
@@ -296,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/testcases/src/android/nfc/test/TestUtils.java b/NfcNci/tests/testcases/src/android/nfc/test/TestUtils.java
index 6cc5fa9..4e0da92 100644
--- a/NfcNci/tests/testcases/src/android/nfc/test/TestUtils.java
+++ b/NfcNci/tests/testcases/src/android/nfc/test/TestUtils.java
@@ -19,8 +19,10 @@
import static org.junit.Assume.assumeFalse;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.KeyguardManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -54,11 +56,15 @@
static Activity createAndResumeActivity(Class<? extends Activity> activityClass) {
ensureUnlocked();
- Intent intent = new Intent(ApplicationProvider.getApplicationContext(), activityClass);
+ Context context = ApplicationProvider.getApplicationContext();
+ Intent intent = new Intent(context, activityClass);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
-
+ ComponentName topComponentName = context.getSystemService(ActivityManager.class)
+ .getRunningTasks(1).get(0).topActivity;
+ Assert.assertEquals("Foreground activity not in the foreground",
+ activityClass.getName(), topComponentName.getClassName());
return activity;
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/EnableNfcFServiceTest.java b/NfcNci/tests/unit/src/com/android/nfc/EnableNfcFServiceTest.java
index d6524e2..f676d19 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/EnableNfcFServiceTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/EnableNfcFServiceTest.java
@@ -16,25 +16,29 @@
package com.android.nfc;
-import static org.mockito.ArgumentMatchers.isA;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.ContextWrapper;
-import android.content.pm.PackageManager;
import android.nfc.cardemulation.NfcFServiceInfo;
import android.os.UserHandle;
-import android.util.Log;
+import android.util.proto.ProtoOutputStream;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
-import com.android.nfc.cardemulation.AidRoutingManager;
import com.android.nfc.cardemulation.EnabledNfcFServices;
+import com.android.nfc.cardemulation.EnabledNfcFServicesProto;
import com.android.nfc.cardemulation.RegisteredNfcFServicesCache;
import com.android.nfc.cardemulation.RegisteredT3tIdentifiersCache;
import com.android.nfc.cardemulation.RoutingOptionManager;
@@ -47,6 +51,10 @@
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+
@RunWith(AndroidJUnit4.class)
public class EnableNfcFServiceTest {
@@ -56,6 +64,7 @@
private NfcFServiceInfo mNfcFServiceInfo;
private EnabledNfcFServices mEnabledNfcFServices;
private ForegroundUtils mForegroundUtils;
+ private EnabledNfcFServices.Callback mCallback;
@Before
public void setUp() throws Exception {
@@ -85,13 +94,12 @@
RoutingOptionManager routingOptionManager = mock(RoutingOptionManager.class);
when(RoutingOptionManager.getInstance()).thenReturn(routingOptionManager);
+
+ mCallback = mock(EnabledNfcFServices.Callback.class);
InstrumentationRegistry.getInstrumentation().runOnMainSync(
() -> mEnabledNfcFServices = new EnabledNfcFServices(mockContext,
registeredNfcFServicesCache, registeredT3tIdentifiersCache,
- (userId, service) -> {
- Log.d(TAG, "CallBack is Received for userid " + userId);
-
- }));
+ mCallback));
Assert.assertNotNull(mEnabledNfcFServices);
}
@@ -106,14 +114,14 @@
Assert.assertFalse(isActivated);
mEnabledNfcFServices.onHostEmulationActivated();
isActivated = mEnabledNfcFServices.isActivated();
- Assert.assertTrue(isActivated);
+ assertTrue(isActivated);
}
@Test
public void testOnHostEmulationDeactivated() {
mEnabledNfcFServices.onHostEmulationActivated();
boolean isActivated = mEnabledNfcFServices.isActivated();
- Assert.assertTrue(isActivated);
+ assertTrue(isActivated);
mEnabledNfcFServices.onHostEmulationDeactivated();
isActivated = mEnabledNfcFServices.isActivated();
Assert.assertFalse(isActivated);
@@ -131,7 +139,7 @@
true);
boolean isRegistered = mEnabledNfcFServices.registerEnabledForegroundService(mComponentName,
1);
- Assert.assertTrue(isRegistered);
+ assertTrue(isRegistered);
}
@@ -139,14 +147,152 @@
public void testOnNfcDisabled() {
mEnabledNfcFServices.onNfcDisabled();
boolean isNfcDisabled = mEnabledNfcFServices.isNfcDisabled();
- Assert.assertTrue(isNfcDisabled);
+ assertTrue(isNfcDisabled);
}
@Test
public void testOnUserSwitched() {
mEnabledNfcFServices.onUserSwitched(0);
boolean isUserSwitched = mEnabledNfcFServices.isUserSwitched();
- Assert.assertTrue(isUserSwitched);
+ assertTrue(isUserSwitched);
}
+
+ @Test
+ public void testDumpDebug() throws NoSuchFieldException, IllegalAccessException {
+ ProtoOutputStream proto = mock(ProtoOutputStream.class);
+ ComponentName mForegroundComponent = mock(ComponentName.class);
+ ComponentName mForegroundRequested = mock(ComponentName.class);
+ Field fieldForegroundComp = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundComponent");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mEnabledNfcFServices, mForegroundComponent);
+ Field fieldForegroundReq = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundRequested");
+ fieldForegroundReq.setAccessible(true);
+ fieldForegroundReq.set(mEnabledNfcFServices, mForegroundRequested);
+ mEnabledNfcFServices.dump(mock(FileDescriptor.class), mock(PrintWriter.class),
+ new String[]{});
+
+ mEnabledNfcFServices.dumpDebug(proto);
+ verify(proto).write(eq(EnabledNfcFServicesProto.ACTIVATED), anyBoolean());
+ }
+
+ @Test
+ public void testUnRegisterForegroundService()
+ throws NoSuchFieldException, IllegalAccessException {
+ int mForegroundUid = 1;
+ int userId = 1;
+ ComponentName mForegroundComponent = mock(ComponentName.class);
+ ComponentName mForegroundRequested = mock(ComponentName.class);
+ UserHandle userHandle = mock(UserHandle.class);
+ Field fieldForegroundUid = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundUid");
+ fieldForegroundUid.setAccessible(true);
+ fieldForegroundUid.set(mEnabledNfcFServices, mForegroundUid);
+ Field fieldForegroundComp = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundComponent");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mEnabledNfcFServices, mForegroundComponent);
+ Field fieldForegroundReq = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundRequested");
+ fieldForegroundReq.setAccessible(true);
+ fieldForegroundReq.set(mEnabledNfcFServices, mForegroundRequested);
+ when(UserHandle.getUserHandleForUid(anyInt())).thenReturn(userHandle);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+
+ mEnabledNfcFServices.onUidToBackground(mForegroundUid);
+ verify(mCallback).onEnabledForegroundNfcFServiceChanged(userId, null);
+ verify(userHandle).getIdentifier();
+ }
+
+ @Test
+ public void testUnregisteredEnabledForegroundService()
+ throws NoSuchFieldException, IllegalAccessException {
+ int callingId = 1;
+ int mForegroundUid = 1;
+ int userId = 1;
+ ComponentName mForegroundComponent = mock(ComponentName.class);
+ ComponentName mForegroundRequested = mock(ComponentName.class);
+ UserHandle userHandle = mock(UserHandle.class);
+ Field fieldForegroundUid = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundUid");
+ fieldForegroundUid.setAccessible(true);
+ fieldForegroundUid.set(mEnabledNfcFServices, mForegroundUid);
+ Field fieldForegroundComp = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundComponent");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mEnabledNfcFServices, mForegroundComponent);
+ Field fieldForegroundReq = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundRequested");
+ fieldForegroundReq.setAccessible(true);
+ fieldForegroundReq.set(mEnabledNfcFServices, mForegroundRequested);
+ when(UserHandle.getUserHandleForUid(anyInt())).thenReturn(userHandle);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+ when(mForegroundUtils.isInForeground(callingId)).thenReturn(true);
+
+ assertTrue(mEnabledNfcFServices.unregisteredEnabledForegroundService(callingId));
+ verify(mCallback).onEnabledForegroundNfcFServiceChanged(userId, null);
+ verify(mForegroundUtils).isInForeground(callingId);
+ }
+
+ @Test
+ public void testUnregisteredEnabledForegroundServiceNonForegroundUid() {
+ int callingId = 1;
+ when(mForegroundUtils.isInForeground(callingId)).thenReturn(false);
+
+ assertFalse(mEnabledNfcFServices.unregisteredEnabledForegroundService(callingId));
+ verify(mForegroundUtils).isInForeground(callingId);
+ }
+
+ @Test
+ public void testOnServiceUpdate() throws NoSuchFieldException, IllegalAccessException {
+ int userId = 1;
+ ComponentName mForegroundComponent = mock(ComponentName.class);
+ ComponentName mForegroundRequested = mock(ComponentName.class);
+ UserHandle userHandle = mock(UserHandle.class);
+ Field fieldForegroundComp = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundComponent");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mEnabledNfcFServices, mForegroundComponent);
+ Field fieldForegroundReq = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundRequested");
+ fieldForegroundReq.setAccessible(true);
+ fieldForegroundReq.set(mEnabledNfcFServices, mForegroundRequested);
+ when(UserHandle.getUserHandleForUid(anyInt())).thenReturn(userHandle);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+
+ mEnabledNfcFServices.onServicesUpdated();
+ verify(mCallback).onEnabledForegroundNfcFServiceChanged(userId, null);
+ verify(userHandle).getIdentifier();
+ }
+
+ @Test
+ public void testOnHostEmulationDeactivatedWithPostponedConfiguration()
+ throws NoSuchFieldException, IllegalAccessException {
+ boolean mComputeFgRequested = true;
+ int userId = 1;
+ ComponentName mForegroundRequested = mock(ComponentName.class);
+ UserHandle userHandle = mock(UserHandle.class);
+ Field fieldForegroundUid = EnabledNfcFServices.class.getDeclaredField(
+ "mComputeFgRequested");
+ fieldForegroundUid.setAccessible(true);
+ fieldForegroundUid.set(mEnabledNfcFServices, mComputeFgRequested);
+ Field fieldForegroundComp = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundComponent");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mEnabledNfcFServices, null);
+ Field fieldForegroundReq = EnabledNfcFServices.class.getDeclaredField(
+ "mForegroundRequested");
+ fieldForegroundReq.setAccessible(true);
+ fieldForegroundReq.set(mEnabledNfcFServices, mForegroundRequested);
+ when(UserHandle.getUserHandleForUid(anyInt())).thenReturn(userHandle);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+
+ mEnabledNfcFServices.onHostEmulationDeactivated();
+ verify(mCallback).onEnabledForegroundNfcFServiceChanged(userId, mForegroundRequested);
+ verify(userHandle).getIdentifier();
+ verify(mForegroundRequested).equals(null);
+ }
+
}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/ExitFrameTest.java b/NfcNci/tests/unit/src/com/android/nfc/ExitFrameTest.java
index b0cb06f..a15ec50 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/ExitFrameTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/ExitFrameTest.java
@@ -53,9 +53,9 @@
@Test
public void testPrefixMatchingMaxLength() {
- ExitFrame frame = new ExitFrame("00112233445566778899AABBCCDDEEFF.*");
+ ExitFrame frame = new ExitFrame("00112233445566778899AABBCCDD.*");
- assertArrayEquals(HexFormat.of().parseHex("00112233445566778899AABBCCDDEEFF"),
+ assertArrayEquals(HexFormat.of().parseHex("00112233445566778899AABBCCDD"),
frame.getData());
assertTrue(frame.isPrefixMatchingAllowed());
}
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 0fe2031..82c0d4f 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/NfcProprietaryCapsTest.java
@@ -126,13 +126,15 @@
true,
false,
true,
- 5
+ 5,
+ false
);
String expected = "NfcProprietaryCaps{" +
"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 31f7af1..6bafec4 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);
@@ -1375,7 +1375,7 @@
@Test
public void testOnSeSelected() {
- mNfcService.onSeSelected();
+ mNfcService.onSeSelected(NfcService.SE_SELECTED_AID);
mLooper.dispatchAll();
verify(mCardEmulationManager).onOffHostAidSelected();
}
@@ -2068,7 +2068,7 @@
verify(mBackupManager).dataChanged();
verify(mDeviceHost).setNfcSecure(true);
verify(mNfcEventLog, times(2)).logEvent(any());
- verify(mCardEmulationManager).onSecureNfcToggled();
+ verify(mCardEmulationManager).onTriggerRoutingTableUpdate();
}
@Test
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 ae8f2fd..574ad68 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/CardEmulationManagerTest.java
@@ -20,6 +20,7 @@
import static android.nfc.cardemulation.CardEmulation.SET_SERVICE_ENABLED_STATUS_OK;
import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -42,13 +43,17 @@
import android.app.ActivityManager;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
-import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.nfc.ComponentNameAndUser;
+import android.nfc.Constants;
import android.nfc.INfcCardEmulation;
+import android.nfc.INfcOemExtensionCallback;
import android.nfc.NfcAdapter;
+import android.nfc.NfcOemExtension;
import android.nfc.PackageAndUser;
import android.nfc.cardemulation.AidGroup;
import android.nfc.cardemulation.ApduServiceInfo;
@@ -61,17 +66,20 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.util.Pair;
+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;
import com.android.nfc.NfcInjector;
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 org.junit.After;
@@ -85,20 +93,23 @@
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HexFormat;
import java.util.List;
-import java.util.Objects;
+import java.util.Optional;
import java.util.regex.Pattern;
public class CardEmulationManagerTest {
private static final int USER_ID = 0;
private static final UserHandle USER_HANDLE = UserHandle.of(USER_ID);
- private static final byte[] TEST_DATA_1 = new byte[] {(byte) 0xd2};
- private static final byte[] TEST_DATA_2 = new byte[] {(byte) 0xd3};
+ private static final byte[] TEST_DATA_1 = new byte[]{(byte) 0xd2};
+ private static final byte[] TEST_DATA_2 = new byte[]{(byte) 0xd3};
private static final byte[] PROPER_SKIP_DATA_NDF1_HEADER =
- new byte[] {
+ new byte[]{
0x00,
(byte) 0xa4,
0x04,
@@ -113,7 +124,7 @@
0x00
};
private static final byte[] PROPER_SKIP_DATA_NDF2_HEADER =
- new byte[] {
+ new byte[]{
0x00,
(byte) 0xa4,
0x04,
@@ -137,29 +148,56 @@
"com.android.test.walletroleholder.WalletRoleHolderApduService");
private static final String PAYMENT_AID_1 = "A000000004101012";
- @Mock private Context mContext;
- @Mock private Resources mResources;
- @Mock private ForegroundUtils mForegroundUtils;
- @Mock private WalletRoleObserver mWalletRoleObserver;
- @Mock private RegisteredAidCache mRegisteredAidCache;
- @Mock private RegisteredT3tIdentifiersCache mRegisteredT3tIdentifiersCache;
- @Mock private HostEmulationManager mHostEmulationManager;
- @Mock private HostNfcFEmulationManager mHostNfcFEmulationManager;
- @Mock private RegisteredServicesCache mRegisteredServicesCache;
- @Mock private RegisteredNfcFServicesCache mRegisteredNfcFServicesCache;
- @Mock private PreferredServices mPreferredServices;
- @Mock private EnabledNfcFServices mEnabledNfcFServices;
- @Mock private RoutingOptionManager mRoutingOptionManager;
- @Mock private PowerManager mPowerManager;
- @Mock private NfcService mNfcService;
- @Mock private UserManager mUserManager;
- @Mock private NfcAdapter mNfcAdapter;
- @Mock private NfcEventLog mNfcEventLog;
- @Mock private PreferredSubscriptionService mPreferredSubscriptionService;
- @Captor private ArgumentCaptor<List<PollingFrame>> mPollingLoopFrameCaptor;
- @Captor private ArgumentCaptor<byte[]> mDataCaptor;
- @Captor private ArgumentCaptor<List<ApduServiceInfo>> mServiceListCaptor;
- @Captor private ArgumentCaptor<List<NfcFServiceInfo>> mNfcServiceListCaptor;
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private ForegroundUtils mForegroundUtils;
+ @Mock
+ private WalletRoleObserver mWalletRoleObserver;
+ @Mock
+ private RegisteredAidCache mRegisteredAidCache;
+ @Mock
+ private RegisteredT3tIdentifiersCache mRegisteredT3tIdentifiersCache;
+ @Mock
+ private HostEmulationManager mHostEmulationManager;
+ @Mock
+ private HostNfcFEmulationManager mHostNfcFEmulationManager;
+ @Mock
+ private RegisteredServicesCache mRegisteredServicesCache;
+ @Mock
+ private RegisteredNfcFServicesCache mRegisteredNfcFServicesCache;
+ @Mock
+ private PreferredServices mPreferredServices;
+ @Mock
+ private EnabledNfcFServices mEnabledNfcFServices;
+ @Mock
+ private RoutingOptionManager mRoutingOptionManager;
+ @Mock
+ private PowerManager mPowerManager;
+ @Mock
+ private NfcService mNfcService;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private NfcAdapter mNfcAdapter;
+ @Mock
+ private NfcEventLog mNfcEventLog;
+ @Mock
+ private PreferredSubscriptionService mPreferredSubscriptionService;
+ @Mock
+ private StatsdUtils mStatsdUtils;
+ @Mock
+ private DeviceConfigFacade mDeviceConfigFacade;
+ @Captor
+ private ArgumentCaptor<List<PollingFrame>> mPollingLoopFrameCaptor;
+ @Captor
+ private ArgumentCaptor<byte[]> mDataCaptor;
+ @Captor
+ private ArgumentCaptor<List<ApduServiceInfo>> mServiceListCaptor;
+ @Captor
+ private ArgumentCaptor<List<NfcFServiceInfo>> mNfcServiceListCaptor;
private MockitoSession mStaticMockSession;
private CardEmulationManager mCardEmulationManager;
@@ -187,7 +225,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();
@@ -397,15 +435,18 @@
@Test
public void testOnSecureNfcToggled() {
- mCardEmulationManager.onSecureNfcToggled();
+ mCardEmulationManager.onTriggerRoutingTableUpdate();
- verify(mRegisteredAidCache).onSecureNfcToggled();
- verify(mRegisteredT3tIdentifiersCache).onSecureNfcToggled();
+ verify(mRegisteredAidCache).onTriggerRoutingTableUpdate();
+ verify(mRegisteredT3tIdentifiersCache).onTriggerRoutingTableUpdate();
}
@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);
@@ -414,6 +455,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());
@@ -1467,7 +1509,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);
@@ -1490,7 +1532,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);
@@ -2232,7 +2274,9 @@
mRoutingOptionManager,
mPowerManager,
mNfcEventLog,
- mPreferredSubscriptionService);
+ mPreferredSubscriptionService,
+ mStatsdUtils,
+ mDeviceConfigFacade);
}
@Test
@@ -2428,7 +2472,7 @@
INfcCardEmulation iNfcCardEmulation = mCardEmulationManager.getNfcCardEmulationInterface();
assertThat(iNfcCardEmulation).isNotNull();
ApduServiceInfo apduServiceInfo = mock(ApduServiceInfo.class);
- List<ApduServiceInfo> apduServiceInfoList = new ArrayList<>();
+ List<ApduServiceInfo> apduServiceInfoList = new ArrayList<>();
apduServiceInfoList.add(apduServiceInfo);
when(mRegisteredServicesCache.getServicesForCategory(1, "payment"))
.thenReturn(apduServiceInfoList);
@@ -2448,7 +2492,7 @@
}
@Test
- public void testSupportsAidPrefixRegistration() throws RemoteException {
+ public void testSupportsAidPrefixRegistration() throws RemoteException {
INfcCardEmulation iNfcCardEmulation = mCardEmulationManager.getNfcCardEmulationInterface();
assertThat(iNfcCardEmulation).isNotNull();
when(mRegisteredAidCache
@@ -2481,8 +2525,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
@@ -2680,163 +2723,513 @@
}
@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());
+ public void testDump() {
+ FileDescriptor fd = mock(FileDescriptor.class);
+ PrintWriter pw = mock(PrintWriter.class);
+ String[] args = new String[]{"test"};
- mCardEmulationManager.getNfcCardEmulationInterface().registerPollingLoopFilterForService(
- USER_ID, WALLET_PAYMENT_SERVICE, "aa", true);
-
- verify(mNfcService).setFirmwareExitFrameTable(any(), anyInt());
+ mCardEmulationManager.dump(fd, pw, args);
+ verify(mRegisteredServicesCache).dump(fd, pw, args);
}
@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());
+ public void testDumpDebug() {
+ ProtoOutputStream proto = mock(ProtoOutputStream.class);
+ when(proto.start(CardEmulationManagerProto.REGISTERED_SERVICES_CACHE)).thenReturn((long) 1);
- mCardEmulationManager.getNfcCardEmulationInterface().registerPollingLoopFilterForService(
- USER_ID, new ComponentName("com.android.test", "com.android.test.Service"), "aa",
+ mCardEmulationManager.dumpDebug(proto);
+ verify(mRegisteredServicesCache).dumpDebug(proto);
+ }
+
+ @Test
+ public void testOnPreferredSubscriptionChangedWithSimEuicc1()
+ throws NoSuchFieldException, IllegalAccessException {
+ int subscriptionId = 1;
+ boolean isActive = true;
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(true);
+ when(subscriptionInfo.getPortIndex()).thenReturn(0);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(mRoutingOptionManager.getSecureElementForRoute(anyInt())).thenReturn("");
+
+ mCardEmulationManager.onPreferredSubscriptionChanged(subscriptionId, isActive);
+ verify(mRoutingOptionManager).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_EUICC_1);
+ verify(mRegisteredAidCache).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_EUICC_1);
+ }
+
+ @Test
+ public void testOnPreferredSubscriptionChangedWithSimEuicc2()
+ throws NoSuchFieldException, IllegalAccessException {
+ int subscriptionId = 1;
+ boolean isActive = true;
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(true);
+ when(subscriptionInfo.getPortIndex()).thenReturn(1);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(mRoutingOptionManager.getSecureElementForRoute(anyInt())).thenReturn("");
+
+ mCardEmulationManager.onPreferredSubscriptionChanged(subscriptionId, isActive);
+ verify(mRoutingOptionManager).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_EUICC_2);
+ verify(mRegisteredAidCache).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_EUICC_2);
+ }
+
+ @Test
+ public void testOnPreferredSubscriptionChangedWithSimUicc()
+ throws NoSuchFieldException, IllegalAccessException {
+ int subscriptionId = 1;
+ boolean isActive = true;
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(false);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(mRoutingOptionManager.getSecureElementForRoute(anyInt())).thenReturn("");
+
+ mCardEmulationManager.onPreferredSubscriptionChanged(subscriptionId, isActive);
+ verify(mRoutingOptionManager).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UICC);
+ verify(mRegisteredAidCache).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UICC);
+ }
+
+ @Test
+ public void testOnPreferredSubscriptionChangedWithSimUnknown()
+ throws NoSuchFieldException, IllegalAccessException {
+ int subscriptionId = 1;
+ boolean isActive = true;
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.empty();
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+
+ mCardEmulationManager.onPreferredSubscriptionChanged(subscriptionId, isActive);
+ verify(mRoutingOptionManager).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UNKNOWN);
+ verify(mRegisteredAidCache).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UNKNOWN);
+ }
+
+ @Test
+ public void testOnPreferredSubscriptionChangedWithSimInActive()
+ throws NoSuchFieldException, IllegalAccessException {
+ int subscriptionId = 1;
+ boolean isActive = false;
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+
+ mCardEmulationManager.onPreferredSubscriptionChanged(subscriptionId, isActive);
+ verify(mRoutingOptionManager).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UNKNOWN);
+ verify(mRegisteredAidCache).onPreferredSimChanged(TelephonyUtils.SIM_TYPE_UNKNOWN);
+ }
+
+ @Test
+ public void testOnEeListenActivated() {
+ mCardEmulationManager.onEeListenActivated(false);
+
+ verify(mPreferredServices).onHostEmulationDeactivated();
+ }
+
+ @Test
+ public void testOnFieldChangeDetected() {
+ mCardEmulationManager.onFieldChangeDetected(true);
+ verify(mHostEmulationManager).onFieldChangeDetected(true);
+ }
+
+ @Test
+ public void testOnHostCardEmulationDataWithApdu() throws RemoteException {
+ INfcOemExtensionCallback nfcOemExtensionCallback = mock(INfcOemExtensionCallback.class);
+ mCardEmulationManager.setOemExtension(nfcOemExtensionCallback);
+
+ mCardEmulationManager.onHostCardEmulationData(
+ CardEmulationManager.NFC_HCE_APDU, PROPER_SKIP_DATA_NDF1_HEADER);
+ verify(nfcOemExtensionCallback).onHceEventReceived(NfcOemExtension.HCE_DATA_TRANSFERRED);
+ verify(mHostEmulationManager).onHostEmulationData(PROPER_SKIP_DATA_NDF1_HEADER);
+ }
+
+ @Test
+ public void testOnHostCardEmulationDataWithNfcf() throws RemoteException {
+ INfcOemExtensionCallback nfcOemExtensionCallback = mock(INfcOemExtensionCallback.class);
+ mCardEmulationManager.setOemExtension(nfcOemExtensionCallback);
+
+ mCardEmulationManager.onHostCardEmulationData(
+ CardEmulationManager.NFC_HCE_NFCF, PROPER_SKIP_DATA_NDF1_HEADER);
+ verify(nfcOemExtensionCallback).onHceEventReceived(NfcOemExtension.HCE_DATA_TRANSFERRED);
+ verify(mHostNfcFEmulationManager).onHostEmulationData(PROPER_SKIP_DATA_NDF1_HEADER);
+ verify(mPowerManager).userActivity(anyLong(), eq(PowerManager.USER_ACTIVITY_EVENT_TOUCH),
+ eq(0));
+ }
+
+ @Test
+ public void testOnHostCardEmulationDeactivatedWithApdu() throws RemoteException {
+ INfcOemExtensionCallback nfcOemExtensionCallback = mock(INfcOemExtensionCallback.class);
+ mCardEmulationManager.setOemExtension(nfcOemExtensionCallback);
+ ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
+
+ mCardEmulationManager.onHostCardEmulationDeactivated(CardEmulationManager.NFC_HCE_APDU);
+ verify(mHostEmulationManager).onHostEmulationDeactivated();
+ verify(mPreferredServices).onHostEmulationDeactivated();
+ verify(nfcOemExtensionCallback).onHceEventReceived(captor.capture());
+ assertEquals(NfcOemExtension.HCE_DEACTIVATE, captor.getValue().intValue());
+ }
+
+ @Test
+ public void testSetDefaultServiceForCategoryChecked() {
+ int userId = 1;
+ ComponentName componentName = new ComponentName("com.example.nfc", "ExampleNfcClass");
+ String category = CardEmulation.CATEGORY_PAYMENT;
+ Context context = mock(Context.class);
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ UserHandle userHandle = mock(UserHandle.class);
+ when(UserHandle.of(userId)).thenReturn(userHandle);
+ when(mRegisteredServicesCache.hasService(userId, componentName)).thenReturn(true);
+ when(mContext.createContextAsUser(userHandle, 0)).thenReturn(context);
+ when(context.getContentResolver()).thenReturn(contentResolver);
+
+ assertTrue(mCardEmulationManager.setDefaultServiceForCategoryChecked(userId, componentName,
+ category));
+ verify(mRegisteredServicesCache).hasService(userId, componentName);
+ }
+
+ @Test
+ public void testSetDefaultServiceForCategoryCheckedWithOtherCategory() {
+ assertFalse(mCardEmulationManager.setDefaultServiceForCategoryChecked(1,
+ new ComponentName("com.example.nfc", "ExampleNfcClass"),
+ CardEmulation.CATEGORY_OTHER));
+ }
+
+ @Test
+ public void testUpdateForDefaultSwpToEuicc() throws NoSuchFieldException,
+ IllegalAccessException {
+ int subscriptionId = 1;
+ when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(true);
+ Resources resources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(resources);
+ when(resources.getBoolean(anyInt())).thenReturn(true);
+ when(NfcInjector.NfcProperties.isEuiccSupported()).thenReturn(true);
+ when(mPreferredSubscriptionService.getPreferredSubscriptionId()).thenReturn(subscriptionId);
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(true);
+ when(subscriptionInfo.getPortIndex()).thenReturn(0);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(telephonyUtils.updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1)).thenReturn(
+ "6F02839000");
+
+ mCardEmulationManager.updateForDefaultSwpToEuicc();
+ verify(mPreferredSubscriptionService).getPreferredSubscriptionId();
+ verify(telephonyUtils).updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1);
+ verify(mContext).getResources();
+ }
+
+ @Test
+ public void testUpdateForDefaultSwpToEuiccWithCmdFail() throws NoSuchFieldException,
+ IllegalAccessException {
+ int subscriptionId = 3;
+ when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(true);
+ Resources resources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(resources);
+ when(resources.getBoolean(anyInt())).thenReturn(true);
+ when(NfcInjector.NfcProperties.isEuiccSupported()).thenReturn(true);
+ when(mPreferredSubscriptionService.getPreferredSubscriptionId()).thenReturn(subscriptionId);
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(true);
+ when(subscriptionInfo.getPortIndex()).thenReturn(0);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(telephonyUtils.updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1)).thenReturn(
+ "6F0283FFFF");
+
+ mCardEmulationManager.updateForDefaultSwpToEuicc();
+ verify(mPreferredSubscriptionService).getPreferredSubscriptionId();
+ verify(telephonyUtils).updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1);
+ verify(mContext).getResources();
+ verify(resources).getBoolean(anyInt());
+ }
+
+ @Test
+ public void testUpdateForDefaultSwpToEuiccWithWrongLength() throws NoSuchFieldException,
+ IllegalAccessException {
+ int subscriptionId = 3;
+ when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(true);
+ Resources resources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(resources);
+ when(resources.getBoolean(anyInt())).thenReturn(true);
+ when(NfcInjector.NfcProperties.isEuiccSupported()).thenReturn(true);
+ when(mPreferredSubscriptionService.getPreferredSubscriptionId()).thenReturn(subscriptionId);
+ TelephonyUtils telephonyUtils = mock(TelephonyUtils.class);
+ SubscriptionInfo subscriptionInfo = mock(SubscriptionInfo.class);
+ Optional<SubscriptionInfo> optionalInfo = Optional.of(subscriptionInfo);
+ Field field = CardEmulationManager.class.getDeclaredField("mTelephonyUtils");
+ field.setAccessible(true);
+ field.set(mCardEmulationManager, telephonyUtils);
+ when(subscriptionInfo.isEmbedded()).thenReturn(true);
+ when(subscriptionInfo.getPortIndex()).thenReturn(0);
+ when(telephonyUtils.getActiveSubscriptionInfoById(subscriptionId)).thenReturn(optionalInfo);
+ when(telephonyUtils.updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1)).thenReturn(
+ "6FF");
+
+ mCardEmulationManager.updateForDefaultSwpToEuicc();
+ verify(mPreferredSubscriptionService).getPreferredSubscriptionId();
+ verify(telephonyUtils).updateSwpStatusForEuicc(TelephonyUtils.SIM_TYPE_EUICC_1);
+ verify(mContext).getResources();
+ verify(resources).getBoolean(anyInt());
+ }
+
+ @Test
+ public void testUpdateForDefaultSwpToEuiccWithEmulationDisabled() {
+ when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(false);
+
+ mCardEmulationManager.updateForDefaultSwpToEuicc();
+ verify(mContext, never()).getResources();
+ }
+
+ @Test
+ public void testUpdateForDefaultSwpToEuiccWithEmulationNotSupport() {
+ when(android.nfc.Flags.enableCardEmulationEuicc()).thenReturn(true);
+ Resources resources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(resources);
+ when(resources.getBoolean(anyInt())).thenReturn(false);
+ when(NfcInjector.NfcProperties.isEuiccSupported()).thenReturn(false);
+
+ mCardEmulationManager.updateForDefaultSwpToEuicc();
+ verify(mContext).getResources();
+ verify(mPreferredSubscriptionService, never()).getPreferredSubscriptionId();
+ }
+
+ @Test
+ public void testWasServicePreInstalled() throws PackageManager.NameNotFoundException {
+ PackageManager packageManager = mock(PackageManager.class);
+ ComponentName service = new ComponentName("com.example.nfc", "NfcClass");
+ ApplicationInfo ai = mock(ApplicationInfo.class);
+ ai.flags = 1;
+ when(packageManager.getApplicationInfo("com.example.nfc", 0)).thenReturn(ai);
+
+ assertTrue(mCardEmulationManager.wasServicePreInstalled(packageManager, service));
+ }
+
+ @Test
+ public void testWasServicePreInstalledWithoutService()
+ throws PackageManager.NameNotFoundException {
+ PackageManager packageManager = mock(PackageManager.class);
+ ComponentName service = new ComponentName("com.example.nfc", "NfcClass");
+ when(packageManager.getApplicationInfo("com.example.nfc", 0)).thenThrow(
+ PackageManager.NameNotFoundException.class);
+
+ assertFalse(mCardEmulationManager.wasServicePreInstalled(packageManager, service));
+ }
+
+ @Test
+ public void testWasServicePreInstalledWithServiceNotPreInstalled()
+ throws PackageManager.NameNotFoundException {
+ PackageManager packageManager = mock(PackageManager.class);
+ ComponentName service = new ComponentName("com.example.nfc", "NfcClass");
+ ApplicationInfo ai = mock(ApplicationInfo.class);
+ ai.flags = 0;
+ when(packageManager.getApplicationInfo("com.example.nfc", 0)).thenReturn(ai);
+
+ assertFalse(mCardEmulationManager.wasServicePreInstalled(packageManager, service));
+ }
+
+ @Test
+ public void testVerifyDefaults() {
+ int userId = 1;
+ List<ApduServiceInfo> services = new ArrayList<>();
+ List<UserHandle> luh = new ArrayList<>();
+ boolean validateInstalled = true;
+ UserHandle userHandle = mock(UserHandle.class);
+ UserHandle secondUserHandle = mock(UserHandle.class);
+ Context context = mock(Context.class);
+ UserManager um = mock(UserManager.class);
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ luh.add(userHandle);
+ luh.add(secondUserHandle);
+ String compName = "com.nfc/.NfcClass";
+ ComponentName service = ComponentName.unflattenFromString(compName);
+ //"com.nfc/.NfcClass" becomes package="com.nfc" class="com.nfc.NfcClass".
+ when(UserHandle.of(userId)).thenReturn(userHandle);
+ when(mContext.createContextAsUser(userHandle, 0)).thenReturn(context);
+ when(context.getSystemService(UserManager.class)).thenReturn(um);
+ when(um.getEnabledProfiles()).thenReturn(luh);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+ when(secondUserHandle.getIdentifier()).thenReturn(userId);
+ when(context.getContentResolver()).thenReturn(contentResolver);
+ when(Settings.Secure.getString(contentResolver,
+ Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT)).thenReturn(
+ compName);
+ when(mRegisteredServicesCache.hasService(userId, service)).thenReturn(true);
+
+ mCardEmulationManager.verifyDefaults(userId, services, validateInstalled);
+ verify(um).getEnabledProfiles();
+ verify(context).getSystemService(UserManager.class);
+ verify(mRegisteredServicesCache, times(2)).hasService(userId, service);
+ }
+
+ @Test
+ public void testVerifyDefaultsWithMorePaymentService()
+ throws PackageManager.NameNotFoundException {
+ int userId = 1;
+ List<ApduServiceInfo> services = new ArrayList<>();
+ List<UserHandle> luh = new ArrayList<>();
+ boolean validateInstalled = true;
+ UserHandle userHandle = mock(UserHandle.class);
+ UserHandle secondUserHandle = mock(UserHandle.class);
+ Context context = mock(Context.class);
+ UserManager um = mock(UserManager.class);
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ luh.add(userHandle);
+ luh.add(secondUserHandle);
+ String compName = "com.nfc/.NfcClass";
+ ComponentName service = ComponentName.unflattenFromString(compName);
+ PackageManager pm = mock(PackageManager.class);
+ ApduServiceInfo apduService = mock(ApduServiceInfo.class);
+ ApduServiceInfo apduService2 = mock(ApduServiceInfo.class);
+ services.add(apduService);
+ services.add(apduService2);
+ ApplicationInfo ai = mock(ApplicationInfo.class);
+ ai.flags = 1;
+
+ when(UserHandle.of(userId)).thenReturn(userHandle);
+ when(mContext.createContextAsUser(userHandle, 0)).thenReturn(context);
+ when(context.getSystemService(UserManager.class)).thenReturn(um);
+ when(um.getEnabledProfiles()).thenReturn(luh);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+ when(secondUserHandle.getIdentifier()).thenReturn(userId);
+ when(context.getContentResolver()).thenReturn(contentResolver);
+ when(Settings.Secure.getString(contentResolver,
+ Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT)).thenReturn(
+ "");
+ when(mContext.createPackageContextAsUser("android", 0, userHandle)).thenReturn(context);
+ when(context.getPackageManager()).thenReturn(pm);
+ when(apduService.hasCategory(CardEmulation.CATEGORY_PAYMENT)).thenReturn(true);
+ when(apduService2.hasCategory(CardEmulation.CATEGORY_PAYMENT)).thenReturn(true);
+ when(apduService.getComponent()).thenReturn(service);
+ when(apduService2.getComponent()).thenReturn(service);
+ when(pm.getApplicationInfo("com.nfc", 0)).thenReturn(ai);
+ when(mRegisteredServicesCache.hasService(userId, service)).thenReturn(true);
+
+ mCardEmulationManager.verifyDefaults(userId, services, validateInstalled);
+ verify(um).getEnabledProfiles();
+ verify(mContext).createPackageContextAsUser("android", 0, userHandle);
+ verify(pm, times(2)).getApplicationInfo("com.nfc", 0);
+ }
+
+ @Test
+ public void testVerifyDefaultsWithSinglePaymentService()
+ throws PackageManager.NameNotFoundException {
+ int userId = 1;
+ List<ApduServiceInfo> services = new ArrayList<>();
+ List<UserHandle> luh = new ArrayList<>();
+ boolean validateInstalled = true;
+ UserHandle userHandle = mock(UserHandle.class);
+ UserHandle secondUserHandle = mock(UserHandle.class);
+ Context context = mock(Context.class);
+ UserManager um = mock(UserManager.class);
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ luh.add(userHandle);
+ luh.add(secondUserHandle);
+ String compName = "com.nfc/.NfcClass";
+ ComponentName service = ComponentName.unflattenFromString(compName);
+ PackageManager pm = mock(PackageManager.class);
+ ApduServiceInfo apduService = mock(ApduServiceInfo.class);
+ services.add(apduService);
+ ApplicationInfo ai = mock(ApplicationInfo.class);
+ ai.flags = 1;
+ when(UserHandle.of(userId)).thenReturn(userHandle);
+ when(mContext.createContextAsUser(userHandle, 0)).thenReturn(context);
+ when(context.getSystemService(UserManager.class)).thenReturn(um);
+ when(um.getEnabledProfiles()).thenReturn(luh);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+ when(secondUserHandle.getIdentifier()).thenReturn(userId);
+ when(context.getContentResolver()).thenReturn(contentResolver);
+ when(Settings.Secure.getString(contentResolver,
+ Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT)).thenReturn(
+ "");
+ when(mContext.createPackageContextAsUser("android", 0, userHandle)).thenReturn(context);
+ when(context.getPackageManager()).thenReturn(pm);
+ when(apduService.hasCategory(CardEmulation.CATEGORY_PAYMENT)).thenReturn(true);
+ when(apduService.getComponent()).thenReturn(service);
+ when(pm.getApplicationInfo("com.nfc", 0)).thenReturn(ai);
+ when(mRegisteredServicesCache.hasService(userId, service)).thenReturn(true);
+
+ mCardEmulationManager.verifyDefaults(userId, services, validateInstalled);
+ verify(um).getEnabledProfiles();
+ verify(mContext).createPackageContextAsUser("android", 0, userHandle);
+ verify(pm, times(1)).getApplicationInfo("com.nfc", 0);
+ }
+
+ @Test
+ public void testVerifyDefaultsWithNoPaymentService()
+ throws PackageManager.NameNotFoundException {
+ int userId = 1;
+ List<ApduServiceInfo> services = new ArrayList<>();
+ List<UserHandle> luh = new ArrayList<>();
+ boolean validateInstalled = true;
+ UserHandle userHandle = mock(UserHandle.class);
+ UserHandle secondUserHandle = mock(UserHandle.class);
+ Context context = mock(Context.class);
+ UserManager um = mock(UserManager.class);
+ ContentResolver contentResolver = mock(ContentResolver.class);
+ luh.add(userHandle);
+ luh.add(secondUserHandle);
+ String compName = "com.nfc/.NfcClass";
+ ComponentName service = ComponentName.unflattenFromString(compName);
+ PackageManager pm = mock(PackageManager.class);
+ ApplicationInfo ai = mock(ApplicationInfo.class);
+ ai.flags = 1;
+ when(UserHandle.of(userId)).thenReturn(userHandle);
+ when(mContext.createContextAsUser(userHandle, 0)).thenReturn(context);
+ when(context.getSystemService(UserManager.class)).thenReturn(um);
+ when(um.getEnabledProfiles()).thenReturn(luh);
+ when(userHandle.getIdentifier()).thenReturn(userId);
+ when(secondUserHandle.getIdentifier()).thenReturn(userId);
+ when(context.getContentResolver()).thenReturn(contentResolver);
+ when(Settings.Secure.getString(contentResolver,
+ Constants.SETTINGS_SECURE_NFC_PAYMENT_DEFAULT_COMPONENT)).thenReturn(
+ "");
+ when(mContext.createPackageContextAsUser("android", 0, userHandle)).thenReturn(context);
+ when(context.getPackageManager()).thenReturn(pm);
+ when(mRegisteredServicesCache.hasService(userId, service)).thenReturn(true);
+
+ mCardEmulationManager.verifyDefaults(userId, services, validateInstalled);
+ verify(um).getEnabledProfiles();
+ 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);
- verify(mNfcService, never()).setFirmwareExitFrameTable(any(), anyInt());
+ mCardEmulationManager.onObserveModeDisabledInFirmware(exitFrame);
+
+ verify(mHostEmulationManager).onObserveModeDisabledInFirmware(exitFrame);
+ verify(mStatsdUtils).logAutoTransactReported(StatsdUtils.PROCESSOR_NFCC,
+ exitFrame.getData());
}
-
- @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());
- }
- }
+}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/HostEmulationManagerTest.java b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/HostEmulationManagerTest.java
index 795e59b..5612d77 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/HostEmulationManagerTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/HostEmulationManagerTest.java
@@ -116,7 +116,7 @@
@Mock private NfcService mNfcService;
@Mock private NfcInjector mNfcInjector;
@Mock private NfcEventLog mNfcEventLog;
- @Mock private StatsdUtils mStatsUtils;
+ @Mock private StatsdUtils mStatsdUtils;
@Mock private DeviceConfigFacade mDeviceConfigFacade;
@Captor private ArgumentCaptor<Intent> mIntentArgumentCaptor;
@Captor private ArgumentCaptor<ServiceConnection> mServiceConnectionArgumentCaptor;
@@ -159,7 +159,7 @@
when(mDeviceConfigFacade.getSlowTapThresholdMillis()).thenReturn(5);
mHostEmulationManager =
new HostEmulationManager(
- mContext, mTestableLooper.getLooper(), mRegisteredAidCache, mStatsUtils,
+ mContext, mTestableLooper.getLooper(), mRegisteredAidCache, mStatsdUtils,
mNfcInjector);
}
@@ -327,6 +327,9 @@
assertTrue(mHostEmulationManager.mEnableObserveModeAfterTransaction);
assertTrue(frame1.getTriggeredAutoTransact());
assertEquals(HostEmulationManager.STATE_POLLING_LOOP, mHostEmulationManager.mState);
+ verify(mStatsdUtils).logAutoTransactReported(StatsdUtils.PROCESSOR_HOST, data.getBytes());
+ verify(mStatsdUtils).setNextObserveModeTriggerSource(
+ StatsdUtils.TRIGGER_SOURCE_AUTO_TRANSACT);
}
@Test
@@ -584,9 +587,9 @@
mHostEmulationManager.onHostEmulationData(mockAidData);
verify(apduServiceInfo, times(2)).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).logCardEmulationWrongSettingEvent();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).logCardEmulationWrongSettingEvent();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mNfcService).sendRequireUnlockIntent();
verify(mNfcService).sendData(eq(HostEmulationManager.AID_NOT_FOUND));
@@ -614,9 +617,9 @@
mHostEmulationManager.onHostEmulationData(mockAidData);
verify(apduServiceInfo, times(2)).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).logCardEmulationWrongSettingEvent();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).logCardEmulationWrongSettingEvent();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mNfcService).sendRequireUnlockIntent();
verify(mNfcService).sendData(eq(HostEmulationManager.AID_NOT_FOUND));
@@ -646,9 +649,9 @@
mHostEmulationManager.onHostEmulationData(mockAidData);
verify(apduServiceInfo).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).logCardEmulationWrongSettingEvent();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).logCardEmulationWrongSettingEvent();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mNfcService).sendData(eq(HostEmulationManager.AID_NOT_FOUND));
verify(mContext).getSystemService(eq(PowerManager.class));
@@ -677,9 +680,9 @@
mHostEmulationManager.onHostEmulationData(mockAidData);
verify(apduServiceInfo).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).logCardEmulationNoRoutingEvent();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).logCardEmulationNoRoutingEvent();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mNfcService).sendData(eq(HostEmulationManager.AID_NOT_FOUND));
verify(mContext).getSystemService(eq(PowerManager.class));
@@ -705,8 +708,8 @@
() -> {
NfcStatsLog.write(NfcStatsLog.NFC_AID_CONFLICT_OCCURRED, MOCK_AID);
});
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_OTHER));
- verify(mStatsUtils).logCardEmulationWrongSettingEvent();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_OTHER));
+ verify(mStatsdUtils).logCardEmulationWrongSettingEvent();
assertEquals(HostEmulationManager.STATE_W4_DEACTIVATE, mHostEmulationManager.getState());
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mContext).getSystemService(eq(PowerManager.class));
@@ -746,9 +749,9 @@
assertEquals(HostEmulationManager.STATE_XFER, mHostEmulationManager.getState());
verify(apduServiceInfo).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).notifyCardEmulationEventWaitingForResponse();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).notifyCardEmulationEventWaitingForResponse();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mContext).getSystemService(eq(PowerManager.class));
verify(mContext).getSystemService(eq(KeyguardManager.class));
@@ -790,9 +793,9 @@
assertEquals(HostEmulationManager.STATE_W4_SERVICE, mHostEmulationManager.getState());
assertEquals(mockAidData, mHostEmulationManager.mSelectApdu);
verify(apduServiceInfo, atLeastOnce()).getUid();
- verify(mStatsUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
- verify(mStatsUtils).setCardEmulationEventUid(eq(USER_ID));
- verify(mStatsUtils).notifyCardEmulationEventWaitingForResponse();
+ verify(mStatsdUtils).setCardEmulationEventCategory(eq(CardEmulation.CATEGORY_PAYMENT));
+ verify(mStatsdUtils).setCardEmulationEventUid(eq(USER_ID));
+ verify(mStatsdUtils).notifyCardEmulationEventWaitingForResponse();
verify(mRegisteredAidCache).resolveAid(eq(MOCK_AID));
verify(mContext).getSystemService(eq(PowerManager.class));
verify(mContext).getSystemService(eq(KeyguardManager.class));
@@ -998,7 +1001,7 @@
assertEquals(
mHostEmulationManager.getServiceConnection(),
mServiceConnectionArgumentCaptor.getValue());
- verify(mStatsUtils).logCardEmulationDeactivatedEvent();
+ verify(mStatsdUtils).logCardEmulationDeactivatedEvent();
mTestableLooper.moveTimeForward(5000);
mTestableLooper.processAllMessages();
@@ -1032,7 +1035,7 @@
verifyZeroInteractions(mMessenger);
verifyNoMoreInteractions(mMessenger);
verifyNoMoreInteractions(mContext);
- verify(mStatsUtils).logCardEmulationDeactivatedEvent();
+ verify(mStatsdUtils).logCardEmulationDeactivatedEvent();
}
@Test
@@ -1122,7 +1125,7 @@
assertEquals(WALLET_PAYMENT_SERVICE, mHostEmulationManager.mServiceName);
assertNotNull(mHostEmulationManager.mService);
assertTrue(mHostEmulationManager.mServiceBound);
- verify(mStatsUtils).notifyCardEmulationEventServiceBound();
+ verify(mStatsdUtils).notifyCardEmulationEventServiceBound();
assertEquals(HostEmulationManager.STATE_XFER, mHostEmulationManager.getState());
assertNull(mHostEmulationManager.mSelectApdu);
verify(service).transact(eq(1), any(), eq(null), eq(1));
diff --git a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/PreferredSubscriptionServiceTest.java b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/PreferredSubscriptionServiceTest.java
new file mode 100644
index 0000000..ff5bffc
--- /dev/null
+++ b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/PreferredSubscriptionServiceTest.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2025 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 com.android.nfc.cardemulation;
+
+import static com.android.nfc.cardemulation.PreferredSubscriptionService.PREF_PREFERRED_SUB_ID;
+import static com.android.nfc.cardemulation.PreferredSubscriptionService.PREF_SUBSCRIPTION;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.telephony.SubscriptionInfo;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.nfc.cardemulation.util.TelephonyUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PreferredSubscriptionServiceTest {
+ @Mock
+ private Context mContext;
+ @Mock
+ private PreferredSubscriptionService.Callback mCallback;
+ @Mock
+ private TelephonyUtils mTelephonyUtils;
+ @Mock
+ private SharedPreferences mSubscriptionPrefs;
+ @Mock
+ private SharedPreferences.Editor mEditor;
+ @Mock
+ private SubscriptionInfo mSubscriptionInfo;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private Resources mResources;
+ private MockitoSession mStaticMockSession;
+ private PreferredSubscriptionService mPreferredSubscriptionService;
+
+ @Before
+ public void setUp() {
+ mStaticMockSession =
+ ExtendedMockito.mockitoSession()
+ .mockStatic(TelephonyUtils.class).strictness(
+ Strictness.LENIENT).startMocking();
+ MockitoAnnotations.initMocks(this);
+ SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.hasSystemFeature(
+ PackageManager.FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC)).thenReturn(true);
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(anyInt())).thenReturn(true);
+ when(TelephonyUtils.getInstance(mContext)).thenReturn(mTelephonyUtils);
+ when(mContext.getSharedPreferences(PREF_SUBSCRIPTION, Context.MODE_PRIVATE)).thenReturn(
+ mSubscriptionPrefs);
+ when(mSubscriptionPrefs.getInt(PREF_PREFERRED_SUB_ID,
+ TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN)).thenReturn(
+ TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN);
+ when(mSubscriptionPrefs.edit()).thenReturn(mEditor);
+ when(mEditor.putInt(PREF_PREFERRED_SUB_ID, TelephonyUtils.SUBSCRIPTION_ID_UICC)).thenReturn(
+ editor);
+ when(editor.commit()).thenReturn(true);
+ mPreferredSubscriptionService = new PreferredSubscriptionService(mContext, mCallback);
+ }
+
+ @After
+ public void tearDown() {
+ mStaticMockSession.finishMocking();
+ }
+
+ @Test
+ public void testGetPreferredSubscriptionId() {
+ when(mSubscriptionPrefs.getInt(PREF_PREFERRED_SUB_ID,
+ TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN)).thenReturn(
+ TelephonyUtils.SUBSCRIPTION_ID_UICC);
+
+ assertEquals(TelephonyUtils.SUBSCRIPTION_ID_UICC,
+ mPreferredSubscriptionService.getPreferredSubscriptionId());
+ }
+
+ @Test
+ public void testSetPreferredSubscriptionId() throws IllegalAccessException,
+ NoSuchFieldException {
+ SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);
+ List<SubscriptionInfo> infos = new ArrayList<>();
+ Field fieldForegroundComp = PreferredSubscriptionService.class.getDeclaredField(
+ "mDefaultSubscriptionId");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mPreferredSubscriptionService,
+ TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN);
+ when(mSubscriptionInfo.isEmbedded()).thenReturn(false);
+ when(mSubscriptionInfo.areUiccApplicationsEnabled()).thenReturn(true);
+ infos.add(mSubscriptionInfo);
+ when(mSubscriptionPrefs.edit()).thenReturn(mEditor);
+ when(mEditor.putInt(PREF_PREFERRED_SUB_ID,
+ TelephonyUtils.SUBSCRIPTION_ID_UICC)).thenReturn(
+ editor);
+ when(editor.commit()).thenReturn(true);
+ when(mTelephonyUtils.getActiveSubscriptions()).thenReturn(infos);
+ when(mTelephonyUtils.isEuiccSubscription(
+ TelephonyUtils.SUBSCRIPTION_ID_UICC)).thenReturn(
+ false);
+
+ mPreferredSubscriptionService.setPreferredSubscriptionId(
+ TelephonyUtils.SUBSCRIPTION_ID_UICC, true);
+ verify(mTelephonyUtils).isEuiccSubscription(TelephonyUtils.SUBSCRIPTION_ID_UICC);
+ verify(editor).commit();
+ }
+
+ @Test
+ public void testOnActiveSubscriptionsUpdated()
+ throws NoSuchFieldException, IllegalAccessException {
+ List<SubscriptionInfo> infos = new ArrayList<>();
+ Field fieldForegroundComp = PreferredSubscriptionService.class.getDeclaredField(
+ "mDefaultSubscriptionId");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mPreferredSubscriptionService,
+ TelephonyUtils.SUBSCRIPTION_ID_UICC);
+ when(mSubscriptionInfo.isEmbedded()).thenReturn(false);
+ when(mSubscriptionInfo.areUiccApplicationsEnabled()).thenReturn(true);
+ infos.add(mSubscriptionInfo);
+ when(mTelephonyUtils.getActiveSubscriptions()).thenReturn(infos);
+ when(mTelephonyUtils.isEuiccSubscription(TelephonyUtils.SUBSCRIPTION_ID_UICC)).thenReturn(
+ false);
+
+ mPreferredSubscriptionService.onActiveSubscriptionsUpdated(infos);
+ verify(mTelephonyUtils).isEuiccSubscription(TelephonyUtils.SUBSCRIPTION_ID_UICC);
+ verify(mCallback).onPreferredSubscriptionChanged(TelephonyUtils.SUBSCRIPTION_ID_UICC,
+ false);
+ }
+
+ @Test
+ public void testInitialize() throws NoSuchFieldException, IllegalAccessException {
+ List<SubscriptionInfo> infos = new ArrayList<>();
+ Field fieldForegroundComp = PreferredSubscriptionService.class.getDeclaredField(
+ "mDefaultSubscriptionId");
+ fieldForegroundComp.setAccessible(true);
+ fieldForegroundComp.set(mPreferredSubscriptionService,
+ TelephonyUtils.SUBSCRIPTION_ID_UNKNOWN);
+ when(mSubscriptionInfo.isEmbedded()).thenReturn(false);
+ when(mSubscriptionInfo.areUiccApplicationsEnabled()).thenReturn(true);
+ infos.add(mSubscriptionInfo);
+ when(mTelephonyUtils.getActiveSubscriptions()).thenReturn(infos);
+ when(mTelephonyUtils.isEuiccSubscription(anyInt())).thenReturn(false);
+
+ mPreferredSubscriptionService.initialize();
+ verify(mTelephonyUtils).isEuiccSubscription(anyInt());
+ verify(mTelephonyUtils).registerSubscriptionChangedCallback(
+ any(TelephonyUtils.Callback.class));
+
+ }
+
+}
diff --git a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCacheTest.java b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCacheTest.java
index b9f6f1e..63e04aa 100644
--- a/NfcNci/tests/unit/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCacheTest.java
+++ b/NfcNci/tests/unit/src/com/android/nfc/cardemulation/RegisteredT3tIdentifiersCacheTest.java
@@ -38,11 +38,6 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.nfc.cardemulation.RegisteredT3tIdentifiersCache.T3tIdentifier;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -50,11 +45,15 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
@RunWith(AndroidJUnit4.class)
public class RegisteredT3tIdentifiersCacheTest {
@@ -155,7 +154,7 @@
cache = new RegisteredT3tIdentifiersCache(mContext, mRoutingManager);
cache.mNfcEnabled = false;
- cache.onSecureNfcToggled();
+ cache.onTriggerRoutingTableUpdate();
verify(mRoutingManager, never()).configureRouting(any());
}
@@ -166,7 +165,7 @@
cache.mNfcEnabled = true;
cache.mForegroundT3tIdentifiersCache.put(NFCID2, mNfcFServiceInfo);
- cache.onSecureNfcToggled();
+ cache.onTriggerRoutingTableUpdate();
verify(mRoutingManager, times(2)).configureRouting(identifiersCaptor.capture());
List<T3tIdentifier> firstList = identifiersCaptor.getAllValues().get(0);
@@ -331,4 +330,4 @@
list.add(mNfcFServiceInfo);
return list;
}
-}
\ No newline at end of file
+}
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/Android.bp b/NfcNci/testutils/Android.bp
index 089218c..3865297 100644
--- a/NfcNci/testutils/Android.bp
+++ b/NfcNci/testutils/Android.bp
@@ -23,6 +23,35 @@
],
}
+android_app {
+ name: "NfcEmulatorApduAppNonTest",
+ sdk_version: "test_current",
+ min_sdk_version: "35",
+ srcs: [
+ "src/com/android/nfc/emulatorapp/**/*.kt",
+ ],
+ assets: ["src/com/android/nfc/emulatorapp/parsed_files/**/*.txt"],
+ resource_dirs: ["src/com/android/nfc/emulatorapp/res"],
+ manifest: "src/com/android/nfc/emulatorapp/AndroidManifest.xml",
+ static_libs: [
+ "guava",
+ "androidx.appcompat_appcompat",
+ "kotlinx-coroutines-android",
+ "androidx.annotation_annotation",
+ "androidx.compose.ui_ui",
+ "com.google.android.material_material",
+ "kotlinx_serialization_core",
+ "kotlinx_serialization_json",
+ "nfc-multidevice-utils",
+ ],
+ visibility: [
+ "//cts:__subpackages__",
+ "//packages/modules/Nfc/NfcNci:__subpackages__",
+ "//packages/modules/Nfc:__subpackages__",
+ "//vendor:__subpackages__",
+ ],
+}
+
android_test {
name: "NfcEmulatorApduApp",
sdk_version: "test_current",
diff --git a/NfcNci/testutils/README.md b/NfcNci/testutils/README.md
index 78a84f0..a94d227 100644
--- a/NfcNci/testutils/README.md
+++ b/NfcNci/testutils/README.md
@@ -56,6 +56,47 @@
commands and responses received and sent by the Host APDU service displayed on
the emulator app.
+To use the emulator app outside of a generated test, perform the following steps:
+
+1\. To prepare a snoop log to be replayed with the app:
+
+```
+python3 nfcreplay.py -f $SNOOP_FILE --parse_only
+```
+
+The script will produce the name of the parsed log, which will be located within
+the folder emulatorapp/parsed_files. Save the name for Step 3.
+
+2\. Build and install the emulator app. The following commands are specific to
+the Pixel 6 Pro (Raven). Non-Raven devices should substitute "raven" for the
+appropriate value.
+
+```
+mma NfcEmulatorApduAppNonTest
+adb install -r -g ~/aosp-main-with-phones/out/target/product/raven/system/app/emulatorapp/NfcEmulatorApduAppNonTest.apk
+
+```
+
+3\. Start the activity. Make sure that $PARSED_SNOOP_FILE is the name of the
+file, rather than its path. It is assumed that this file is located within
+emulatorapp/parsed_files, where it was originally created.
+
+```
+adb shell am start -n com.android.nfc.emulatorapp/.MainActivity --es "snoop_file" "$PARSED_SNOOP_FILE"
+```
+
+When you are ready to start the transaction, press the "Start Host APDU Service"
+button.
+
+4\. To replay the transaction with the PN532 module, follow the steps above to
+generate and replay a test case, though you should make sure to append the flag
+`--replay_with_app` to the end of each command.
+
+When the transaction is replayed, you should be able to see a list of APDU
+commands and responses received and sent by the Host APDU service displayed on
+the emulator app. Additionally, the replay script will output similar
+information.
+
### Creating a Snoop Log
To create a snoop log from your Android device, you should first go to Developer
diff --git a/NfcNci/testutils/pn532/pn532.py b/NfcNci/testutils/pn532/pn532.py
index 6006ea9..c3fa37c 100644
--- a/NfcNci/testutils/pn532/pn532.py
+++ b/NfcNci/testutils/pn532/pn532.py
@@ -355,7 +355,11 @@
},
)
self.log.debug("Serial port: %s", path)
- self.device = serial.Serial(path, 115200, timeout=0.5)
+ try:
+ self.device = serial.Serial(path, 115200, timeout=0.5)
+ except Exception as e:
+ self.log.debug("Failed to connect to serial port %s", path)
+ return False
self.device.flush()
self._send_ack_frame()
diff --git a/NfcNci/testutils/src/com/android/nfc/emulator/AndroidManifest.xml b/NfcNci/testutils/src/com/android/nfc/emulator/AndroidManifest.xml
index 1e8bc3d..d36f846 100644
--- a/NfcNci/testutils/src/com/android/nfc/emulator/AndroidManifest.xml
+++ b/NfcNci/testutils/src/com/android/nfc/emulator/AndroidManifest.xml
@@ -127,6 +127,11 @@
android:label="Event Listener Activity"
android:exported="true">
</activity>
+ <activity
+ android:name=".ExitFrameEmulatorActivity"
+ android:label="Exit Frame Activity"
+ android:exported="true">
+ </activity>
<service android:name="com.android.nfc.service.PollingLoopService" android:exported="true"
android:permission="android.permission.BIND_NFC_SERVICE"
android:enabled="true">
diff --git a/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java b/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java
new file mode 100644
index 0000000..143cae2
--- /dev/null
+++ b/NfcNci/testutils/src/com/android/nfc/emulator/ExitFrameEmulatorActivity.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2025 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 com.android.nfc.emulator;
+
+import android.content.ComponentName;
+import android.nfc.cardemulation.CardEmulation;
+import android.nfc.cardemulation.PollingFrame;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.android.nfc.service.PaymentService1;
+
+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);
+ }
+
+ 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();
+ }
+
+ public void onResume() {
+ super.onResume();
+ mServiceName =
+ new ComponentName(this.getApplicationContext(), PaymentService1.class);
+ 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) {
+ verifyExitFrameAndPassTest();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ mCardEmulation.unregisterNfcEventCallback(mEventListener);
+ }
+
+ @Override
+ 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 4db71ee..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;
@@ -412,6 +413,23 @@
mActivity = (EventListenerEmulatorActivity) instrumentation.startActivitySync(intent);
}
+ @Rpc(description = "Opens the Exit Frame Activity")
+ public void startExitFrameActivity(String intendedExitFrame, String[] plpfs,
+ boolean waitForTransaction) {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ 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);
+ }
+
/** Registers receiver that waits for RF field broadcast */
@AsyncRpc(description = "Waits for RF field detected broadcast")
public void asyncWaitForRfOnBroadcast(String callbackId, String eventName) {
@@ -546,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/NfcNci/testutils/src/com/android/nfc/emulatorapp/MainActivity.kt b/NfcNci/testutils/src/com/android/nfc/emulatorapp/MainActivity.kt
index fc20c60..107b3cd 100644
--- a/NfcNci/testutils/src/com/android/nfc/emulatorapp/MainActivity.kt
+++ b/NfcNci/testutils/src/com/android/nfc/emulatorapp/MainActivity.kt
@@ -48,11 +48,23 @@
viewModel.uiState.observe(this, observer)
EmulatorHostApduService.viewModel = viewModel
+ findViewById<MaterialButton>(R.id.service_button).setOnClickListener {
+ startHostApduService()
+ findViewById<MaterialButton>(R.id.service_button).isEnabled = false
+ }
+
val snoopData = intent.getStringExtra(SNOOP_DATA_FLAG)
- if (snoopData != null) {
+ if (snoopData != null && snoopData.length > 0) {
val apdus = parseJsonString(snoopData)
updateService(apdus)
}
+
+ val snoopFile = intent.getStringExtra(SNOOP_FILE_FLAG)
+ if (snoopFile != null && snoopFile.length > 0) {
+ val apdus = openAndParseFile(PARSED_FILES_DIR + snoopFile)
+ updateService(apdus)
+ viewModel.setSnoopFile(snoopFile)
+ }
startHostApduService()
}
@@ -64,6 +76,30 @@
)
}
+ /* Opens the snoop file and extracts all APDU commands and responses. */
+ private fun openAndParseFile(file: String): List<ApduPair> {
+ val apduPairs = mutableListOf<ApduPair>()
+ val text = BufferedReader(InputStreamReader(getAssets().open(file))).use { it.readText() }
+ val lines = text.split("\n").toTypedArray()
+ for (line in lines) {
+ val arr = line.split(";").toTypedArray()
+ if (arr.size != 2) { // Should contain commands, followed by responses
+ continue
+ }
+ val commands = arr[0].split(",").toTypedArray()
+ val responses = arr[1].split(",").toTypedArray()
+ if (commands.size != responses.size) {
+ continue
+ }
+ for (i in commands.indices) {
+ val command = standardize(commands[i])
+ val response = standardize(responses[i])
+ apduPairs.add(ApduPair(command, response))
+ }
+ }
+ return apduPairs
+ }
+
/** Extracts all APDU commands and responses from JSON string. */
private fun parseJsonString(text: String): List<ApduPair> {
val apduPairs = mutableListOf<ApduPair>()
@@ -106,6 +142,7 @@
companion object {
private const val TAG = "EmulatorHostApduServiceLog"
const val SNOOP_DATA_FLAG = "snoop_data"
+ const val SNOOP_FILE_FLAG = "snoop_file"
private const val PARSED_FILES_DIR = "src/com/android/nfc/emulatorapp/parsed_files/"
}
}
\ No newline at end of file
diff --git a/framework/api/current.txt b/framework/api/current.txt
index f69d436..ef327ae 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -77,6 +77,7 @@
method public boolean isEnabled();
method public boolean isObserveModeEnabled();
method public boolean isObserveModeSupported();
+ method @FlaggedApi("com.android.nfc.module.flags.reader_mode_annotations") public boolean isReaderModeAnnotationSupported();
method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
method public boolean isSecureNfcEnabled();
diff --git a/framework/java/android/nfc/INfcAdapter.aidl b/framework/java/android/nfc/INfcAdapter.aidl
index ac0a5aa..43d601f 100644
--- a/framework/java/android/nfc/INfcAdapter.aidl
+++ b/framework/java/android/nfc/INfcAdapter.aidl
@@ -91,6 +91,7 @@
boolean isReaderOptionSupported();
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
boolean enableReaderOption(boolean enable, in String pkg);
+ boolean isReaderModeAnnotationSupported();
boolean isObserveModeSupported();
boolean isObserveModeEnabled();
boolean setObserveMode(boolean enabled, String pkg);
diff --git a/framework/java/android/nfc/INfcEventCallback.aidl b/framework/java/android/nfc/INfcEventCallback.aidl
index af1fa2f..17b0d58 100644
--- a/framework/java/android/nfc/INfcEventCallback.aidl
+++ b/framework/java/android/nfc/INfcEventCallback.aidl
@@ -1,6 +1,7 @@
package android.nfc;
import android.nfc.ComponentNameAndUser;
+import android.nfc.cardemulation.PollingFrame;
/**
* @hide
@@ -8,6 +9,7 @@
oneway interface INfcEventCallback {
void onPreferredServiceChanged(in ComponentNameAndUser ComponentNameAndUser);
void onObserveModeStateChanged(boolean isEnabled);
+ void onObserveModeDisabledInFirmware(in PollingFrame exitFrame);
void onAidConflictOccurred(in String aid);
void onAidNotRouted(in String aid);
void onNfcStateChanged(in int nfcState);
diff --git a/framework/java/android/nfc/NfcAdapter.java b/framework/java/android/nfc/NfcAdapter.java
index f330437..c8e19cf 100644
--- a/framework/java/android/nfc/NfcAdapter.java
+++ b/framework/java/android/nfc/NfcAdapter.java
@@ -52,7 +52,6 @@
import android.os.UserHandle;
import android.util.Log;
-import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -624,7 +623,6 @@
final Object mLock;
final NfcOemExtension mNfcOemExtension;
- ITagRemovedCallback mTagRemovedListener; // protected by mLock
/**
* A callback to be invoked when the system finds a tag while the foreground activity is
@@ -942,7 +940,6 @@
mContext = context;
mNfcActivityManager = new NfcActivityManager(this);
mNfcUnlockHandlers = new HashMap<NfcUnlockHandler, INfcUnlockHandler>();
- mTagRemovedListener = null;
mLock = new Object();
mControllerAlwaysOnListener = new NfcControllerAlwaysOnListener();
mNfcWlcStateListener = new NfcWlcStateListener(getService());
@@ -1195,6 +1192,21 @@
callService(() -> sService.pausePolling(timeoutInMs));
}
+ /**
+ * Returns whether the device supports setting annotation frames when enabling reader
+ * mode by passing an extras bundle that includes a
+ * {@link #EXTRA_READER_TECH_A_POLLING_LOOP_ANNOTATION} key to
+ * {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. These annotations frames
+ * will be reported as unknown frames via
+ * {@link android.nfc.cardemulation.HostApduService#processPollingFrames(List)} on another
+ * Android device that has set enabled observe mode by passing true to
+ * {@link #setObserveModeEnabled(boolean)} .
+ * @return true if the mode is supported, false otherwise.
+ */
+ @FlaggedApi(com.android.nfc.module.flags.Flags.FLAG_READER_MODE_ANNOTATIONS)
+ public boolean isReaderModeAnnotationSupported() {
+ return callServiceReturn(() -> sService.isReaderModeAnnotationSupported(), false);
+ }
/**
* Returns whether the device supports observe mode or not. When observe mode is enabled, the
@@ -2202,15 +2214,9 @@
} else {
tagRemovedListener.onTagRemoved();
}
- synchronized (mLock) {
- mTagRemovedListener = null;
- }
}
};
}
- synchronized (mLock) {
- mTagRemovedListener = iListener;
- }
final ITagRemovedCallback.Stub passedListener = iListener;
return callServiceReturn(() ->
sService.ignore(tag.getServiceHandle(), debounceMs, passedListener), false);
diff --git a/framework/java/android/nfc/cardemulation/CardEmulation.java b/framework/java/android/nfc/cardemulation/CardEmulation.java
index daecb35..c68c262 100644
--- a/framework/java/android/nfc/cardemulation/CardEmulation.java
+++ b/framework/java/android/nfc/cardemulation/CardEmulation.java
@@ -27,6 +27,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -1350,6 +1351,16 @@
default void onObserveModeStateChanged(boolean isEnabled) {}
/**
+ * This method is called when observe mode has been disabled in the firmware.
+ *
+ * @param exitFrame The polling frame that caused the firmware to exit observe mode. Null
+ * when we were unable to parse the exit frame from the NFCC.
+ * @hide
+ */
+ @FlaggedApi(android.nfc.Flags.FLAG_NFC_EVENT_LISTENER)
+ default void onObserveModeDisabledInFirmware(@Nullable PollingFrame exitFrame) {}
+
+ /**
* This method is called when an AID conflict is detected during an NFC transaction. This
* can happen when multiple services are registered for the same AID. If your service is
* registered for this AID you may want to instruct users to bring your app to the
@@ -1429,6 +1440,13 @@
callListeners(listener -> listener.onObserveModeStateChanged(isEnabled));
}
+ public void onObserveModeDisabledInFirmware(PollingFrame exitFrame) {
+ if (!android.nfc.Flags.nfcEventListener()) {
+ return;
+ }
+ callListeners(listener -> listener.onObserveModeDisabledInFirmware(exitFrame));
+ }
+
public void onAidConflictOccurred(String aid) {
if (!android.nfc.Flags.nfcEventListener()) {
return;
diff --git a/libnfc-nci/src/adaptation/NfcAdaptation.cc b/libnfc-nci/src/adaptation/NfcAdaptation.cc
index 5beb02a..2cb10dc 100644
--- a/libnfc-nci/src/adaptation/NfcAdaptation.cc
+++ b/libnfc-nci/src/adaptation/NfcAdaptation.cc
@@ -711,6 +711,7 @@
}
AIBinder_unlinkToDeath(mAidlHal->asBinder().get(), mDeathRecipient.get(),
nullptr);
+ mAidlHal = nullptr;
} else if (mHal != nullptr) {
if (sVndExtnsPresent) {
sNfcVendorExtn->finalize();
@@ -1004,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) {
@@ -1055,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();
@@ -1139,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) {
@@ -1158,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/adaptation/nfc_config.cc b/libnfc-nci/src/adaptation/nfc_config.cc
index 46c2409..ce4f0a9 100644
--- a/libnfc-nci/src/adaptation/nfc_config.cc
+++ b/libnfc-nci/src/adaptation/nfc_config.cc
@@ -22,6 +22,8 @@
#include <android-base/strings.h>
#include <config.h>
+#include <mutex>
+
#include "NfcAdaptation.h"
using namespace ::std;
@@ -29,6 +31,8 @@
#define PATH_NCI_UPDATE_CONF "/data/vendor/nfc/libnfc-nci-update.conf"
+static std::mutex config_mutex;
+
namespace {
std::string searchConfigPath(std::string file_name) {
const std::vector<std::string> search_path = {
@@ -87,9 +91,8 @@
}
}
-NfcConfig::NfcConfig() { loadConfig(); }
-
NfcConfig& NfcConfig::getInstance() {
+ std::lock_guard<std::mutex> lock(config_mutex);
static NfcConfig theInstance;
if (theInstance.config_.isEmpty()) {
theInstance.loadConfig();
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/include/nci_defs.h b/libnfc-nci/src/include/nci_defs.h
index 084ce1a..736494a 100644
--- a/libnfc-nci/src/include/nci_defs.h
+++ b/libnfc-nci/src/include/nci_defs.h
@@ -230,19 +230,13 @@
**********************************************/
#define NCI_MSG_PROP_ANDROID 0x0C
-#define NCI_ANDROID_SIGNAL_STRENGTH_NTF 0x01
-#define NCI_ANDROID_FIELD_CHANGE_NTF 0x02
-#define NCI_ANDROID_POLLING_FRAME_NTF 0x03
-#define NCI_ANDROID_GET_PASSIVE_OBSERVER_EXIT_FRAME_NTF 0x04
-#define NCI_ANDROID_PASSIVE_OBSERVER_SUSPENDED_NTF 0x05
-#define NCI_ANDROID_PASSIVE_OBSERVER_RESUMED_NTF 0x06
#define NCI_ANDROID_RESTART_RF_DISCOVERY_REQUEST_NTF 0x07
/* Android Opcodes */
#define NCI_ANDROID_GET_CAPS 0x0
#define NCI_ANDROID_POWER_SAVING 0x1
#define NCI_ANDROID_PASSIVE_OBSERVE 0x2
-#define NCI_ANDROID_POLLING_FRAME 0x3
+#define NCI_ANDROID_POLLING_FRAME_NTF 0x03
#define NCI_QUERY_ANDROID_PASSIVE_OBSERVE 0x4
#define NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH 0x05
#define NCI_ANDROID_SET_PASSIVE_OBSERVER_EXIT_FRAME 0x06
@@ -250,6 +244,8 @@
#define NCI_ANDROID_BLANK_NCI 0x8
#define NCI_ANDROID_SET_TECH_A_POLLING_LOOP_ANNOTATION 0x9
#define NCI_QUERY_ANDROID_POWER_SAVING 0x0A
+#define NCI_ANDROID_PASSIVE_OBSERVER_SUSPENDED_NTF 0x0B
+#define NCI_ANDROID_PASSIVE_OBSERVER_RESUMED_NTF 0x0C
/* Android Get Proprietary Caps */
#define NCI_ANDROID_GET_CAPS_PARAM_SIZE 0x1
diff --git a/libnfc-nci/src/include/nfc_config.h b/libnfc-nci/src/include/nfc_config.h
index 906d0c2..f478179 100644
--- a/libnfc-nci/src/include/nfc_config.h
+++ b/libnfc-nci/src/include/nfc_config.h
@@ -87,7 +87,7 @@
private:
void loadConfig();
static NfcConfig& getInstance();
- NfcConfig();
+ NfcConfig() {};
ConfigFile config_;
};
diff --git a/libnfc-nci/src/nfa/dm/nfa_dm_act.cc b/libnfc-nci/src/nfa/dm/nfa_dm_act.cc
index 0604492..95769ea 100644
--- a/libnfc-nci/src/nfa/dm/nfa_dm_act.cc
+++ b/libnfc-nci/src/nfa/dm/nfa_dm_act.cc
@@ -29,6 +29,7 @@
#include "nci_hmsgs.h"
#include "nfa_api.h"
#include "nfa_ce_int.h"
+#include "nfa_hci_int.h"
#include "nfa_rw_api.h"
#include "nfa_rw_int.h"
#include "nfa_wlc_int.h"
@@ -1135,7 +1136,8 @@
LOG(VERBOSE) << __func__;
- if (nfa_dm_cb.disc_cb.disc_flags & NFA_DM_DISC_FLAGS_ENABLED) {
+ if ((nfa_dm_cb.disc_cb.disc_flags & NFA_DM_DISC_FLAGS_ENABLED) ||
+ (nfa_hci_cb.hci_state == NFA_HCI_STATE_EE_RECOVERY)) {
evt_data.status = NFA_STATUS_OK;
nfa_dm_conn_cback_event_notify(NFA_RF_DISCOVERY_STARTED_EVT, &evt_data);
} else if (nfa_dm_cb.disc_cb.disc_state != NFA_DM_RFST_IDLE) {
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/nfc/nfc_ncif.cc b/libnfc-nci/src/nfc/nfc/nfc_ncif.cc
index a1595ca..47be304 100644
--- a/libnfc-nci/src/nfc/nfc/nfc_ncif.cc
+++ b/libnfc-nci/src/nfc/nfc/nfc_ncif.cc
@@ -1775,7 +1775,10 @@
data_cevt.p_data = p_evt;
/* adjust payload, if needed */
- if (p_cb->conn_id == NFC_RF_CONN_ID && p_evt->len) {
+ // On RF raw fragmented frames, data status is present
+ // only on last fragment
+ if ((p_cb->conn_id == NFC_RF_CONN_ID) &&
+ (p_evt->layer_specific & NFC_RAS_FRAGMENTED) && p_evt->len) {
/* if NCI_PROTOCOL_T1T/NCI_PROTOCOL_T2T/NCI_PROTOCOL_T3T, the status
* byte needs to be removed
*/
diff --git a/libnfc-nci/src/nfc/tags/ce_t4t.cc b/libnfc-nci/src/nfc/tags/ce_t4t.cc
index 4e9c135..42a9742 100644
--- a/libnfc-nci/src/nfc/tags/ce_t4t.cc
+++ b/libnfc-nci/src/nfc/tags/ce_t4t.cc
@@ -567,8 +567,6 @@
LOG(VERBOSE) << StringPrintf("%s: conn_id = 0x%02X", __func__, conn_id);
- p_cmd = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
-
if (p_c_apdu->len == 0) {
LOG(ERROR) << StringPrintf("%s: Wrong length in ce_t4t_data_cback",
__func__);
@@ -577,7 +575,7 @@
GKI_freebuf(p_c_apdu);
return;
}
-
+ p_cmd = (uint8_t*)(p_c_apdu + 1) + p_c_apdu->offset;
/* Class Byte */
BE_STREAM_TO_UINT8(cla, p_cmd);
diff --git a/libnfc-nci/src/nfc/tags/rw_i93.cc b/libnfc-nci/src/nfc/tags/rw_i93.cc
index 06e5d20..ee482fc 100644
--- a/libnfc-nci/src/nfc/tags/rw_i93.cc
+++ b/libnfc-nci/src/nfc/tags/rw_i93.cc
@@ -3417,7 +3417,7 @@
*******************************************************************************/
tNFC_STATUS rw_i93_select(uint8_t* p_uid) {
tRW_I93_CB* p_i93 = &rw_cb.tcb.i93;
- uint8_t uid[I93_UID_BYTE_LEN], *p;
+ uint8_t uid[I93_UID_BYTE_LEN] = {0}, *p;
LOG(VERBOSE) << __func__;
diff --git a/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc b/libnfc-nci/src/nfc_vendor_extn/NfcVendorExtn.cc
index e7fe62a..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(
@@ -120,7 +161,12 @@
LOG(VERBOSE) << StringPrintf("%s:", __func__);
mVendorExtnCb.hidlHal = hidlHal;
mVendorExtnCb.aidlHal = aidlHal;
- return NfcExtn_LibSetup();
+ if (!NfcExtn_LibSetup()) {
+ mVendorExtnCb.hidlHal = nullptr;
+ mVendorExtnCb.aidlHal = nullptr;
+ return false;
+ }
+ return true;
}
void NfcVendorExtn::setNciCallback(tHAL_NFC_CBACK* pHalCback,
@@ -204,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;
}
@@ -213,5 +259,7 @@
bool NfcVendorExtn::finalize(void) {
LOG(VERBOSE) << __func__;
phNfcExtn_LibClose();
+ mVendorExtnCb.hidlHal = nullptr;
+ mVendorExtnCb.aidlHal = nullptr;
return true;
}
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 {
diff --git a/libnfc-nci/tools/casimir/src/controller.rs b/libnfc-nci/tools/casimir/src/controller.rs
index b14e14d..a23bb02 100644
--- a/libnfc-nci/tools/casimir/src/controller.rs
+++ b/libnfc-nci/tools/casimir/src/controller.rs
@@ -1744,7 +1744,16 @@
self.state.last_observe_mode_state = Some(self.state.passive_observe_mode);
self.state.passive_observe_mode = nci::PassiveObserveMode::Disable.into();
self.state.exit_frame_start_time = Some(Instant::now());
- // TODO(johnrjohn) send NCI_ANDROID_PASSIVE_OBSERVER_SUSPENDED_NTF
+
+ self.send_control(nci::PassiveObserverSuspendedNotificationBuilder {
+ exit_frame_type: match technology {
+ rf::Technology::NfcA => 0x00,
+ rf::Technology::NfcB => 0x01,
+ _ => panic!(),
+ },
+ payload: Some(data.clone().into()),
+ })
+ .await?;
}
self.send_control(nci::AndroidPollingLoopNotificationBuilder {
@@ -2286,7 +2295,7 @@
self.state.passive_observe_mode =
self.state.last_observe_mode_state.unwrap_or(nci::TechnologyMask::AllOn.into());
info!("Turning observe mode back on, exit frame timeout has passed.");
- // TODO(johnrjohn) send NCI_ANDROID_PASSIVE_OBSERVER_RESUMED_NTF
+ self.send_control(nci::PassiveObserverResumedNotificationBuilder {}).await?;
}
}
diff --git a/libnfc-nci/tools/casimir/src/nci_packets.pdl b/libnfc-nci/tools/casimir/src/nci_packets.pdl
index ec90b89..cd1269b 100644
--- a/libnfc-nci/tools/casimir/src/nci_packets.pdl
+++ b/libnfc-nci/tools/casimir/src/nci_packets.pdl
@@ -84,7 +84,9 @@
BLANK_NCI = 0x8,
SET_TECH_A_POLLING_LOOP_ANNOTATION = 0x09,
QUERY_POWER_SAVING_MODE = 0x0A,
-}
+ ANDROID_PASSIVE_OBSERVER_SUSPENDED = 0xB,
+ ANDROID_PASSIVE_OBSERVER_RESUMED = 0xC,
+ }
enum Status : 8 {
OK = 0x00,
@@ -954,6 +956,7 @@
}
packet AndroidSetPassiveObserverExitFrameCommand : AndroidPacket(mt = COMMAND, android_sub_oid = SET_PASSIVE_OBSERVER_EXIT_FRAME) {
+ more: 8,
timeout: 16,
_count_(exit_frames): 8,
exit_frames: ExitFrameEntry[]
@@ -962,3 +965,11 @@
packet AndroidSetPassiveObserverExitFrameResponse : AndroidPacket(mt = RESPONSE, android_sub_oid = SET_PASSIVE_OBSERVER_EXIT_FRAME) {
status: Status,
}
+
+packet PassiveObserverSuspendedNotification : AndroidPacket(mt = NOTIFICATION, android_sub_oid = ANDROID_PASSIVE_OBSERVER_SUSPENDED) {
+ exit_frame_type: 8,
+ _size_(_payload_): 8,
+ _payload_
+}
+
+packet PassiveObserverResumedNotification : AndroidPacket(mt = NOTIFICATION, android_sub_oid = ANDROID_PASSIVE_OBSERVER_RESUMED) {}
\ No newline at end of file
diff --git a/tests/cts/hostsidetests/multidevices/AndroidTest.xml b/tests/cts/hostsidetests/multidevices/AndroidTest.xml
index 8b9f799..5621803 100644
--- a/tests/cts/hostsidetests/multidevices/AndroidTest.xml
+++ b/tests/cts/hostsidetests/multidevices/AndroidTest.xml
@@ -22,6 +22,9 @@
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
<device name="AndroidDevice">
+ <target_preparer class="AndroidDeviceFeaturesCheckDecorator">
+ <option name="required_feature" value="android.hardware.nfc.hce" />
+ </target_preparer>
<target_preparer class="AndroidMinSdkVersionCheckDecorator">
<option name="min_sdk_version" value="35" />
</target_preparer>
diff --git a/tests/cts/hostsidetests/multidevices/cts_nfc_hce_multi_device_test.py b/tests/cts/hostsidetests/multidevices/cts_nfc_hce_multi_device_test.py
index db82993..2f32090 100644
--- a/tests/cts/hostsidetests/multidevices/cts_nfc_hce_multi_device_test.py
+++ b/tests/cts/hostsidetests/multidevices/cts_nfc_hce_multi_device_test.py
@@ -36,6 +36,7 @@
import logging
import ssl
import sys
+import time
from android.platform.test.annotations import CddTest
from android.platform.test.annotations import ApiTest
@@ -154,14 +155,12 @@
start_emulator_fun(*args)
else:
if preferred_service is None:
- self.emulator.nfc_emulator.startSimpleEmulatorActivity(service_list,
- expected_service, is_payment,
- should_disable_services_on_destroy)
+ self.emulator.nfc_emulator.startSimpleEmulatorActivity(
+ service_list, expected_service, is_payment,
+ should_disable_services_on_destroy)
else:
self.emulator.nfc_emulator.startSimpleEmulatorActivityWithPreferredService(
- service_list, expected_service, preferred_service, is_payment,
- should_disable_services_on_destroy
- )
+ service_list, expected_service, preferred_service, is_payment)
if is_payment:
role_held_handler.waitAndGet('RoleHeld', _NFC_TIMEOUT_SEC)
@@ -236,10 +235,6 @@
)
self.emulator.adb.shell(['svc', 'nfc', 'enable'])
self.emulator.debug_tag = 'emulator'
- if not self.emulator.nfc_emulator.isNfcHceSupported():
- self._setup_failure_reason = f'NFC HCE is not supported on {self.emulator}'
- self._setup_failure_should_block_tests = False
- return
if (
hasattr(self.emulator, 'dimensions')
@@ -1201,6 +1196,7 @@
_LOG.debug(f"Polling frame gain results {results_for_power_level}")
+ issues = []
for power_level in power_levels:
# No value to compare to
if power_level == 0:
@@ -1209,16 +1205,27 @@
for type_ in polling_frame_types:
previous_gain = results_for_power_level[power_level - 1][type_]
current_gain = results_for_power_level[power_level][type_]
- asserts.assert_greater_equal(
- current_gain, previous_gain,
- _FAILED_VENDOR_GAIN_VALUE_DROPPED_ON_POWER_INCREASE,
- {
- "type": type_,
- "power_level": power_level * 20,
- "previous_gain": previous_gain,
- "current_gain": current_gain,
- }
+ if current_gain >= previous_gain:
+ continue
+ sample = {
+ "type": type_,
+ "power_level": power_level * 20,
+ "previous_gain": previous_gain,
+ "current_gain": current_gain,
+ }
+ _LOG.warning(
+ f"Reported gain level dropped" + \
+ f" between power steps {sample}"
)
+ issues.append(sample)
+
+ # Allow up to 2 reported gain decreases out of (5 * 3) = 15 test samples
+ # Theoretically, this could happen
+ # due to automatic power/gain/load management feature of chipsets
+ asserts.assert_true(
+ len(issues) <= 2,
+ _FAILED_VENDOR_GAIN_VALUE_DROPPED_ON_POWER_INCREASE,
+ )
@CddTest(requirements = ["7.4.4/C-1-13"])
def test_polling_frame_type(self):
@@ -1336,13 +1343,15 @@
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 hasattr(self, 'pn532'):
+ self.pn532.reset_buffers()
+ self.pn532.mute()
+ if hasattr(self, 'emulator'):
+ 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)
#@CddTest(requirements = {"7.4.4/C-2-2", "7.4.4/C-1-2"})
def test_single_non_payment_service_with_listen_tech_disabled(self):
diff --git a/tests/cts/tests/src/android/nfc/cts/CardEmulationTest.java b/tests/cts/tests/src/android/nfc/cts/CardEmulationTest.java
index 12fdd5d..8c6d853 100644
--- a/tests/cts/tests/src/android/nfc/cts/CardEmulationTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/CardEmulationTest.java
@@ -1,5 +1,7 @@
package android.nfc.cts;
+import static android.nfc.cts.NfcUtils.assumeObserveModeSupported;
+import static android.nfc.cts.NfcUtils.assumeVsrApiGreaterThanUdc;
import static android.nfc.cts.WalletRoleTestUtils.CTS_PACKAGE_NAME;
import static android.nfc.cts.WalletRoleTestUtils.WALLET_HOLDER_PACKAGE_NAME;
import static android.nfc.cts.WalletRoleTestUtils.WALLET_HOLDER_SERVICE_DESC;
@@ -7,14 +9,22 @@
import static android.nfc.cts.WalletRoleTestUtils.runWithRole;
import static android.nfc.cts.WalletRoleTestUtils.runWithRoleNone;
-import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
@@ -33,7 +43,6 @@
import android.nfc.cardemulation.CardEmulation;
import android.nfc.cardemulation.PollingFrame;
import android.nfc.cardemulation.PollingFrame.PollingFrameType;
-import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -46,6 +55,7 @@
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import android.testing.PollingCheck;
+import android.util.Log;
import android.view.KeyEvent;
import androidx.test.InstrumentationRegistry;
@@ -101,33 +111,36 @@
}
@Before
- public void setUp() throws NoSuchFieldException, RemoteException {
+ public void setUp() throws NoSuchFieldException, RemoteException, InterruptedException {
assumeTrue("Device must support NFC HCE", supportsHardware());
mContext = InstrumentationRegistry.getContext();
mAdapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertNotNull("NFC Adapter is null", mAdapter);
- Assert.assertTrue("NFC Adapter could not be enabled",
- NfcUtils.enableNfc(mAdapter, mContext));
+ assertNotNull("NFC Adapter is null", mAdapter);
+ assertTrue("NFC Adapter could not be enabled", NfcUtils.enableNfc(mAdapter, mContext));
}
@After
public void tearDown() throws Exception {
+ if (mAdapter != null && mContext != null) {
+ Assert.assertTrue("Failed to enable NFC in test cleanup",
+ NfcUtils.enableNfc(mAdapter, mContext));
+ } else {
+ Log.w("CardEmulationTest", "mAdapter or mContext is null");
+ }
sCurrentPollLoopReceiver = null;
}
@Test
public void getNonNullInstance() {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
- Assert.assertNotNull("CardEmulation instance is null", instance);
+ assertNotNull("CardEmulation instance is null", instance);
}
@Test
public void testCategoryAllowsForegroundPreference() {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
- Assert.assertTrue(
- instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_PAYMENT));
- Assert.assertTrue(
- instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_OTHER));
+ assertTrue(instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_PAYMENT));
+ assertTrue(instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_OTHER));
}
@Test
@@ -139,14 +152,14 @@
int result = instance.getSelectionModeForCategory(CardEmulation.CATEGORY_PAYMENT);
- Assert.assertTrue(validResults.contains(result));
+ assertTrue(validResults.contains(result));
}
@Test
public void testGetSelectionModeForCategoryWithCategoryOther() {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
int result = instance.getSelectionModeForCategory(CardEmulation.CATEGORY_OTHER);
- Assert.assertEquals(CardEmulation.SELECTION_MODE_ASK_IF_CONFLICT, result);
+ assertEquals(CardEmulation.SELECTION_MODE_ASK_IF_CONFLICT, result);
}
@Test
@@ -156,13 +169,11 @@
ComponentName offHostService = new ComponentName(mContext, CtsMyOffHostApduService.class);
try {
- Assert.assertTrue(instance.setOffHostForService(offHostService, "eSE"));
- Assert.assertTrue(
- instance.setShouldDefaultToObserveModeForService(offHostService, true));
- Assert.assertTrue(instance.unsetOffHostForService(offHostService));
+ assertTrue(instance.setOffHostForService(offHostService, "eSE"));
+ assertTrue(instance.setShouldDefaultToObserveModeForService(offHostService, true));
+ assertTrue(instance.unsetOffHostForService(offHostService));
} finally {
- Assert.assertTrue(
- instance.setShouldDefaultToObserveModeForService(offHostService, false));
+ assertTrue(instance.setShouldDefaultToObserveModeForService(offHostService, false));
}
}
@@ -170,15 +181,14 @@
public void testRegisterAndGetAids() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
- Assert.assertTrue(
- instance.registerAidsForService(
+ assertTrue(instance.registerAidsForService(
mService, CardEmulation.CATEGORY_PAYMENT, PAYMENT_AIDS));
List<String> result = instance.getAidsForService(mService, CardEmulation.CATEGORY_PAYMENT);
- Assert.assertEquals(result, PAYMENT_AIDS);
+ assertEquals(result, PAYMENT_AIDS);
// Unregister AIDs from service
- Assert.assertTrue(instance.removeAidsForService(mService, CardEmulation.CATEGORY_PAYMENT));
- Assert.assertNull(instance.getAidsForService(mService, CardEmulation.CATEGORY_PAYMENT));
+ assertTrue(instance.removeAidsForService(mService, CardEmulation.CATEGORY_PAYMENT));
+ assertNull(instance.getAidsForService(mService, CardEmulation.CATEGORY_PAYMENT));
}
@Test
@@ -186,64 +196,63 @@
CardEmulation instance = CardEmulation.getInstance(mAdapter);
Activity activity = createAndResumeActivity();
- Assert.assertTrue(instance.setPreferredService(activity, mService));
- Assert.assertTrue(instance.unsetPreferredService(activity));
+ assertTrue(instance.setPreferredService(activity, mService));
+ assertTrue(instance.unsetPreferredService(activity));
}
@Test
public void testSupportsAidPrefixRegistration() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
boolean result = instance.supportsAidPrefixRegistration();
- Assert.assertTrue(result);
+ assertTrue(result);
}
@Test
public void testGetAidsForPreferredPaymentService() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
Activity activity = createAndResumeActivity();
- Assert.assertTrue(instance.setPreferredService(activity, mService));
+ assertTrue(instance.setPreferredService(activity, mService));
List<String> result = instance.getAidsForPreferredPaymentService();
- Assert.assertEquals(result, PAYMENT_AIDS);
+ assertEquals(result, PAYMENT_AIDS);
}
@Test
public void testGetRouteDestinationForHostService() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
Activity activity = createAndResumeActivity();
- Assert.assertTrue(instance.setPreferredService(activity, mService));
+ assertTrue(instance.setPreferredService(activity, mService));
String result = instance.getRouteDestinationForPreferredPaymentService();
- Assert.assertEquals("Host", result);
+ assertEquals("Host", result);
}
@Test
public void testGetRouteDestinationForOffHostService() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
Activity activity = createAndResumeActivity();
- Assert.assertTrue(
- instance.setPreferredService(activity,
+ assertTrue(instance.setPreferredService(activity,
new ComponentName(mContext, CtsMyOffHostApduService.class)));
String result = instance.getRouteDestinationForPreferredPaymentService();
- Assert.assertEquals("OffHost", result);
+ assertEquals("OffHost", result);
// Unset preferred service
- Assert.assertTrue(instance.unsetPreferredService(activity));
+ assertTrue(instance.unsetPreferredService(activity));
}
@Test
public void testGetDescriptionForPreferredPaymentService() throws RemoteException {
CardEmulation instance = CardEmulation.getInstance(mAdapter);
Activity activity = createAndResumeActivity();
- Assert.assertTrue(instance.setPreferredService(activity, mService));
+ assertTrue(instance.setPreferredService(activity, mService));
CharSequence result = instance.getDescriptionForPreferredPaymentService();
- Assert.assertEquals(result.toString(),
+ assertEquals(result.toString(),
mContext.getResources().getString(getResIdForServiceClass(CtsMyHostApduService.class)));
}
@@ -256,7 +265,7 @@
instance.getServices(
CardEmulation.CATEGORY_PAYMENT, mContext.getUser().getIdentifier());
- Assert.assertNotNull(result);
+ assertNotNull(result);
}
@Test
@@ -267,7 +276,7 @@
List<ApduServiceInfo> result =
instance.getServices(CardEmulation.CATEGORY_OTHER, mContext.getUser().getIdentifier());
- Assert.assertNotNull(result);
+ assertNotNull(result);
}
@Test
@@ -280,8 +289,7 @@
ComponentName paymentService = CardEmulation.getPreferredPaymentService(
ApplicationProvider.getApplicationContext());
- Assert.assertEquals(paymentService,
- ComponentName.unflattenFromString(expectedPaymentService));
+ assertEquals(paymentService, ComponentName.unflattenFromString(expectedPaymentService));
}
@Test
@@ -344,7 +352,7 @@
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
customServiceName,
annotationStringHex, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(6);
@@ -364,7 +372,7 @@
Arrays.asList(frames.get(2), frames.get(6)));
notifyPollingLoopAndWait(/* framesToSend = */ frames, framesToReceive,
CustomHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(
+ assertTrue(cardEmulation.removePollingLoopFilterForService(
customServiceName, annotationStringHex));
adapter.notifyHceDeactivated();
});
@@ -441,7 +449,7 @@
handler, Activity.RESULT_OK, null, null);
try {
if (!latch.await(5, TimeUnit.SECONDS)) {
- Assert.fail("Did not receive the expected broadcast within the elapsed time");
+ fail("Did not receive the expected broadcast within the elapsed time");
}
} catch (InterruptedException ie) {
}
@@ -524,7 +532,7 @@
void waitForEvents() {
try {
if (!mLatch.await(5, TimeUnit.SECONDS)) {
- Assert.fail("Did not receive all events within the elapsed time");
+ fail("Did not receive all events within the elapsed time");
}
} catch (InterruptedException ie) {
}
@@ -533,7 +541,7 @@
void waitForEvents(int type) {
try {
if (!mLatches[type].await(5, TimeUnit.SECONDS)) {
- Assert.fail("Did not receive all events within the elapsed time");
+ fail("Did not receive all events within the elapsed time");
}
} catch (InterruptedException ie) {
}
@@ -614,52 +622,46 @@
sCurrentPollLoopReceiver = eventPollLoopReceiver;
Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(
- cardEmulation.setPreferredService(
+ assertTrue(cardEmulation.setPreferredService(
activity, new ComponentName(mContext, CustomHostApduService.class)));
ensurePreferredService(CustomHostApduService.class);
eventPollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(
- cardEmulation.setPreferredService(
+ assertTrue(cardEmulation.setPreferredService(
activity, new ComponentName(mContext, CtsMyHostApduService.class)));
eventPollLoopReceiver.waitForEvents();
ensurePreferredService(CtsMyHostApduService.class);
EventPollLoopReceiver.EventLogEntry event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, event.mEventType);
- Assert.assertTrue((boolean)event.mState);
+ assertEquals(CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
+ assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, event.mEventType);
+ assertTrue((boolean)event.mState);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
eventPollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.setObserveModeEnabled(true));
eventPollLoopReceiver.waitForEvents();
event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
- Assert.assertTrue((boolean)event.mState);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertEquals(CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
+ assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
+ assertTrue((boolean)event.mState);
+ assertTrue(adapter.isObserveModeEnabled());
eventPollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(adapter.setObserveModeEnabled(false));
+ assertTrue(adapter.setObserveModeEnabled(false));
eventPollLoopReceiver.waitForEvents();
event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
- Assert.assertFalse((boolean)event.mState);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertEquals(CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
+ assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
+ assertFalse((boolean)event.mState);
+ assertFalse(adapter.isObserveModeEnabled());
eventPollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
eventPollLoopReceiver.waitForEvents();
event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, event.mEventType);
- Assert.assertFalse((boolean)event.mState);
+ assertEquals(CtsMyHostApduService.class.getPackageName(), event.mServicePackageName);
+ assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, event.mEventType);
+ assertFalse((boolean)event.mState);
} finally {
cardEmulation.unsetPreferredService(activity);
activity.finish();
@@ -699,8 +701,7 @@
WalletRoleTestUtils.WALLET_HOLDER_PACKAGE_NAME,
() -> {
eventPollLoopReceiver.waitForEvents();
- Assert.assertTrue(
- "Didn't receive any events",
+ assertTrue("Didn't receive any events",
startingEvents < eventPollLoopReceiver.mEvents.size());
int numEvents = eventPollLoopReceiver.mEvents.size();
int numWalletEvents =
@@ -709,19 +710,16 @@
eventPollLoopReceiver.setNumEventsToWaitFor(1);
walletRolePollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(
- cardEmulation.setPreferredService(
+ assertTrue(cardEmulation.setPreferredService(
activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
try {
eventPollLoopReceiver.waitForEvents();
walletRolePollLoopReceiver.waitForEvents();
- Assert.assertTrue(
- "Didn't receive event",
+ assertTrue("Didn't receive event",
numEvents < eventPollLoopReceiver.mEvents.size());
- Assert.assertTrue(
- "Didn't receive event",
+ assertTrue("Didn't receive event",
numWalletEvents < walletRolePollLoopReceiver.mEvents.size());
EventPollLoopReceiver.EventLogEntry lostEvent =
@@ -729,44 +727,40 @@
EventPollLoopReceiver.EventLogEntry gainedEvent =
eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(WALLET_HOLDER_PACKAGE_NAME,
- lostEvent.mServicePackageName);
- Assert.assertEquals(
- EventPollLoopReceiver.PREFERRED_SERVICE, lostEvent.mEventType);
- Assert.assertFalse((boolean)lostEvent.mState);
+ assertEquals(WALLET_HOLDER_PACKAGE_NAME, lostEvent.mServicePackageName);
+ assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, lostEvent.mEventType);
+ assertFalse((boolean)lostEvent.mState);
- Assert.assertEquals(
+ assertEquals(
CtsMyHostApduService.class.getPackageName(),
gainedEvent.mServicePackageName);
- Assert.assertEquals(
+ assertEquals(
EventPollLoopReceiver.PREFERRED_SERVICE, gainedEvent.mEventType);
- Assert.assertTrue((boolean)gainedEvent.mState);
+ assertTrue((boolean)gainedEvent.mState);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
eventPollLoopReceiver.setNumEventsToWaitFor(1);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.setObserveModeEnabled(true));
eventPollLoopReceiver.waitForEvents();
EventPollLoopReceiver.EventLogEntry event =
eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(),
+ assertEquals(CtsMyHostApduService.class.getPackageName(),
event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
- Assert.assertTrue((boolean)event.mState);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
+ assertTrue((boolean)event.mState);
+ assertTrue(adapter.isObserveModeEnabled());
eventPollLoopReceiver.setNumEventsToWaitFor(1,
EventPollLoopReceiver.OBSERVE_MODE);
- Assert.assertTrue(adapter.setObserveModeEnabled(false));
+ assertTrue(adapter.setObserveModeEnabled(false));
eventPollLoopReceiver.waitForEvents(EventPollLoopReceiver.OBSERVE_MODE);
event = eventPollLoopReceiver
.mSpecificEvents[EventPollLoopReceiver.OBSERVE_MODE].getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(),
+ assertEquals(CtsMyHostApduService.class.getPackageName(),
event.mServicePackageName);
- Assert.assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
- Assert.assertFalse((boolean)event.mState);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertEquals(EventPollLoopReceiver.OBSERVE_MODE, event.mEventType);
+ assertFalse((boolean)event.mState);
+ assertFalse(adapter.isObserveModeEnabled());
numEvents = eventPollLoopReceiver.mEvents.size();
numWalletEvents =
walletRolePollLoopReceiver
@@ -774,15 +768,13 @@
eventPollLoopReceiver.setNumEventsToWaitFor(1);
walletRolePollLoopReceiver
.setNumEventsToWaitFor(1, EventPollLoopReceiver.PREFERRED_SERVICE);
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
eventPollLoopReceiver.waitForEvents();
walletRolePollLoopReceiver
.waitForEvents(EventPollLoopReceiver.PREFERRED_SERVICE);
- Assert.assertTrue(
- "Didn't receive event",
+ assertTrue("Didn't receive event",
numEvents < eventPollLoopReceiver.mEvents.size());
- Assert.assertTrue(
- "Didn't receive event",
+ assertTrue("Didn't receive event",
numWalletEvents < walletRolePollLoopReceiver
.mSpecificEvents[EventPollLoopReceiver.PREFERRED_SERVICE]
.size());
@@ -791,17 +783,14 @@
.mSpecificEvents[EventPollLoopReceiver.PREFERRED_SERVICE].getLast();
lostEvent = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(
- CtsMyHostApduService.class.getPackageName(),
+ assertEquals(CtsMyHostApduService.class.getPackageName(),
lostEvent.mServicePackageName);
- Assert.assertEquals(
- EventPollLoopReceiver.PREFERRED_SERVICE, lostEvent.mEventType);
- Assert.assertFalse((boolean)lostEvent.mState);
+ assertEquals(EventPollLoopReceiver.PREFERRED_SERVICE, lostEvent.mEventType);
+ assertFalse((boolean)lostEvent.mState);
- Assert.assertEquals(WALLET_HOLDER_PACKAGE_NAME,
- gainedEvent.mServicePackageName);
- Assert.assertEquals(
- EventPollLoopReceiver.PREFERRED_SERVICE, gainedEvent.mEventType);
+ assertEquals(WALLET_HOLDER_PACKAGE_NAME, gainedEvent.mServicePackageName);
+ assertEquals(
+ EventPollLoopReceiver.PREFERRED_SERVICE, gainedEvent.mEventType);
} finally {
if (activity != null) {
cardEmulation.unsetPreferredService(activity);
@@ -847,29 +836,29 @@
runAndWaitForNfcAdapterStateChange(
() -> {
- Assert.assertTrue(adapter.disable());
+ assertTrue(adapter.disable());
},
NfcAdapter.STATE_OFF);
eventPollLoopReceiver.waitForEvents();
- Assert.assertFalse(adapter.isEnabled());
+ assertFalse(adapter.isEnabled());
EventPollLoopReceiver.EventLogEntry event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(EventPollLoopReceiver.NFC_STATE_CHANGED, event.mEventType);
- Assert.assertEquals(NfcAdapter.STATE_OFF, event.mState);
+ assertEquals(EventPollLoopReceiver.NFC_STATE_CHANGED, event.mEventType);
+ assertEquals(NfcAdapter.STATE_OFF, event.mState);
eventPollLoopReceiver.setNumEventsToWaitFor(2);
runAndWaitForNfcAdapterStateChange(
() -> {
- Assert.assertTrue(adapter.enable());
+ assertTrue(adapter.enable());
},
NfcAdapter.STATE_ON);
eventPollLoopReceiver.waitForEvents();
- Assert.assertTrue(adapter.isEnabled());
+ assertTrue(adapter.isEnabled());
event = eventPollLoopReceiver.mEvents.getLast();
- Assert.assertEquals(EventPollLoopReceiver.NFC_STATE_CHANGED, event.mEventType);
- Assert.assertEquals(NfcAdapter.STATE_ON, event.mState);
+ assertEquals(EventPollLoopReceiver.NFC_STATE_CHANGED, event.mEventType);
+ assertEquals(NfcAdapter.STATE_ON, event.mState);
} finally {
adapter.enable();
activity.finish();
@@ -932,7 +921,7 @@
* and OID as not a VS response, so this will cause a hardware error */
adapter.sendVendorNciMessage(0x00, 0x03, 0x00, new byte[0]);
if (!callback.mErrorLatch.await(5, TimeUnit.SECONDS)) {
- Assert.fail("Did not receive internal error event within the elapsed time");
+ fail("Did not receive internal error event within the elapsed time");
}
// ToDo: can we query the recovery_option from the NfcConfig to make sure
// the error matches the config?
@@ -945,13 +934,12 @@
// The NFC service has died, so we should wait for it to come back up.
if (!adapterStateLatch.await(20, TimeUnit.SECONDS)) {
- Assert.fail("NFC service did not come back up within the elapsed time");
+ fail("NFC service did not come back up within the elapsed time");
}
- Assert.assertEquals(adapter.getAdapterState(), NfcAdapter.STATE_ON);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(
- cardEmulation.setPreferredService(
+ assertEquals(adapter.getAdapterState(), NfcAdapter.STATE_ON);
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(cardEmulation.setPreferredService(
activity, new ComponentName(mContext,
CustomHostApduService.class)));
}
@@ -961,11 +949,11 @@
// send a hardware error. Wait for the adapter to come back up to prevent
// other tests from failing.
if (!adapterStateLatch.await(20, TimeUnit.SECONDS)) {
- Assert.fail("NFC service did not come back up within the elapsed time");
+ fail("NFC service did not come back up within the elapsed time");
}
break;
default:
- Assert.fail("Expected a hardware error or timeout error but got: "
+ fail("Expected a hardware error or timeout error but got: "
+ callback.mErrorType);
}
} finally {
@@ -984,7 +972,7 @@
Activity activity = createAndResumeActivity();
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext,
CtsMyHostApduService.class)));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(6);
@@ -997,7 +985,7 @@
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1014,29 +1002,27 @@
try {
ComponentName backgroundService =
new ComponentName(mContext, BackgroundHostApduService.class);
- Assert.assertTrue(
- cardEmulation.setShouldDefaultToObserveModeForService(
+ assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(
backgroundService, false));
- Assert.assertTrue(cardEmulation.setPreferredService(activity, backgroundService));
+ assertTrue(cardEmulation.setPreferredService(activity, backgroundService));
ensurePreferredService(BackgroundHostApduService.class);
- Assert.assertFalse(adapter.isObserveModeEnabled());
- Assert.assertTrue(
- cardEmulation.setShouldDefaultToObserveModeForService(backgroundService, true));
+ assertFalse(adapter.isObserveModeEnabled());
+ assertTrue(
+ cardEmulation.setShouldDefaultToObserveModeForService(backgroundService, true));
// Observe mode is set asynchronously, so just wait a bit to let it happen.
try {
CommonTestUtils.waitUntil(
"Observe mode hasn't been set", 1, () -> adapter.isObserveModeEnabled());
} catch (InterruptedException|AssertionError e) {
}
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
ComponentName backgroundService =
new ComponentName(mContext, BackgroundHostApduService.class);
- Assert.assertTrue(
- cardEmulation.setShouldDefaultToObserveModeForService(
+ assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(
backgroundService, false));
activity.finish();
adapter.notifyHceDeactivated();
@@ -1053,12 +1039,12 @@
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
ComponentName ctsService = new ComponentName(mContext, CtsMyHostApduService.class);
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsService));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsService));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1075,15 +1061,14 @@
try {
ComponentName backgroundService =
new ComponentName(mContext, BackgroundHostApduService.class);
- Assert.assertTrue(
- cardEmulation.setShouldDefaultToObserveModeForService(
+ assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(
backgroundService, true));
- Assert.assertTrue(cardEmulation.setPreferredService(activity, backgroundService));
+ assertTrue(cardEmulation.setPreferredService(activity, backgroundService));
ensurePreferredService(BackgroundHostApduService.class);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1099,12 +1084,12 @@
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
ComponentName ctsService = new ComponentName(mContext, CtsMyOffHostApduService.class);
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsService));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsService));
ensurePreferredService(CtsMyOffHostApduService.class);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1121,12 +1106,12 @@
try {
ComponentName offhostService =
new ComponentName(mContext, CtsMyOffHostDefaultToObserveApduService.class);
- Assert.assertTrue(cardEmulation.setPreferredService(activity, offhostService));
+ assertTrue(cardEmulation.setPreferredService(activity, offhostService));
ensurePreferredService(CtsMyOffHostDefaultToObserveApduService.class);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1140,7 +1125,7 @@
Activity activity = createAndResumeActivity();
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext,
CtsMyHostApduService.class)));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(4);
@@ -1157,7 +1142,7 @@
try {
sCurrentPollLoopReceiver.wait(5000);
} catch (InterruptedException ie) {
- Assert.assertNull(ie);
+ assertNull(ie);
}
}
sCurrentPollLoopReceiver.test();
@@ -1205,7 +1190,7 @@
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
WalletRoleTestUtils.runWithRole(mContext, WalletRoleTestUtils.WALLET_HOLDER_PACKAGE_NAME,
() -> {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext,
CtsMyHostApduService.class)));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(6);
@@ -1217,7 +1202,7 @@
frames.add(createFrame(PollingFrame.POLLING_LOOP_TYPE_OFF));
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
});
@@ -1264,11 +1249,11 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CustomHostApduService.class)));
ensurePreferredService(CustomHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.setObserveModeEnabled(true));
ComponentName backgroundServiceName = new ComponentName(mContext,
BackgroundHostApduService.class);
@@ -1276,7 +1261,7 @@
}.getClass().getEnclosingMethod().getName();
String annotationStringHex1 =
HexFormat.of().toHexDigits((testName + "background").hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
backgroundServiceName, annotationStringHex1, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(2);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
@@ -1287,15 +1272,15 @@
String annotationStringHex2 =
HexFormat.of().toHexDigits((testName + "custom").hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
customServiceName, annotationStringHex2, false));
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex2)));
notifyPollingLoopAndWait(frames, /* serviceName = */ null);
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(
+ assertTrue(cardEmulation.removePollingLoopFilterForService(
backgroundServiceName, annotationStringHex1));
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(
+ assertTrue(cardEmulation.removePollingLoopFilterForService(
customServiceName, annotationStringHex2));
} finally {
cardEmulation.unsetPreferredService(activity);
@@ -1312,11 +1297,11 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.setObserveModeEnabled(true));
ComponentName backgroundServiceName = new ComponentName(mContext,
BackgroundHostApduService.class);
@@ -1324,7 +1309,7 @@
}.getClass().getEnclosingMethod().getName();
String annotationStringHex1 =
HexFormat.of().toHexDigits((testName + "background").hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
backgroundServiceName, annotationStringHex1, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(2);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
@@ -1335,15 +1320,15 @@
String annotationStringHex2 =
HexFormat.of().toHexDigits((testName + "custom").hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
customServiceName, annotationStringHex2, false));
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex2)));
notifyPollingLoopAndWait(frames, /* serviceName = */ null);
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(
+ assertTrue(cardEmulation.removePollingLoopFilterForService(
backgroundServiceName, annotationStringHex1));
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(
+ assertTrue(cardEmulation.removePollingLoopFilterForService(
customServiceName, annotationStringHex2));
} finally {
cardEmulation.unsetPreferredService(activity);
@@ -1362,7 +1347,7 @@
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
annotationStringHex, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
@@ -1373,7 +1358,7 @@
notifyPollingLoopAndWait(/* framesToSend = */ frames,
/* framesToReceive = */ new ArrayList<PollingFrame>(Arrays.asList(frames.get(0))),
CustomHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
annotationStringHex));
adapter.notifyHceDeactivated();
}
@@ -1390,7 +1375,7 @@
String annotationStringHexPrefix = HexFormat.of().toHexDigits(testName.hashCode());
String annotationStringHex = annotationStringHexPrefix + "123456789ABCDF";
String annotationStringHexPattern = annotationStringHexPrefix + ".*";
- Assert.assertTrue(cardEmulation.registerPollingLoopPatternFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopPatternFilterForService(
customServiceName, annotationStringHexPattern, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
@@ -1400,7 +1385,7 @@
notifyPollingLoopAndWait(/* framesToSend = */ frames,
/* framesToReceive = */ new ArrayList<PollingFrame>(Arrays.asList(frames.get(0))),
CustomHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.removePollingLoopPatternFilterForService(customServiceName,
+ assertTrue(cardEmulation.removePollingLoopPatternFilterForService(customServiceName,
annotationStringHexPrefix));
adapter.notifyHceDeactivated();
}
@@ -1418,7 +1403,7 @@
originalDefault = setDefaultPaymentService(CustomHostApduService.class);
ComponentName ctsMyServiceName = new ComponentName(mContext,
CtsMyHostApduService.class);
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsMyServiceName));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsMyServiceName));
ComponentName customServiceName = new ComponentName(mContext,
CustomHostApduService.class);
ComponentName backgroundServiceName = new ComponentName(mContext,
@@ -1426,11 +1411,11 @@
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
annotationStringHex, false));
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
backgroundServiceName, annotationStringHex, false));
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsMyServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsMyServiceName,
annotationStringHex, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
@@ -1438,7 +1423,7 @@
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
setDefaultPaymentService(originalDefault);
adapter.notifyHceDeactivated();
@@ -1455,25 +1440,25 @@
ComponentName ctsServiceName = new ComponentName(mContext,
CtsMyHostApduService.class);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsServiceName));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsServiceName));
ComponentName backgroundServiceName = new ComponentName(mContext,
BackgroundHostApduService.class);
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsServiceName,
annotationStringHex, false));
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
backgroundServiceName, annotationStringHex, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex)));
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(ctsServiceName,
+ assertTrue(cardEmulation.removePollingLoopFilterForService(ctsServiceName,
annotationStringHex));
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1492,23 +1477,23 @@
originalDefault = setDefaultPaymentService(customServiceName);
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
- Assert.assertTrue(cardEmulation.isDefaultServiceForCategory(customServiceName,
+ assertTrue(cardEmulation.isDefaultServiceForCategory(customServiceName,
CardEmulation.CATEGORY_PAYMENT));
ComponentName backgroundServiceName = new ComponentName(mContext,
BackgroundHostApduService.class);
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
annotationStringHex, false));
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(
backgroundServiceName, annotationStringHex, false));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex)));
ensurePreferredService(CustomHostApduService.class);
notifyPollingLoopAndWait(frames, CustomHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
annotationStringHex));
} finally {
setDefaultPaymentService(originalDefault);
@@ -1542,7 +1527,7 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
originalDefault = setDefaultPaymentService(CustomHostApduService.class);
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
@@ -1553,7 +1538,7 @@
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
setDefaultPaymentService(originalDefault);
adapter.notifyHceDeactivated();
@@ -1570,7 +1555,7 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
WalletRoleTestUtils.runWithRole(mContext, WalletRoleTestUtils.WALLET_HOLDER_PACKAGE_NAME,
() -> {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
@@ -1580,7 +1565,7 @@
HexFormat.of().parseHex(annotationStringHex)));
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
});
@@ -1594,7 +1579,7 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
String testName = new Object() {
}.getClass().getEnclosingMethod().getName();
@@ -1605,7 +1590,7 @@
ensurePreferredService(CtsMyHostApduService.class);
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
} finally {
- Assert.assertTrue(cardEmulation.unsetPreferredService(activity));
+ assertTrue(cardEmulation.unsetPreferredService(activity));
activity.finish();
adapter.notifyHceDeactivated();
}
@@ -1662,7 +1647,7 @@
assumeVsrApiGreaterThanUdc();
runWithRole(mContext, CTS_PACKAGE_NAME, () -> {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
String testName = new Object() {
@@ -1674,11 +1659,11 @@
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
PollingCheck.check("Observe mode not disabled", 4000,
() -> !adapter.isObserveModeEnabled());
adapter.notifyHceDeactivated();
@@ -1696,7 +1681,7 @@
public void testDontAutoDisableObserveModeInForeground() throws Exception {
assumeVsrApiGreaterThanUdc();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
String testName = new Object() {
@@ -1708,16 +1693,16 @@
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
final Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
Thread.currentThread().sleep(4000);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
adapter.notifyHceDeactivated();
} catch (Exception ex) {
throw new RuntimeException(ex);
@@ -1732,7 +1717,7 @@
public void testDontAutoDisableObserveModeInForegroundTwoServices() throws Exception {
assumeVsrApiGreaterThanUdc();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
String testName = new Object() {
@@ -1745,27 +1730,27 @@
ComponentName walletServiceName = WalletRoleTestUtils.getWalletRoleHolderService();
String annotationStringHex2 = HexFormat.of().toHexDigits((testName).hashCode());
ComponentName ctsComponentName = new ComponentName(mContext, CtsMyHostApduService.class);
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsComponentName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(ctsComponentName,
annotationStringHex2, false));
ArrayList<PollingFrame> frames2 = new ArrayList<PollingFrame>(1);
frames2.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex2)));
final Activity activity = createAndResumeActivity();
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames1,
WalletRoleTestUtils.getWalletRoleHolderService().getClassName());
- Assert.assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
receivedFrames =
notifyPollingLoopAndWait(frames2, CtsMyHostApduService.class.getName());
- Assert.assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertFalse(receivedFrames.get(0).getTriggeredAutoTransact());
Thread.currentThread().sleep(5000);
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(ctsComponentName,
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(cardEmulation.removePollingLoopFilterForService(ctsComponentName,
annotationStringHex2));
adapter.notifyHceDeactivated();
} catch (Exception ex) {
@@ -1779,7 +1764,7 @@
public void testAutoTransact() throws Exception {
assumeVsrApiGreaterThanUdc();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
final Activity activity = createAndResumeActivity();
@@ -1791,14 +1776,14 @@
HexFormat.of().parseHex(annotationStringHex)));
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CustomHostApduService.class.getName());
- Assert.assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
PollingCheck.check("Observe mode not disabled", 200,
() -> !adapter.isObserveModeEnabled());
adapter.notifyHceDeactivated();
@@ -1816,7 +1801,7 @@
assumeVsrApiGreaterThanUdc();
runWithRole(mContext, CTS_PACKAGE_NAME, () -> {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
createAndResumeActivity();
@@ -1826,11 +1811,11 @@
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex)));
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CustomHostApduService.class.getName());
- Assert.assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
try {
PollingCheck.check("Observe mode not disabled", 200,
() -> !adapter.isObserveModeEnabled());
@@ -1848,7 +1833,7 @@
public void testAutoTransactDynamic() throws Exception {
assumeVsrApiGreaterThanUdc();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
final Activity activity = createAndResumeActivity();
@@ -1857,23 +1842,23 @@
String annotationStringHex = HexFormat.of().toHexDigits(testName.hashCode());
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName customServiceName = new ComponentName(mContext, CustomHostApduService.class);
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
annotationStringHex, true));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex)));
ComponentName ctsComponentName = new ComponentName(mContext, CtsMyHostApduService.class);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CustomHostApduService.class.getName());
- Assert.assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
PollingCheck.check("Observe mode not disabled", 200,
() -> !adapter.isObserveModeEnabled());
- Assert.assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.removePollingLoopFilterForService(customServiceName,
annotationStringHex));
adapter.notifyHceDeactivated();
PollingCheck.check("Observe mode not enabled", 3000, adapter::isObserveModeEnabled);
@@ -1889,7 +1874,7 @@
public void testOffHostAutoTransactDynamic() throws Exception {
assumeVsrApiGreaterThanUdc();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
final Activity activity = createAndResumeActivity();
@@ -1899,18 +1884,18 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName offhostServiceName = new ComponentName(mContext,
CtsMyOffHostApduService.class);
- Assert.assertFalse(cardEmulation.registerPollingLoopFilterForService(offhostServiceName,
+ assertFalse(cardEmulation.registerPollingLoopFilterForService(offhostServiceName,
"1234567890", false));
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(offhostServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(offhostServiceName,
annotationStringHex, true));
PollingFrame frame = createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex));
ComponentName ctsComponentName = new ComponentName(mContext, CtsMyHostApduService.class);
try {
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsComponentName));
ensurePreferredService(CtsMyHostApduService.class);
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
adapter.notifyPollingLoop(frame);
PollingCheck.check("Observe mode not disabled", 200,
() -> !adapter.isObserveModeEnabled());
@@ -1928,11 +1913,11 @@
public void testDisallowNonDefaultSetObserveMode() throws NoSuchFieldException {
runWithRole(mContext, WalletRoleTestUtils.WALLET_HOLDER_PACKAGE_NAME, () -> {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
- Assert.assertFalse(adapter.setObserveModeEnabled(true));
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.setObserveModeEnabled(true));
+ assertFalse(adapter.isObserveModeEnabled());
});
}
@@ -1943,7 +1928,7 @@
runWithRole(mContext, CTS_PACKAGE_NAME, () -> {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
assumeObserveModeSupported(adapter);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
adapter.notifyHceDeactivated();
createAndResumeActivity();
String testName = new Object() {
@@ -1952,16 +1937,16 @@
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName customServiceName = new ComponentName(mContext,
CtsMyHostApduService.class);
- Assert.assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
+ assertTrue(cardEmulation.registerPollingLoopFilterForService(customServiceName,
annotationStringHex, true));
ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(1);
frames.add(createFrameWithData(PollingFrame.POLLING_LOOP_TYPE_UNKNOWN,
HexFormat.of().parseHex(annotationStringHex)));
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
List<PollingFrame> receivedFrames =
notifyPollingLoopAndWait(frames, CtsMyHostApduService.class.getName());
- Assert.assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
+ assertTrue(receivedFrames.get(0).getTriggeredAutoTransact());
try {
PollingCheck.check("Observe mode not disabled", 200,
() -> !adapter.isObserveModeEnabled());
@@ -1981,13 +1966,13 @@
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName customServiceName = new ComponentName(mContext, CustomHostApduService.class);
- Assert.assertThrows(IllegalArgumentException.class,
+ assertThrows(IllegalArgumentException.class,
() -> cardEmulation.registerPollingLoopFilterForService(customServiceName,
"", false));
- Assert.assertThrows(IllegalArgumentException.class,
+ assertThrows(IllegalArgumentException.class,
() ->cardEmulation.registerPollingLoopFilterForService(customServiceName,
"????", false));
- Assert.assertThrows(IllegalArgumentException.class,
+ assertThrows(IllegalArgumentException.class,
() ->cardEmulation.registerPollingLoopFilterForService(customServiceName,
"123", false));
@@ -2094,21 +2079,21 @@
void test() {
if (mReceivedFrames.size() > mExpectedFrames.size()) {
- Assert.fail("received more frames than sent");
+ fail("received more frames than sent");
} else if (mReceivedFrames.size() < mExpectedFrames.size()) {
- Assert.fail("received fewer frames than sent");
+ fail("received fewer frames than sent");
}
for (PollingFrame receivedFrame : mReceivedFrames) {
PollingFrame expectedFrame = mExpectedFrames.get(mFrameIndex);
- Assert.assertEquals(expectedFrame.getType(), receivedFrame.getType());
- Assert.assertEquals(expectedFrame.getVendorSpecificGain(),
- receivedFrame.getVendorSpecificGain());
- Assert.assertEquals(expectedFrame.getTimestamp(), receivedFrame.getTimestamp());
- Assert.assertArrayEquals(expectedFrame.getData(), receivedFrame.getData());
+ assertEquals(expectedFrame.getType(), receivedFrame.getType());
+ assertEquals(expectedFrame.getVendorSpecificGain(),
+ receivedFrame.getVendorSpecificGain());
+ assertEquals(expectedFrame.getTimestamp(), receivedFrame.getTimestamp());
+ assertArrayEquals(expectedFrame.getData(), receivedFrame.getData());
mFrameIndex++;
}
if (mExpectedServiceName != null) {
- Assert.assertEquals(mExpectedServiceName, mReceivedServiceName);
+ assertEquals(mExpectedServiceName, mReceivedServiceName);
}
}
public void onObserveModeStateChanged(String className, boolean isEnabled) {
@@ -2145,7 +2130,7 @@
try {
pollLoopReceiver.wait(10000);
} catch (InterruptedException ie) {
- Assert.assertNull(ie);
+ assertNull(ie);
}
}
pollLoopReceiver.test();
@@ -2183,19 +2168,19 @@
* The foreground app does not have NON_PAYMENT_AID_1. Neither does the role holder.
* So an app in the background (Non Payment App) gets the routing.
**/
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getNonPaymentService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
- Assert.assertTrue(instance.unsetPreferredService(activity));
+ assertTrue(instance.unsetPreferredService(activity));
activity.finish();
});
}
@@ -2222,13 +2207,13 @@
* PAYMENT_AID_2.
**/
CardEmulation instance = CardEmulation.getInstance(mAdapter);
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getAssociatedService(),
WalletRoleTestUtils.PAYMENT_AID_3));
});
@@ -2259,13 +2244,13 @@
* PAYMENT_AID_2.
**/
CardEmulation instance = CardEmulation.getInstance(mAdapter);
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getAssociatedService(),
WalletRoleTestUtils.PAYMENT_AID_3));
});
@@ -2300,25 +2285,25 @@
* A background app that is not the wallet role holder has the NON_PAYMENT_AID_1.
* So that app gets the routing for NON_PAYMENT_AID_1.
**/
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderXService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderXService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getNonPaymentService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
});
@@ -2349,25 +2334,25 @@
* The rest of the apps will always need to disambig and will not be set as defaults.
*
**/
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderXService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderXService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getNonPaymentService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
});
@@ -2397,25 +2382,25 @@
* for those AIDs.
*
**/
- Assert.assertTrue(instance.isDefaultServiceForAid(
+ assertTrue(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getNonPaymentService(),
WalletRoleTestUtils.NON_PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderXService(),
WalletRoleTestUtils.PAYMENT_AID_2));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getWalletRoleHolderService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.PAYMENT_AID_1));
- Assert.assertFalse(instance.isDefaultServiceForAid(
+ assertFalse(instance.isDefaultServiceForAid(
WalletRoleTestUtils.getForegroundService(),
WalletRoleTestUtils.PAYMENT_AID_2));
});
@@ -2425,10 +2410,10 @@
@Test
public void testOverrideRoutingTable() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
final Activity activity = createAndResumeActivity();
CardEmulation instance = CardEmulation.getInstance(adapter);
- Assert.assertThrows(SecurityException.class,
+ assertThrows(SecurityException.class,
() -> instance.overrideRoutingTable(activity,
CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_DH,
CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET));
@@ -2443,7 +2428,7 @@
@Test
public void testRecoverRoutingTable() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
final Activity activity = createAndResumeActivity();
CardEmulation instance = CardEmulation.getInstance(adapter);
instance.recoverRoutingTable(activity);
@@ -2453,7 +2438,7 @@
@Test
public void testIsEuiccSupported() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
CardEmulation instance = CardEmulation.getInstance(adapter);
instance.isEuiccSupported();
}
@@ -2462,11 +2447,11 @@
@Test
public void testGetSetDefaultNfcSubscriptionId() {
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
CardEmulation instance = CardEmulation.getInstance(adapter);
instance.setDefaultNfcSubscriptionId(SUBSCRIPTION_ID_UICC);
- Assert.assertEquals(SUBSCRIPTION_ID_UICC, instance.getDefaultNfcSubscriptionId());
+ assertEquals(SUBSCRIPTION_ID_UICC, instance.getDefaultNfcSubscriptionId());
}
@RequiresFlagsEnabled(Flags.FLAG_NFC_APDU_SERVICE_INFO_CONSTRUCTOR)
@@ -2494,15 +2479,6 @@
"test");
}
- private void assumeObserveModeSupported(@NonNull NfcAdapter adapter) {
- assumeTrue("Observe mode must be supported", adapter.isObserveModeSupported());
- }
-
- private void assumeVsrApiGreaterThanUdc() {
- assumeTrue("Device VSR API level must be greater than UDC",
- getVsrApiLevel() > Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
- }
-
private Activity createAndResumeActivity() {
ensureUnlocked();
Intent intent
@@ -2511,6 +2487,10 @@
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ ComponentName topComponentName = mContext.getSystemService(ActivityManager.class)
+ .getRunningTasks(1).get(0).topActivity;
+ Assert.assertEquals("Foreground activity not in the foreground",
+ NfcFCardEmulationActivity.class.getName(), topComponentName.getClassName());
return activity;
}
}
diff --git a/tests/cts/tests/src/android/nfc/cts/DefaultPaymentProviderTestUtils.java b/tests/cts/tests/src/android/nfc/cts/DefaultPaymentProviderTestUtils.java
index 8771bf2..c186d9f 100644
--- a/tests/cts/tests/src/android/nfc/cts/DefaultPaymentProviderTestUtils.java
+++ b/tests/cts/tests/src/android/nfc/cts/DefaultPaymentProviderTestUtils.java
@@ -16,6 +16,8 @@
package android.nfc.cts;
+import static org.junit.Assert.assertTrue;
+
import android.content.ComponentName;
import android.content.Context;
import android.nfc.Constants;
@@ -80,8 +82,8 @@
count++;
}
}
- Assert.assertTrue(count < 10);
- Assert.assertTrue(serviceName == null
+ assertTrue(count < 10);
+ assertTrue(serviceName == null
? null == CardEmulation.getPreferredPaymentService(context)
: serviceName.equals(cardEmulation.getPreferredPaymentService(context)));
return originalValue;
diff --git a/tests/cts/tests/src/android/nfc/cts/HostApduServiceTest.java b/tests/cts/tests/src/android/nfc/cts/HostApduServiceTest.java
index ead3399..2c3205a 100644
--- a/tests/cts/tests/src/android/nfc/cts/HostApduServiceTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/HostApduServiceTest.java
@@ -1,5 +1,8 @@
package android.nfc.cts;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.content.Intent;
import android.nfc.cardemulation.PollingFrame;
import android.os.Bundle;
@@ -32,7 +35,7 @@
public void testOnBind() {
Intent serviceIntent
= new Intent(CtsMyHostApduService.SERVICE_INTERFACE);
- Assert.assertNotNull(service.onBind(serviceIntent));
+ assertNotNull(service.onBind(serviceIntent));
}
@Test
@@ -67,8 +70,8 @@
@Test
public void testProcessCommandApdu() {
byte[] result = service.processCommandApdu(new byte[0], new Bundle());
- Assert.assertNotNull(result);
- Assert.assertTrue(result.length == 0);
+ assertNotNull(result);
+ assertTrue(result.length == 0);
}
@Test
diff --git a/tests/cts/tests/src/android/nfc/cts/HostNfcFServiceTest.java b/tests/cts/tests/src/android/nfc/cts/HostNfcFServiceTest.java
index cf41790..df63f37 100644
--- a/tests/cts/tests/src/android/nfc/cts/HostNfcFServiceTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/HostNfcFServiceTest.java
@@ -1,5 +1,8 @@
package android.nfc.cts;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
@@ -25,7 +28,7 @@
public void testOnBind() {
Intent serviceIntent
= new Intent(CtsMyHostNfcFService.SERVICE_INTERFACE);
- Assert.assertNotNull(service.onBind(serviceIntent));
+ assertNotNull(service.onBind(serviceIntent));
}
@Test
@@ -41,8 +44,8 @@
@Test
public void testProcessNfcFPacket() {
byte[] result = service.processNfcFPacket(new byte[0], new Bundle());
- Assert.assertNotNull(result);
- Assert.assertTrue(result.length == 0);
+ assertNotNull(result);
+ assertTrue(result.length == 0);
}
@Test
diff --git a/tests/cts/tests/src/android/nfc/cts/NfcAdapterTest.java b/tests/cts/tests/src/android/nfc/cts/NfcAdapterTest.java
index f0faaf5..b5ee863 100644
--- a/tests/cts/tests/src/android/nfc/cts/NfcAdapterTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/NfcAdapterTest.java
@@ -8,12 +8,13 @@
import static android.nfc.NfcRoutingTableEntry.TYPE_TECHNOLOGY;
import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET;
-
-import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel;
+import static android.nfc.cts.NfcUtils.assumeObserveModeSupported;
+import static android.nfc.cts.NfcUtils.assumeVsrApiGreaterThanUdc;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
@@ -24,6 +25,7 @@
import static org.mockito.Mockito.when;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -51,7 +53,6 @@
import android.nfc.cardemulation.CardEmulation;
import android.nfc.tech.IsoDep;
import android.nfc.tech.TagTechnology;
-import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -69,6 +70,7 @@
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -105,17 +107,16 @@
MockitoAnnotations.initMocks(this);
mContext = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
assumeTrue("Device must support NFC", supportsHardware());
- // Backup the original service. It is being overridden
- // when creating a mocked adapter.
+
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- Assume.assumeNotNull("NFC Adapter is null", adapter);
- assumeTrue("NFC Adapter could not be enabled", NfcUtils.enableNfc(adapter, mContext));
+ assertNotNull("NFC Adapter is null", adapter);
+ assertTrue("NFC Adapter could not be enabled", NfcUtils.enableNfc(adapter, mContext));
}
@Test
public void testGetDefaultAdapter() {
NfcAdapter adapter = getDefaultAdapter();
- Assert.assertNotNull(adapter);
+ assertNotNull(adapter);
}
@Test
@@ -130,29 +131,29 @@
@Test
public void testEnableAndDisable() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- Assert.assertTrue(adapter.isEnabled());
+ assertTrue(adapter.isEnabled());
// Disable NFC
- Assert.assertTrue(NfcUtils.disableNfc(adapter, mContext));
- Assert.assertFalse(adapter.isEnabled());
+ assertTrue(NfcUtils.disableNfc(adapter, mContext));
+ assertFalse(adapter.isEnabled());
// Re-enable NFC
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(adapter.isEnabled());
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(adapter.isEnabled());
}
@Test
public void testEnableAndDisablePersist() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- Assert.assertTrue(adapter.isEnabled());
+ assertTrue(adapter.isEnabled());
// Disable NFC
- Assert.assertTrue(NfcUtils.disableNfc(adapter, mContext, /* persist = */ false));
- Assert.assertFalse(adapter.isEnabled());
+ assertTrue(NfcUtils.disableNfc(adapter, mContext, /* persist = */ false));
+ assertFalse(adapter.isEnabled());
// Re-enable NFC
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(adapter.isEnabled());
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(adapter.isEnabled());
}
@Test
@@ -194,32 +195,32 @@
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_NFC_READER_OPTION)
public void testEnableAndDisableReaderOption() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- assumeTrue(adapter.isReaderOptionSupported());
+ assumeTrue("Device must support reader option", adapter.isReaderOptionSupported());
- Assert.assertTrue(adapter.enableReaderOption(/* enable = */ true));
- Assert.assertTrue(adapter.isReaderOptionEnabled());
+ assertTrue(adapter.enableReaderOption(/* enable = */ true));
+ assertTrue(adapter.isReaderOptionEnabled());
- Assert.assertTrue(adapter.enableReaderOption(/* enable = */ false));
- Assert.assertFalse(adapter.isReaderOptionEnabled());
+ assertTrue(adapter.enableReaderOption(/* enable = */ false));
+ assertFalse(adapter.isReaderOptionEnabled());
}
@Test
public void testEnableAndDisableSecureNfc() throws RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- assumeTrue(adapter.isSecureNfcSupported());
+ assumeTrue("Device must support secure NFC", adapter.isSecureNfcSupported());
- Assert.assertTrue(adapter.enableSecureNfc(/* enable = */ true));
- Assert.assertTrue(adapter.isSecureNfcEnabled());
+ assertTrue(adapter.enableSecureNfc(/* enable = */ true));
+ assertTrue(adapter.isSecureNfcEnabled());
- Assert.assertTrue(adapter.enableSecureNfc(/* enable = */ false));
- Assert.assertFalse(adapter.isSecureNfcEnabled());
+ assertTrue(adapter.enableSecureNfc(/* enable = */ false));
+ assertFalse(adapter.isSecureNfcEnabled());
}
@Test
public void testGetNfcAntennaInfo() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
NfcAntennaInfo antenna = adapter.getNfcAntennaInfo();
- Assert.assertNotNull(antenna);
+ assertNotNull(antenna);
}
@Test
@@ -229,14 +230,14 @@
sTagRemoved = false;
IsoDep isoDep = createIsoDepTag();
- Assert.assertTrue(adapter.ignore(isoDep.getTag(), 0, listener, null));
+ assertTrue(adapter.ignore(isoDep.getTag(), 0, listener, null));
// Wait a second to make sure listener callback fired
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// Ignore
}
- Assert.assertTrue(sTagRemoved);
+ assertTrue(sTagRemoved);
}
@Test
@@ -245,24 +246,25 @@
NfcAdapter adapter = getDefaultAdapter();
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
.getUiAutomation().adoptShellPermissionIdentity(NFC_SET_CONTROLLER_ALWAYS_ON);
- assumeTrue(adapter.isControllerAlwaysOnSupported());
+ assumeTrue("Device must support controller always on",
+ adapter.isControllerAlwaysOnSupported());
NfcControllerAlwaysOnListener cb = null;
CountDownLatch countDownLatch;
try {
countDownLatch = new CountDownLatch(1);
cb = new NfcControllerAlwaysOnListener(countDownLatch);
adapter.registerControllerAlwaysOnListener(Executors.newSingleThreadExecutor(), cb);
- Assert.assertTrue(adapter.setControllerAlwaysOn(true));
+ assertTrue(adapter.setControllerAlwaysOn(true));
assertTrue(countDownLatch.await(1, TimeUnit.SECONDS));
- Assert.assertTrue(adapter.isControllerAlwaysOn());
+ assertTrue(adapter.isControllerAlwaysOn());
adapter.unregisterControllerAlwaysOnListener(cb);
countDownLatch = new CountDownLatch(1);
cb = new NfcControllerAlwaysOnListener(countDownLatch);
adapter.registerControllerAlwaysOnListener(Executors.newSingleThreadExecutor(), cb);
- Assert.assertTrue(adapter.setControllerAlwaysOn(false));
+ assertTrue(adapter.setControllerAlwaysOn(false));
assertTrue(countDownLatch.await(1, TimeUnit.SECONDS));
- Assert.assertFalse(adapter.isControllerAlwaysOn());
+ assertFalse(adapter.isControllerAlwaysOn());
adapter.unregisterControllerAlwaysOnListener(cb);
} finally {
if (cb != null)
@@ -278,11 +280,11 @@
public void testAdapterState() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(adapter.getAdapterState() == NfcAdapter.STATE_ON);
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(adapter.getAdapterState() == NfcAdapter.STATE_ON);
- Assert.assertTrue(NfcUtils.disableNfc(adapter, mContext));
- Assert.assertTrue(adapter.getAdapterState() == NfcAdapter.STATE_OFF);
+ assertTrue(NfcUtils.disableNfc(adapter, mContext));
+ assertTrue(adapter.getAdapterState() == NfcAdapter.STATE_OFF);
}
@Test
@@ -343,9 +345,9 @@
try {
originalDefault = setDefaultPaymentService(CtsMyHostApduService.class);
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
boolean result = adapter.setObserveModeEnabled(false);
- Assert.assertTrue(result);
+ assertTrue(result);
} finally {
setDefaultPaymentService(originalDefault);
adapter.notifyHceDeactivated();
@@ -362,9 +364,9 @@
try {
originalDefault = setDefaultPaymentService(CtsMyHostApduService.class);
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
boolean result = adapter.setObserveModeEnabled(true);
- Assert.assertTrue(result);
+ assertTrue(result);
} finally {
setDefaultPaymentService(originalDefault);
adapter.notifyHceDeactivated();
@@ -385,10 +387,10 @@
CustomHostApduService.class), true);
originalDefault = setDefaultPaymentService(CustomHostApduService.class);
CardEmulationTest.ensurePreferredService(CustomHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
setDefaultPaymentService(CtsMyHostApduService.class);
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
cardEmulation.setShouldDefaultToObserveModeForService(new ComponentName(mContext,
CustomHostApduService.class), false);
@@ -402,7 +404,7 @@
public void testDefaultObserveModeForegroundDynamic() {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
try {
Activity activity = createAndResumeActivity();
@@ -410,15 +412,15 @@
CustomHostApduService.class), true);
cardEmulation.setShouldDefaultToObserveModeForService(new ComponentName(mContext,
CtsMyHostApduService.class), false);
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CustomHostApduService.class)));
CardEmulationTest.ensurePreferredService(CustomHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
adapter.notifyHceDeactivated();
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
cardEmulation.setShouldDefaultToObserveModeForService(new ComponentName(mContext,
CustomHostApduService.class), false);
@@ -431,27 +433,27 @@
public void testDefaultObserveModeOnlyWithServiceChange() {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
cardEmulation.setShouldDefaultToObserveModeForService(new ComponentName(mContext,
CtsMyHostApduService.class), true);
WalletRoleTestUtils.runWithRole(mContext, WalletRoleTestUtils.CTS_PACKAGE_NAME, () -> {
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(adapter.setObserveModeEnabled(false));
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(false));
+ assertFalse(adapter.isObserveModeEnabled());
try {
Activity activity = createAndResumeActivity();
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertFalse(adapter.isObserveModeEnabled());
- Assert.assertTrue(adapter.setObserveModeEnabled(true));
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertFalse(adapter.isObserveModeEnabled());
+ assertTrue(adapter.setObserveModeEnabled(true));
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CustomHostApduService.class)));
CardEmulationTest.ensurePreferredService(CustomHostApduService.class, mContext);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
cardEmulation.setShouldDefaultToObserveModeForService(new ComponentName(mContext,
CustomHostApduService.class), false);
@@ -472,10 +474,10 @@
try {
originalDefault = setDefaultPaymentService(BackgroundHostApduService.class);
CardEmulationTest.ensurePreferredService(BackgroundHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
setDefaultPaymentService(CtsMyHostApduService.class);
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
} finally {
setDefaultPaymentService(originalDefault);
adapter.notifyHceDeactivated();
@@ -491,15 +493,15 @@
new ComponentName(mContext, CtsMyHostApduService.class), false);
Activity activity = createAndResumeActivity();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assumeObserveModeSupported(adapter);
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, BackgroundHostApduService.class)));
CardEmulationTest.ensurePreferredService(BackgroundHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(cardEmulation.setPreferredService(activity,
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(cardEmulation.setPreferredService(activity,
new ComponentName(mContext, CtsMyHostApduService.class)));
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
}
@Test
@@ -509,9 +511,9 @@
WalletRoleTestUtils.runWithRole(mContext, WalletRoleTestUtils.CTS_PACKAGE_NAME, () -> {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
adapter.setObserveModeEnabled(false);
- Assert.assertFalse(adapter.isObserveModeEnabled());
+ assertFalse(adapter.isObserveModeEnabled());
adapter.notifyHceDeactivated();
});
}
@@ -523,9 +525,9 @@
WalletRoleTestUtils.runWithRole(mContext, WalletRoleTestUtils.CTS_PACKAGE_NAME, () -> {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
adapter.setObserveModeEnabled(true);
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
adapter.notifyHceDeactivated();
});
}
@@ -536,22 +538,22 @@
NfcAdapter adapter = getDefaultAdapter();
// Disable charging feature
- Assert.assertTrue(adapter.setWlcEnabled(false));
- Assert.assertFalse(adapter.isWlcEnabled());
+ assertTrue(adapter.setWlcEnabled(false));
+ assertFalse(adapter.isWlcEnabled());
// Enable charging feature
- Assert.assertTrue(adapter.setWlcEnabled(true));
- Assert.assertTrue(adapter.isWlcEnabled());
+ assertTrue(adapter.setWlcEnabled(true));
+ assertTrue(adapter.isWlcEnabled());
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_NFC_VENDOR_CMD)
public void testSendVendorCmd() throws InterruptedException, RemoteException {
- assumeTrue(getVsrApiLevel() > Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
+ assumeVsrApiGreaterThanUdc();
CountDownLatch rspCountDownLatch = new CountDownLatch(1);
CountDownLatch ntfCountDownLatch = new CountDownLatch(1);
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcVendorNciCallback cb =
new NfcVendorNciCallback(rspCountDownLatch, ntfCountDownLatch);
try {
@@ -587,7 +589,7 @@
.thenReturn(mDevicePolicyManager);
NfcAdapter adapter = getDefaultAdapter();
boolean result = adapter.enable();
- Assert.assertTrue(result);
+ assertTrue(result);
}
@Test
@@ -602,32 +604,32 @@
.thenReturn(mDevicePolicyManager);
NfcAdapter adapter = getDefaultAdapter();
boolean result = adapter.disable();
- Assert.assertTrue(result);
+ assertTrue(result);
result = adapter.enable();
- Assert.assertTrue(result);
+ assertTrue(result);
}
@Test
public void testShouldDefaultToObserveModeAfterNfcOffOn() throws InterruptedException {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
adapter.notifyHceDeactivated();
Activity activity = createAndResumeActivity();
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName ctsService = new ComponentName(mContext, CtsMyHostApduService.class);
try {
- Assert.assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
+ assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
true));
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsService));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsService));
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertTrue(adapter.isObserveModeEnabled());
- Assert.assertTrue(NfcUtils.disableNfc(adapter, mContext));
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(NfcUtils.disableNfc(adapter, mContext));
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(adapter.isObserveModeEnabled());
} finally {
cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
false);
@@ -640,20 +642,20 @@
public void testShouldDefaultToObserveModeWithNfcOff() throws InterruptedException {
NfcAdapter adapter = getDefaultAdapter();
adapter.notifyHceDeactivated();
- assumeTrue(adapter.isObserveModeSupported());
+ assumeObserveModeSupported(adapter);
Activity activity = createAndResumeActivity();
final CardEmulation cardEmulation = CardEmulation.getInstance(adapter);
ComponentName ctsService = new ComponentName(mContext, CtsMyHostApduService.class);
try {
- Assert.assertTrue(NfcUtils.disableNfc(adapter, mContext));
- Assert.assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
+ assertTrue(NfcUtils.disableNfc(adapter, mContext));
+ assertTrue(cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
true));
- Assert.assertTrue(cardEmulation.setPreferredService(activity, ctsService));
+ assertTrue(cardEmulation.setPreferredService(activity, ctsService));
CardEmulationTest.ensurePreferredService(CtsMyHostApduService.class, mContext);
- Assert.assertTrue(NfcUtils.enableNfc(adapter, mContext));
- Assert.assertTrue(adapter.isObserveModeEnabled());
+ assertTrue(NfcUtils.enableNfc(adapter, mContext));
+ assertTrue(adapter.isObserveModeEnabled());
} finally {
cardEmulation.setShouldDefaultToObserveModeForService(ctsService,
false);
@@ -667,9 +669,9 @@
public void testOemExtension() throws InterruptedException {
CountDownLatch tagDetectedCountDownLatch = new CountDownLatch(3);
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
NfcOemExtensionCallback cb =
new NfcOemExtensionCallback(tagDetectedCountDownLatch);
try {
@@ -748,28 +750,30 @@
@Test
@RequiresDevice
+ @Ignore("b/404565741")
@RequiresFlagsEnabled(Flags.FLAG_NFC_OEM_EXTENSION)
public void testOemExtensionMaybeTriggerFirmwareUpdateWhenEnabled()
throws InterruptedException, RemoteException {
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
nfcOemExtension.maybeTriggerFirmwareUpdate();
}
@Test
@RequiresDevice
+ @Ignore("b/404565741")
@RequiresFlagsEnabled(Flags.FLAG_NFC_OEM_EXTENSION)
public void testOemExtensionMaybeTriggerFirmwareUpdateWhenDisabled()
throws InterruptedException, RemoteException {
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
// Disable NFC
- Assert.assertTrue(NfcUtils.disableNfc(nfcAdapter, mContext));
- Assert.assertFalse(nfcAdapter.isEnabled());
+ assertTrue(NfcUtils.disableNfc(nfcAdapter, mContext));
+ assertFalse(nfcAdapter.isEnabled());
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
nfcOemExtension.maybeTriggerFirmwareUpdate();
}
@@ -778,9 +782,9 @@
public void testOemExtensionTriggerInitialization()
throws InterruptedException, RemoteException {
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
nfcOemExtension.triggerInitialization();
}
@@ -790,10 +794,10 @@
throws RemoteException, InterruptedException {
CountDownLatch tagDetectedCountDownLatch = new CountDownLatch(5);
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
NfcOemExtension.Callback cb = new NfcOemExtensionCallback(tagDetectedCountDownLatch);
try {
nfcOemExtension.registerCallback(
@@ -914,12 +918,13 @@
@RequiresFlagsEnabled(Flags.FLAG_NFC_OEM_EXTENSION)
public void testOemExtensionSetControllerAlwaysOn() throws InterruptedException {
NfcAdapter nfcAdapter = getDefaultAdapter();
- Assert.assertNotNull(nfcAdapter);
+ assertNotNull(nfcAdapter);
NfcOemExtension nfcOemExtension = nfcAdapter.getNfcOemExtension();
- Assert.assertNotNull(nfcOemExtension);
+ assertNotNull(nfcOemExtension);
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
.getUiAutomation().adoptShellPermissionIdentity(NFC_SET_CONTROLLER_ALWAYS_ON);
- assumeTrue(nfcAdapter.isControllerAlwaysOnSupported());
+ assumeTrue("Device must support controller always on",
+ nfcAdapter.isControllerAlwaysOnSupported());
NfcControllerAlwaysOnListener cb = null;
CountDownLatch countDownLatch;
try {
@@ -1193,6 +1198,10 @@
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ ComponentName topComponentName = mContext.getSystemService(ActivityManager.class)
+ .getRunningTasks(1).get(0).topActivity;
+ Assert.assertEquals("Foreground activity not in the foreground",
+ NfcFCardEmulationActivity.class.getName(), topComponentName.getClassName());
return activity;
}
@@ -1236,28 +1245,29 @@
@RequiresFlagsEnabled(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE)
public void testSetTagIntentAppPreference() throws NoSuchFieldException, RemoteException {
NfcAdapter adapter = getDefaultAdapter();
- assumeTrue(adapter.isTagIntentAppPreferenceSupported());
+ assumeTrue("Device must support tag intent app preference",
+ adapter.isTagIntentAppPreferenceSupported());
int user = mContext.getUser().getIdentifier();
// Disallow package
- Assert.assertEquals(NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS,
+ assertEquals(NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS,
adapter.setTagIntentAppPreferenceForUser(
user, "android.nfc.cts", /* allow = */ false));
Map<String, Boolean> disallowMap = adapter.getTagIntentAppPreferenceForUser(user);
- Assert.assertNotNull(disallowMap);
- Assert.assertFalse(disallowMap.isEmpty());
- Assert.assertEquals(false, disallowMap.get("android.nfc.cts"));
- Assert.assertFalse(adapter.isTagIntentAllowed());
+ assertNotNull(disallowMap);
+ assertFalse(disallowMap.isEmpty());
+ assertEquals(false, disallowMap.get("android.nfc.cts"));
+ assertFalse(adapter.isTagIntentAllowed());
// Allow package
- Assert.assertEquals(NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS,
+ assertEquals(NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS,
adapter.setTagIntentAppPreferenceForUser(
user, "android.nfc.cts", /* allow = */ true));
Map<String, Boolean> allowMap = adapter.getTagIntentAppPreferenceForUser(user);
- Assert.assertNotNull(allowMap);
- Assert.assertFalse(allowMap.isEmpty());
- Assert.assertEquals(true, allowMap.get("android.nfc.cts"));
- Assert.assertTrue(adapter.isTagIntentAllowed());
+ assertNotNull(allowMap);
+ assertFalse(allowMap.isEmpty());
+ assertEquals(true, allowMap.get("android.nfc.cts"));
+ assertTrue(adapter.isTagIntentAllowed());
}
@Test
diff --git a/tests/cts/tests/src/android/nfc/cts/NfcFCardEmulationTest.java b/tests/cts/tests/src/android/nfc/cts/NfcFCardEmulationTest.java
index 43a8c3c..5711c79 100644
--- a/tests/cts/tests/src/android/nfc/cts/NfcFCardEmulationTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/NfcFCardEmulationTest.java
@@ -1,8 +1,13 @@
package android.nfc.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import android.app.Activity;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -36,13 +41,13 @@
assumeTrue("Device must support NFC type F HCE", supportsHardware());
Context mContext = InstrumentationRegistry.getContext();
mAdapter = NfcAdapter.getDefaultAdapter(mContext);
- Assert.assertNotNull("NFC Adapter is null", mAdapter);
+ assertNotNull("NFC Adapter is null", mAdapter);
}
@Test
public void getNonNullInstance() {
NfcFCardEmulation instance = NfcFCardEmulation.getInstance(mAdapter);
- Assert.assertNotNull(instance);
+ assertNotNull(instance);
}
@Test
@@ -51,23 +56,23 @@
String code = "4000";
// Register system code
- Assert.assertTrue(instance.registerSystemCodeForService(mService, code));
- Assert.assertEquals(instance.getSystemCodeForService(mService), code);
+ assertTrue(instance.registerSystemCodeForService(mService, code));
+ assertEquals(instance.getSystemCodeForService(mService), code);
// Unregister system code
- Assert.assertTrue(instance.unregisterSystemCodeForService(mService));
- Assert.assertNotEquals(instance.getSystemCodeForService(mService), code);
+ assertTrue(instance.unregisterSystemCodeForService(mService));
+ assertNotEquals(instance.getSystemCodeForService(mService), code);
// Re-register system code future tests
- Assert.assertTrue(instance.registerSystemCodeForService(mService, code));
+ assertTrue(instance.registerSystemCodeForService(mService, code));
}
@Test
public void testSetAndGetNfcid2ForService() throws RemoteException {
NfcFCardEmulation instance = getInstance();
String testNfcid2 = "02FE000000000000";
- Assert.assertTrue(instance.setNfcid2ForService(mService, testNfcid2));
- Assert.assertEquals(instance.getNfcid2ForService(mService), testNfcid2);
+ assertTrue(instance.setNfcid2ForService(mService, testNfcid2));
+ assertEquals(instance.getNfcid2ForService(mService), testNfcid2);
}
@Test
@@ -75,18 +80,21 @@
NfcFCardEmulation instance = getInstance();
Activity activity = createAndResumeActivity();
- Assert.assertTrue(instance.enableService(activity, mService));
- Assert.assertTrue(instance.disableService(activity));
+ assertTrue(instance.enableService(activity, mService));
+ assertTrue(instance.disableService(activity));
}
private Activity createAndResumeActivity() {
CardEmulationTest.ensureUnlocked();
- Intent intent
- = new Intent(ApplicationProvider.getApplicationContext(),
- NfcFCardEmulationActivity.class);
+ Context context = ApplicationProvider.getApplicationContext();
+ Intent intent = new Intent(context, NfcFCardEmulationActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ ComponentName topComponentName = context.getSystemService(ActivityManager.class)
+ .getRunningTasks(1).get(0).topActivity;
+ Assert.assertEquals("Foreground activity not in the foreground",
+ NfcFCardEmulationActivity.class.getName(), topComponentName.getClassName());
return activity;
}
diff --git a/tests/cts/tests/src/android/nfc/cts/NfcPreferredPaymentTest.java b/tests/cts/tests/src/android/nfc/cts/NfcPreferredPaymentTest.java
index 863d141..f0887b8 100644
--- a/tests/cts/tests/src/android/nfc/cts/NfcPreferredPaymentTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/NfcPreferredPaymentTest.java
@@ -73,7 +73,7 @@
@Before
public void setUp() throws Exception {
- assumeTrue(supportsHardware());
+ assumeTrue("Device must support NFC HCE", supportsHardware());
mContext = InstrumentationRegistry.getContext();
mAdapter = NfcAdapter.getDefaultAdapter(mContext);
assertNotNull(mAdapter);
diff --git a/tests/cts/tests/src/android/nfc/cts/NfcUtils.java b/tests/cts/tests/src/android/nfc/cts/NfcUtils.java
index f99b012..f773b5e 100644
--- a/tests/cts/tests/src/android/nfc/cts/NfcUtils.java
+++ b/tests/cts/tests/src/android/nfc/cts/NfcUtils.java
@@ -18,14 +18,21 @@
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+import static com.android.compatibility.common.util.PropertyUtil.getVsrApiLevel;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.util.Log;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -34,97 +41,113 @@
public final class NfcUtils {
private NfcUtils() {}
- static boolean enableNfc(NfcAdapter nfcAdapter, Context context) {
- try {
- if (nfcAdapter.isEnabled()) {
- return true;
- }
- CountDownLatch countDownLatch = new CountDownLatch(1);
- AtomicInteger state = new AtomicInteger(NfcAdapter.STATE_OFF);
- BroadcastReceiver nfcChangeListener = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int s = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
- NfcAdapter.STATE_OFF);
- if (s == NfcAdapter.STATE_TURNING_ON) {
- return;
- }
- context.unregisterReceiver(this);
- state.set(s);
- countDownLatch.countDown();
- }
- };
- HandlerThread handlerThread = new HandlerThread("nfc_cts_listener");
- handlerThread.start();
- Handler handler = new Handler(handlerThread.getLooper());
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
- context.registerReceiver(nfcChangeListener, intentFilter, null,
- handler);
- androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
- .getUiAutomation().adoptShellPermissionIdentity(WRITE_SECURE_SETTINGS);
- if (!nfcAdapter.enable()) {
- return false;
- }
- countDownLatch.await(2000, TimeUnit.MILLISECONDS);
- return state.get() == NfcAdapter.STATE_ON;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- } finally {
- androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
- .getUiAutomation().dropShellPermissionIdentity();
- }
+ private static final String TAG = "NfcUtils";
+
+ static boolean enableNfc(@NonNull NfcAdapter nfcAdapter, @NonNull Context context) {
+ return setNfcState(nfcAdapter, context, /* setEnabled= */ true, null);
}
- static boolean disableNfc(NfcAdapter nfcAdapter, Context context) {
+ static boolean disableNfc(@NonNull NfcAdapter nfcAdapter, @NonNull Context context) {
return disableNfc(nfcAdapter, context, null);
}
- static boolean disableNfc(NfcAdapter nfcAdapter, Context context, @Nullable Boolean persist) {
+ static boolean disableNfc(@NonNull NfcAdapter nfcAdapter, @NonNull Context context,
+ @Nullable Boolean persist) {
+ return setNfcState(nfcAdapter, context, /* setEnabled= */ false, persist);
+ }
+
+ private static boolean setNfcState(
+ @NonNull NfcAdapter nfcAdapter,
+ @NonNull Context context,
+ boolean setEnabled,
+ @Nullable Boolean disablePersist) {
+ if (setEnabled == nfcAdapter.isEnabled()) {
+ return true;
+ }
+ HandlerThread handlerThread = new HandlerThread("nfc_cts_listener");
+ handlerThread.start();
+ Handler handler = new Handler(handlerThread.getLooper());
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
+
+ NfcStateChangeListener nfcChangeListener = new NfcStateChangeListener(setEnabled);
try {
- if (!nfcAdapter.isEnabled()) {
- return true;
- }
- CountDownLatch countDownLatch = new CountDownLatch(1);
- AtomicInteger state = new AtomicInteger(NfcAdapter.STATE_ON);
- BroadcastReceiver nfcChangeListener = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- int s = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
- NfcAdapter.STATE_ON);
- if (s == NfcAdapter.STATE_TURNING_OFF) {
- return;
- }
- context.unregisterReceiver(this);
- state.set(s);
- countDownLatch.countDown();
+ context.registerReceiver(nfcChangeListener, intentFilter, null, handler);
+ androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(WRITE_SECURE_SETTINGS);
+
+ if (setEnabled) {
+ if (!nfcAdapter.enable()) {
+ Log.e(TAG, "Failed to enable NFC");
+ return false;
}
- };
- HandlerThread handlerThread = new HandlerThread("nfc_cts_listener");
- handlerThread.start();
- Handler handler = new Handler(handlerThread.getLooper());
- IntentFilter intentFilter = new IntentFilter();
- intentFilter.addAction(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
- context.registerReceiver(nfcChangeListener, intentFilter, null,
- handler);
- androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
- .getUiAutomation().adoptShellPermissionIdentity(WRITE_SECURE_SETTINGS);
- boolean result = false;
- if (persist != null) {
- result = nfcAdapter.disable(persist);
} else {
- result = nfcAdapter.disable();
+ if (disablePersist != null) {
+ if (!nfcAdapter.disable(disablePersist)) {
+ Log.e(TAG, "Failed to disable NFC");
+ return false;
+ }
+ } else {
+ if (!nfcAdapter.disable()) {
+ Log.e(TAG, "Failed to disable NFC");
+ return false;
+ }
+ }
}
- if (!result) return false;
- countDownLatch.await(2000, TimeUnit.MILLISECONDS);
- return state.get() == NfcAdapter.STATE_OFF;
- } catch (Exception e) {
- return false;
+
+ return nfcChangeListener.awaitStateChange();
} finally {
+ context.unregisterReceiver(nfcChangeListener);
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
- .getUiAutomation().dropShellPermissionIdentity();
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
}
}
+ private static class NfcStateChangeListener extends BroadcastReceiver {
+ private final CountDownLatch mCountDownLatch;
+ private final boolean mExpectingEnabled;
+
+ NfcStateChangeListener(boolean expectingEnabled) {
+ mCountDownLatch = new CountDownLatch(1);
+ mExpectingEnabled = expectingEnabled;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int s = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE, 0);
+
+ if ((mExpectingEnabled && s == NfcAdapter.STATE_ON)
+ || (!mExpectingEnabled && s == NfcAdapter.STATE_OFF)) {
+ mCountDownLatch.countDown();
+ }
+ }
+
+ public boolean awaitStateChange() {
+ try {
+ boolean success = mCountDownLatch.await(20, TimeUnit.SECONDS);
+
+ if (!success) {
+ Log.e( TAG, "Timeout waiting for NFC to be "
+ + (mExpectingEnabled ? "enabled" : "disabled"));
+ }
+
+ return success;
+ } catch (InterruptedException e) {
+ Log.e( TAG, "Interrupted while waiting for NFC to be "
+ + (mExpectingEnabled ? "enabled" : "disabled"));
+ return false;
+ }
+ }
+ }
+
+ public static void assumeObserveModeSupported(@NonNull NfcAdapter adapter) {
+ assumeTrue("Observe mode must be supported", adapter.isObserveModeSupported());
+ }
+
+ public static void assumeVsrApiGreaterThanUdc() {
+ assumeTrue("Device VSR API level must be greater than UDC",
+ getVsrApiLevel() > Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
+ }
}
diff --git a/tests/cts/tests/src/android/nfc/cts/OffHostApduServiceTest.java b/tests/cts/tests/src/android/nfc/cts/OffHostApduServiceTest.java
index b3b45cb..bb6d230 100644
--- a/tests/cts/tests/src/android/nfc/cts/OffHostApduServiceTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/OffHostApduServiceTest.java
@@ -1,5 +1,7 @@
package android.nfc.cts;
+import static org.junit.Assert.assertNull;
+
import android.content.Intent;
import android.os.Looper;
import org.junit.Assert;
@@ -24,6 +26,6 @@
public void testOnBind() {
Intent serviceIntent
= new Intent(CtsMyOffHostApduService.SERVICE_INTERFACE);
- Assert.assertNull(service.onBind(serviceIntent));
+ assertNull(service.onBind(serviceIntent));
}
}
diff --git a/tests/cts/tests/src/android/nfc/cts/TagLostExceptionTest.java b/tests/cts/tests/src/android/nfc/cts/TagLostExceptionTest.java
index 47c71c5..d4bd0d0 100644
--- a/tests/cts/tests/src/android/nfc/cts/TagLostExceptionTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/TagLostExceptionTest.java
@@ -1,5 +1,7 @@
package android.nfc.cts;
+import static org.junit.Assert.assertTrue;
+
import android.nfc.TagLostException;
import org.junit.Assert;
import org.junit.Test;
@@ -11,13 +13,13 @@
try {
throw new TagLostException();
} catch (TagLostException e) {
- Assert.assertTrue("TagLostException message is null", e.getMessage() == null);
+ assertTrue("TagLostException message is null", e.getMessage() == null);
}
String s = new String("testTagLostException");
try {
throw new TagLostException(s);
} catch (TagLostException e) {
- Assert.assertTrue("TagLostException message is not correct", e.getMessage().equals(s));
+ assertTrue("TagLostException message is not correct", e.getMessage().equals(s));
}
}
}
diff --git a/tests/cts/tests/src/android/nfc/cts/WalletRoleTest.java b/tests/cts/tests/src/android/nfc/cts/WalletRoleTest.java
index b285bf6..0bedf36 100644
--- a/tests/cts/tests/src/android/nfc/cts/WalletRoleTest.java
+++ b/tests/cts/tests/src/android/nfc/cts/WalletRoleTest.java
@@ -23,6 +23,9 @@
import static android.nfc.cts.WalletRoleTestUtils.clearRoleHolders;
import static android.nfc.cts.WalletRoleTestUtils.getDefaultWalletRoleHolder;
import static android.nfc.cts.WalletRoleTestUtils.getOverLayDefaultHolder;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+import static org.testng.Assert.assertEquals;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -53,7 +56,7 @@
@Before
public void setUp() {
mContext = InstrumentationRegistry.getContext();
- Assume.assumeTrue(supportsHardware());
+ assumeTrue(supportsHardware());
}
private boolean supportsHardware() {
@@ -64,15 +67,15 @@
@Test
public void testMigrationFromOverlay() {
String overlayConfig = getOverLayDefaultHolder(mContext);
- Assume.assumeNotNull(overlayConfig);
- Assume.assumeTrue(canAssignRoleToPackage(mContext, overlayConfig));
+ assumeNotNull(overlayConfig);
+ assumeTrue(canAssignRoleToPackage(mContext, overlayConfig));
runWithDefaultPaymentSetting(mContext,
null,
() -> {
clearRoleHolders(mContext);
String currentHolder = getDefaultWalletRoleHolder(mContext);
- Assert.assertEquals(currentHolder, overlayConfig);
+ assertEquals(currentHolder, overlayConfig);
});
}
@@ -84,7 +87,7 @@
clearRoleHolders(mContext);
String currentHolder = getDefaultWalletRoleHolder(mContext);
- Assert.assertEquals(currentHolder, CTS_PACKAGE_NAME);
+ assertEquals(currentHolder, CTS_PACKAGE_NAME);
});
}
diff --git a/tests/cts/tests/src/android/nfc/cts/WalletRoleTestUtils.java b/tests/cts/tests/src/android/nfc/cts/WalletRoleTestUtils.java
index 9081d7b..7990503 100644
--- a/tests/cts/tests/src/android/nfc/cts/WalletRoleTestUtils.java
+++ b/tests/cts/tests/src/android/nfc/cts/WalletRoleTestUtils.java
@@ -21,6 +21,7 @@
import static android.Manifest.permission.MANAGE_ROLE_HOLDERS;
import static android.Manifest.permission.OBSERVE_ROLE_HOLDERS;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import android.app.role.OnRoleHoldersChangedListener;
@@ -146,7 +147,7 @@
static void runWithRole(Context context, String roleHolder, Runnable runnable) {
final UserManager userManager = context.getSystemService(UserManager.class);
- assumeFalse(userManager.isHeadlessSystemUserMode());
+ assumeFalse("Device must not be headless", userManager.isHeadlessSystemUserMode());
try {
runWithRoleNone(context, () -> {}); //Remove the role holder first to trigger callbacks
RoleManager roleManager = context.getSystemService(RoleManager.class);
@@ -171,7 +172,7 @@
.getUiAutomation()
.adoptShellPermissionIdentity(
MANAGE_DEFAULT_APPLICATIONS, INTERACT_ACROSS_USERS_FULL);
- Assert.assertTrue(setDefaultWalletRoleHolder(context, roleHolder));
+ assertTrue(setDefaultWalletRoleHolder(context, roleHolder));
countDownLatch.await(4000, TimeUnit.MILLISECONDS);
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation()
.getUiAutomation().adoptShellPermissionIdentity(OBSERVE_ROLE_HOLDERS);
@@ -229,7 +230,7 @@
.getUiAutomation().adoptShellPermissionIdentity(MANAGE_ROLE_HOLDERS);
if (currentHolder != null) {
roleManager.setRoleFallbackEnabled(RoleManager.ROLE_WALLET, false);
- Assert.assertTrue(removeRoleHolder(context, currentHolder));
+ assertTrue(removeRoleHolder(context, currentHolder));
countDownLatch.await(4000, TimeUnit.MILLISECONDS);
roleManager.setRoleFallbackEnabled(RoleManager.ROLE_WALLET, true);
}