aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-12 15:44:38 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-11-12 15:44:38 +0000
commitaa86636e6bc3872aeb8ef214c2b3fbb519f6f3cd (patch)
treeb7f8b73b10a414d0bc6b8036d00e8c74b3594bb8
parente9c4c7306fd22a30d67bea2a186cc22c6d267f15 (diff)
parent8045eba07f71575f67f546599080b7482bf62a32 (diff)
downloadtelephony-android12-mainline-neuralnetworks-release.tar.gz
Snap for 7910331 from 8045eba07f71575f67f546599080b7482bf62a32 to mainline-neuralnetworks-releaseandroid-mainline-12.0.0_r92android-mainline-12.0.0_r78android-mainline-12.0.0_r50android12-mainline-neuralnetworks-release
Change-Id: If90d12bdcd9036b78021864594780170b65f5f76
-rw-r--r--OWNERS7
-rw-r--r--src/java/com/android/internal/telephony/GsmCdmaConnection.java19
-rw-r--r--src/java/com/android/internal/telephony/GsmCdmaPhone.java56
-rw-r--r--src/java/com/android/internal/telephony/MultiSimSettingController.java25
-rw-r--r--src/java/com/android/internal/telephony/NetworkTypeController.java22
-rw-r--r--src/java/com/android/internal/telephony/Phone.java41
-rw-r--r--src/java/com/android/internal/telephony/PhoneInternalInterface.java24
-rw-r--r--src/java/com/android/internal/telephony/PhoneSubInfoController.java14
-rw-r--r--src/java/com/android/internal/telephony/RadioIndication.java6
-rw-r--r--src/java/com/android/internal/telephony/SmsController.java8
-rw-r--r--src/java/com/android/internal/telephony/SubscriptionController.java39
-rw-r--r--src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java13
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/ApnContext.java4
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DataConnection.java69
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DcController.java25
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java3
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/DcTracker.java40
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/QosCallbackTracker.java18
-rw-r--r--src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java18
-rw-r--r--src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java6
-rw-r--r--src/java/com/android/internal/telephony/gsm/GsmMmiCode.java2
-rw-r--r--src/java/com/android/internal/telephony/ims/ImsResolver.java9
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhone.java35
-rwxr-xr-xsrc/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java1
-rw-r--r--src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java10
-rwxr-xr-xsrc/java/com/android/internal/telephony/sip/SipPhone.java5
-rw-r--r--src/java/com/android/internal/telephony/uicc/PinStorage.java8
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccController.java10
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccPkcs15.java2
-rw-r--r--src/java/com/android/internal/telephony/uicc/UiccProfile.java9
-rw-r--r--tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java171
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java6
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java18
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java29
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java8
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java88
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/PhysicalChannelConfigTest.java20
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java4
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java84
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java2
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java76
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java137
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java43
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/QosCallbackTrackerTest.java34
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java11
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java12
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java12
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/uicc/PinStorageTest.java44
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java161
-rw-r--r--tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java32
50 files changed, 1241 insertions, 299 deletions
diff --git a/OWNERS b/OWNERS
index 3059d4d64a..003cc3c9be 100644
--- a/OWNERS
+++ b/OWNERS
@@ -2,14 +2,15 @@ amitmahajan@google.com
breadley@google.com
fionaxu@google.com
jackyu@google.com
-hallliu@google.com
rgreenwalt@google.com
tgunn@google.com
jminjie@google.com
shuoq@google.com
-refuhoo@google.com
nazaninb@google.com
sarahchin@google.com
-dbright@google.com
xiaotonj@google.com
+huiwang@google.com
+jayachandranc@google.com
+chinmayd@google.com
+amruthr@google.com
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index e9ecb79874..b79bdef998 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -42,7 +42,7 @@ import com.android.internal.telephony.uicc.UiccCardApplication;
import com.android.telephony.Rlog;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
/**
* {@hide}
@@ -141,7 +141,10 @@ public class GsmCdmaConnection extends Connection {
mAddress = dc.number;
setEmergencyCallInfo(mOwner);
- mForwardedNumber = new ArrayList<String>(Arrays.asList(dc.forwardedNumber));
+ String forwardedNumber = TextUtils.isEmpty(dc.forwardedNumber) ? null : dc.forwardedNumber;
+ Rlog.i(LOG_TAG, "create, forwardedNumber=" + Rlog.pii(LOG_TAG, forwardedNumber));
+ mForwardedNumber = forwardedNumber == null ? null :
+ new ArrayList<>(Collections.singletonList(dc.forwardedNumber));
mIsIncoming = dc.isMT;
mCreateTime = System.currentTimeMillis();
mCnapName = dc.name;
@@ -710,11 +713,13 @@ public class GsmCdmaConnection extends Connection {
mOwner.getPhone().getVoiceCallSessionStats().onAudioCodecChanged(this, dc.audioQuality);
}
- ArrayList<String> forwardedNumber =
- new ArrayList<String>(Arrays.asList(dc.forwardedNumber));
- if (!equalsHandlesNulls(mForwardedNumber, forwardedNumber)) {
- if (Phone.DEBUG_PHONE) log("update: mForwardedNumber, # changed!");
- mForwardedNumber = forwardedNumber;
+ String forwardedNumber = TextUtils.isEmpty(dc.forwardedNumber) ? null : dc.forwardedNumber;
+ Rlog.i(LOG_TAG, "update: forwardedNumber=" + Rlog.pii(LOG_TAG, forwardedNumber));
+ ArrayList<String> forwardedNumbers = forwardedNumber == null ? null :
+ new ArrayList<>(Collections.singletonList(dc.forwardedNumber));
+ if (!equalsHandlesNulls(mForwardedNumber, forwardedNumbers)) {
+ if (Phone.DEBUG_PHONE) log("update: mForwardedNumber, # changed");
+ mForwardedNumber = forwardedNumbers;
changed = true;
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 895c21318c..a034392cee 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -126,6 +126,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -257,6 +258,7 @@ public class GsmCdmaPhone extends Phone {
private IccSmsInterfaceManager mIccSmsInterfaceManager;
private boolean mResetModemOnRadioTechnologyChange = false;
+ private boolean mSsOverCdmaSupported = false;
private int mRilVersion;
private boolean mBroadcastEmergencyCallStateChanges = false;
@@ -1325,8 +1327,8 @@ public class GsmCdmaPhone extends Phone {
}
@Override
- public Connection dial(String dialString, @NonNull DialArgs dialArgs)
- throws CallStateException {
+ public Connection dial(String dialString, @NonNull DialArgs dialArgs,
+ Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
if (!isPhoneTypeGsm() && dialArgs.uusInfo != null) {
throw new CallStateException("Sending UUS information NOT supported in CDMA!");
}
@@ -1409,6 +1411,7 @@ public class GsmCdmaPhone extends Phone {
|| useImsForEmergency) {
try {
if (DBG) logd("Trying IMS PS call");
+ chosenPhoneConsumer.accept(imsPhone);
return imsPhone.dial(dialString, dialArgs);
} catch (CallStateException e) {
if (DBG) logd("IMS PS call exception " + e +
@@ -1465,6 +1468,7 @@ public class GsmCdmaPhone extends Phone {
mCi.testingEmergencyCall();
}
+ chosenPhoneConsumer.accept(this);
return dialInternal(dialString, dialArgs);
}
@@ -2200,6 +2204,11 @@ public class GsmCdmaPhone extends Phone {
return false;
}
+ private void updateSsOverCdmaSupported(PersistableBundle b) {
+ if (b == null) return;
+ mSsOverCdmaSupported = b.getBoolean(CarrierConfigManager.KEY_SUPPORT_SS_OVER_CDMA_BOOL);
+ }
+
@Override
public boolean useSsOverIms(Message onComplete) {
boolean isUtEnabled = isUtEnabled();
@@ -2240,8 +2249,16 @@ public class GsmCdmaPhone extends Phone {
mCi.queryCallForwardStatus(commandInterfaceCFReason, serviceClass, null, resp);
}
} else {
- loge("getCallForwardingOption: not possible in CDMA, just return empty result");
- AsyncResult.forMessage(onComplete, makeEmptyCallForward(), null);
+ if (!mSsOverCdmaSupported) {
+ // If SS over CDMA is not supported and UT is not at the time, notify the user of
+ // the error and disable the option.
+ AsyncResult.forMessage(onComplete, null,
+ new CommandException(CommandException.Error.INVALID_STATE,
+ "Call Forwarding over CDMA unavailable"));
+ } else {
+ loge("getCallForwardingOption: not possible in CDMA, just return empty result");
+ AsyncResult.forMessage(onComplete, makeEmptyCallForward(), null);
+ }
onComplete.sendToTarget();
}
}
@@ -2289,7 +2306,7 @@ public class GsmCdmaPhone extends Phone {
timerSeconds,
resp);
}
- } else {
+ } else if (mSsOverCdmaSupported) {
String formatNumber = GsmCdmaConnection.formatDialString(dialingNumber);
String cfNumber = CdmaMmiCode.getCallForwardingPrefixAndNumber(
commandInterfaceCFAction, commandInterfaceCFReason, formatNumber);
@@ -2306,6 +2323,10 @@ public class GsmCdmaPhone extends Phone {
AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
onComplete.sendToTarget();
+ } else {
+ loge("setCallForwardingOption: SS over CDMA not supported, can not complete");
+ AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
+ onComplete.sendToTarget();
}
}
@@ -2429,8 +2450,17 @@ public class GsmCdmaPhone extends Phone {
//class parameter in call waiting interrogation to network
mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete);
} else {
- int arr[] = {CommandsInterface.SS_STATUS_UNKNOWN, CommandsInterface.SERVICE_CLASS_NONE};
- AsyncResult.forMessage(onComplete, arr, null);
+ if (!mSsOverCdmaSupported) {
+ // If SS over CDMA is not supported and UT is not at the time, notify the user of
+ // the error and disable the option.
+ AsyncResult.forMessage(onComplete, null,
+ new CommandException(CommandException.Error.INVALID_STATE,
+ "Call Waiting over CDMA unavailable"));
+ } else {
+ int[] arr =
+ {CommandsInterface.SS_STATUS_UNKNOWN, CommandsInterface.SERVICE_CLASS_NONE};
+ AsyncResult.forMessage(onComplete, arr, null);
+ }
onComplete.sendToTarget();
}
}
@@ -2458,7 +2488,7 @@ public class GsmCdmaPhone extends Phone {
if (isPhoneTypeGsm()) {
mCi.setCallWaiting(enable, serviceClass, onComplete);
- } else {
+ } else if (mSsOverCdmaSupported) {
String cwPrefix = CdmaMmiCode.getCallWaitingPrefix(enable);
Rlog.i(LOG_TAG, "setCallWaiting in CDMA : dial for set call waiting" + " prefix= " + cwPrefix);
@@ -2472,6 +2502,10 @@ public class GsmCdmaPhone extends Phone {
AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
onComplete.sendToTarget();
+ } else {
+ loge("setCallWaiting: SS over CDMA not supported, can not complete");
+ AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
+ onComplete.sendToTarget();
}
}
@@ -2907,8 +2941,6 @@ public class GsmCdmaPhone extends Phone {
break;
case EVENT_CARRIER_CONFIG_CHANGED:
- // Obtain new radio capabilities from the modem, since some are SIM-dependent
- mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
// Only check for the voice radio tech if it not going to be updated by the voice
// registration changes.
if (!mContext.getResources().getBoolean(
@@ -2926,8 +2958,10 @@ public class GsmCdmaPhone extends Phone {
updateCdmaRoamingSettingsAfterCarrierConfigChanged(b);
updateNrSettingsAfterCarrierConfigChanged(b);
+ updateSsOverCdmaSupported(b);
loadAllowedNetworksFromSubscriptionDatabase();
- updateAllowedNetworkTypes(null);
+ // Obtain new radio capabilities from the modem, since some are SIM-dependent
+ mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
break;
case EVENT_SET_ROAMING_PREFERENCE_DONE:
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index 26fcfd6e0b..ca5d962701 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -341,16 +341,18 @@ public class MultiSimSettingController extends Handler {
}
/**
- * Upon initialization, update defaults and mobile data enabling.
+ * Upon initialization or radio available, update defaults and mobile data enabling.
* Should only be triggered once.
*/
private void onAllSubscriptionsLoaded() {
- if (DBG) log("onAllSubscriptionsLoaded");
- mSubInfoInitialized = true;
- for (Phone phone : PhoneFactory.getPhones()) {
- phone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+ if (DBG) log("onAllSubscriptionsLoaded: mSubInfoInitialized=" + mSubInfoInitialized);
+ if (!mSubInfoInitialized) {
+ mSubInfoInitialized = true;
+ for (Phone phone : PhoneFactory.getPhones()) {
+ phone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+ }
+ reEvaluateAll();
}
- reEvaluateAll();
}
/**
@@ -445,11 +447,16 @@ public class MultiSimSettingController extends Handler {
}
/**
- * Wait for subInfo initialization (after boot up) and carrier config load for all active
- * subscriptions before re-evaluate multi SIM settings.
+ * Wait for subInfo initialization (after boot up or radio unavailable) and carrier config load
+ * for all active subscriptions before re-evaluate multi SIM settings.
*/
private boolean isReadyToReevaluate() {
- return mSubInfoInitialized && isCarrierConfigLoadedForAllSub();
+ boolean carrierConfigsLoaded = isCarrierConfigLoadedForAllSub();
+ if (DBG) {
+ log("isReadyToReevaluate: subInfoInitialized=" + mSubInfoInitialized
+ + ", carrierConfigsLoaded=" + carrierConfigsLoaded);
+ }
+ return mSubInfoInitialized && carrierConfigsLoaded;
}
private void reEvaluateAll() {
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 5d5fca0ee4..a1724a6822 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -150,6 +150,7 @@ public class NetworkTypeController extends StateMachine {
private boolean mIsPhysicalChannelConfig16Supported;
private Boolean mIsNrAdvancedAllowedByPco = false;
private int mNrAdvancedCapablePcoId = 0;
+ private boolean mIsUsingUserDataForRrcDetection = false;
/**
* NetworkTypeController constructor.
@@ -279,6 +280,13 @@ public class NetworkTypeController extends StateMachine {
CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY);
mNrAdvancedCapablePcoId = b.getInt(
CarrierConfigManager.KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT);
+ mIsUsingUserDataForRrcDetection = b.getBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
+ if (mIsPhysicalChannelConfig16Supported && mIsUsingUserDataForRrcDetection) {
+ mPhone.getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .registerForPhysicalLinkStateChanged(getHandler(),
+ EVENT_PHYSICAL_LINK_STATE_CHANGED);
+ }
}
}
createTimerRules(nrIconConfiguration, overrideTimerRule, overrideSecondaryTimerRule);
@@ -503,7 +511,7 @@ public class NetworkTypeController extends StateMachine {
// ignored
break;
case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
- if (mIsPhysicalChannelConfig16Supported) {
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
}
break;
@@ -608,7 +616,7 @@ public class NetworkTypeController extends StateMachine {
// ignored
break;
case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
- if (mIsPhysicalChannelConfig16Supported) {
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
if (mIsTimerResetEnabledForLegacyStateRRCIdle && !isPhysicalLinkActive()) {
resetAllTimers();
@@ -680,7 +688,7 @@ public class NetworkTypeController extends StateMachine {
// ignore
break;
case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
- if (mIsPhysicalChannelConfig16Supported) {
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
if (isNrNotRestricted()) {
// NOT_RESTRICTED_RRC_IDLE -> NOT_RESTRICTED_RRC_CON
@@ -764,7 +772,7 @@ public class NetworkTypeController extends StateMachine {
// ignore
break;
case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
- if (mIsPhysicalChannelConfig16Supported) {
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
if (isNrNotRestricted()) {
// NOT_RESTRICTED_RRC_CON -> NOT_RESTRICTED_RRC_IDLE
@@ -856,7 +864,7 @@ public class NetworkTypeController extends StateMachine {
break;
case EVENT_NR_FREQUENCY_CHANGED:
case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
- if (mIsPhysicalChannelConfig16Supported) {
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
mPhysicalLinkState = getPhysicalLinkStateFromPhysicalChannelConfig();
}
updateNrAdvancedState();
@@ -1188,6 +1196,10 @@ public class NetworkTypeController extends StateMachine {
}
}
+ private boolean isUsingPhysicalChannelConfigForRrcDetection() {
+ return mIsPhysicalChannelConfig16Supported && !mIsUsingUserDataForRrcDetection;
+ }
+
protected void log(String s) {
Rlog.d(TAG, "[" + mPhone.getPhoneId() + "] " + s);
}
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index ef032cd475..93a2e8e488 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -452,7 +452,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
private static final String ALLOWED_NETWORK_TYPES_TEXT_ENABLE_2G = "enable_2g";
private static final int INVALID_ALLOWED_NETWORK_TYPES = -1;
protected boolean mIsCarrierNrSupported = false;
-
+ protected boolean mIsAllowedNetworkTypesLoadedFromDb = false;
private boolean mUnitTestMode;
private CarrierPrivilegesTracker mCarrierPrivilegesTracker = null;
@@ -737,6 +737,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
break;
case EVENT_INITIATE_SILENT_REDIAL:
+ // This is an ImsPhone -> GsmCdmaPhone redial
+ // See ImsPhone#initiateSilentRedial
Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
ar = (AsyncResult) msg.obj;
if ((ar.exception == null) && (ar.result != null)) {
@@ -747,6 +749,10 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
if (TextUtils.isEmpty(dialString)) return;
try {
Connection cn = dialInternal(dialString, dialArgs);
+ // The ImsPhoneConnection that is owned by the ImsPhone is currently the
+ // one with a callback registered to TelephonyConnection. Notify the
+ // redial happened over that Phone so that it can be replaced with the
+ // new GSM/CDMA Connection.
Rlog.d(LOG_TAG, "Notify redial connection changed cn: " + cn);
if (mImsPhone != null) {
// Don't care it is null or not.
@@ -2317,6 +2323,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
String result = SubscriptionController.getInstance().getSubscriptionProperty(
getSubId(),
SubscriptionManager.ALLOWED_NETWORK_TYPES);
+ // After fw load network type from DB, do unlock if subId is valid.
+ mIsAllowedNetworkTypesLoadedFromDb = SubscriptionManager.isValidSubscriptionId(getSubId());
if (result == null) {
return;
}
@@ -2418,10 +2426,18 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
int subId = getSubId();
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypes: Invalid allowed network type reason: " + reason);
+ AsyncResult.forMessage(response, null,
+ new CommandException(CommandException.Error.INVALID_ARGUMENTS));
+ response.sendToTarget();
return;
}
- if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
- loge("setAllowedNetworkTypes: Invalid subscriptionId: " + subId);
+ if (!SubscriptionManager.isUsableSubscriptionId(subId)
+ || !mIsAllowedNetworkTypesLoadedFromDb) {
+ loge("setAllowedNetworkTypes: no sim or network type is not loaded. SubscriptionId: "
+ + subId + ", isNetworkTypeLoaded" + mIsAllowedNetworkTypesLoadedFromDb);
+ AsyncResult.forMessage(response, null,
+ new CommandException(CommandException.Error.MISSING_RESOURCE));
+ response.sendToTarget();
return;
}
String mapAsString = "";
@@ -4247,8 +4263,9 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
Phone imsPhone = mImsPhone;
if (imsPhone != null) {
imsPhone.getImsRegistrationState(callback);
+ } else {
+ callback.accept(RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
}
- callback.accept(RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
}
@@ -4371,7 +4388,9 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
public void sendSubscriptionSettings(boolean restoreNetworkSelection) {
// Send settings down
- updateAllowedNetworkTypes(null);
+ if (mIsAllowedNetworkTypesLoadedFromDb) {
+ updateAllowedNetworkTypes(null);
+ }
if (restoreNetworkSelection) {
restoreSavedNetworkSelection(null);
@@ -5024,4 +5043,16 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
private static String pii(String s) {
return Rlog.pii(LOG_TAG, s);
}
+
+ /**
+ * Used in unit tests to set whether the AllowedNetworkTypes is loaded from Db. Should not
+ * be used otherwise.
+ *
+ * @return {@code true} if the AllowedNetworkTypes is loaded from Db,
+ * {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean isAllowedNetworkTypesLoadedFromDb() {
+ return mIsAllowedNetworkTypesLoadedFromDb;
+ }
}
diff --git a/src/java/com/android/internal/telephony/PhoneInternalInterface.java b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
index a61954bcd8..437459f89e 100644
--- a/src/java/com/android/internal/telephony/PhoneInternalInterface.java
+++ b/src/java/com/android/internal/telephony/PhoneInternalInterface.java
@@ -38,6 +38,7 @@ import com.android.internal.telephony.PhoneConstants.DataState;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.function.Consumer;
/**
* Internal interface used to control the phone; SDK developers cannot
@@ -489,12 +490,33 @@ public interface PhoneInternalInterface {
*
* @param dialString The dial string.
* @param dialArgs Parameters to perform the dial with.
+ * @param chosenPhone The Phone (either GsmCdmaPhone or ImsPhone) that has been chosen to dial
+ * this number. This is used for any setup that should occur before dial
+ * actually occurs.
* @exception CallStateException if a new outgoing call is not currently
* possible because no more call slots exist or a call exists
* that is dialing, alerting, ringing, or waiting. Other
* errors are handled asynchronously.
*/
- Connection dial(String dialString, @NonNull DialArgs dialArgs) throws CallStateException;
+ Connection dial(String dialString, @NonNull DialArgs dialArgs,
+ Consumer<Phone> chosenPhone) throws CallStateException;
+
+ /**
+ * Initiate a new voice connection. This happens asynchronously, so you
+ * cannot assume the audio path is connected (or a call index has been
+ * assigned) until PhoneStateChanged notification has occurred.
+ *
+ * @param dialString The dial string.
+ * @param dialArgs Parameters to perform the dial with.
+ * @exception CallStateException if a new outgoing call is not currently
+ * possible because no more call slots exist or a call exists
+ * that is dialing, alerting, ringing, or waiting. Other
+ * errors are handled asynchronously.
+ */
+ default Connection dial(String dialString, @NonNull DialArgs dialArgs)
+ throws CallStateException {
+ return dial(dialString, dialArgs, (phone) -> {});
+ }
/**
* Initiate a new conference connection. This happens asynchronously, so you
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index 8db71d99c0..36ed749600 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -23,6 +23,7 @@ import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -35,6 +36,7 @@ import android.telephony.ImsiEncryptionInfo;
import android.telephony.PhoneNumberUtils;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
+import android.util.EventLog;
import com.android.internal.telephony.uicc.IsimRecords;
import com.android.internal.telephony.uicc.UiccCard;
@@ -48,6 +50,7 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private final Context mContext;
+ private AppOpsManager mAppOps;
public PhoneSubInfoController(Context context) {
ServiceRegisterer phoneSubServiceRegisterer = TelephonyFrameworkInitializer
@@ -56,6 +59,7 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
if (phoneSubServiceRegisterer.get() == null) {
phoneSubServiceRegisterer.register(this);
}
+ mAppOps = context.getSystemService(AppOpsManager.class);
mContext = context;
}
@@ -71,6 +75,7 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
public String getDeviceIdForPhone(int phoneId, String callingPackage,
String callingFeatureId) {
+ enforceCallingPackageUidMatched(callingPackage);
return callPhoneMethodForPhoneIdWithReadDeviceIdentifiersCheck(phoneId, callingPackage,
callingFeatureId, "getDeviceId", (phone) -> phone.getDeviceId());
}
@@ -265,6 +270,15 @@ public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
return PhoneFactory.getPhone(phoneId);
}
+ private void enforceCallingPackageUidMatched(String callingPackage) {
+ try {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ } catch (SecurityException se) {
+ EventLog.writeEvent(0x534e4554, "188677422", Binder.getCallingUid());
+ throw se;
+ }
+ }
+
private boolean enforceIccSimChallengeResponsePermission(Context context, int subId,
String callingPackage, String callingFeatureId, String message) {
if (TelephonyPermissions.checkCallingOrSelfUseIccAuthWithDeviceIdentifier(context,
diff --git a/src/java/com/android/internal/telephony/RadioIndication.java b/src/java/com/android/internal/telephony/RadioIndication.java
index 72ba991347..d18efdcb9c 100644
--- a/src/java/com/android/internal/telephony/RadioIndication.java
+++ b/src/java/com/android/internal/telephony/RadioIndication.java
@@ -1132,8 +1132,8 @@ public class RadioIndication extends IRadioIndication.Stub {
@NetworkRegistrationInfo.Domain int domain,
int causeCode, int additionalCauseCode) {
mRil.processIndication(indicationType);
-
- if (cellIdentity == null
+ CellIdentity ci = CellIdentity.create(cellIdentity);
+ if (ci == null
|| TextUtils.isEmpty(chosenPlmn)
|| (domain & NetworkRegistrationInfo.DOMAIN_CS_PS) == 0
|| (domain & ~NetworkRegistrationInfo.DOMAIN_CS_PS) != 0
@@ -1147,8 +1147,6 @@ public class RadioIndication extends IRadioIndication.Stub {
return;
}
- CellIdentity ci = CellIdentity.create(cellIdentity);
-
mRil.mRegistrationFailedRegistrant.notifyRegistrant(
new AsyncResult(
null,
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index e7feaf4cad..9f791619d8 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -515,6 +515,10 @@ public class SmsController extends ISmsImplBase {
Uri messageUri, String scAddress, PendingIntent sentIntent,
PendingIntent deliveryIntent) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
+ if (!getCallingPackage().equals(callingPkg)) {
+ throw new SecurityException("sendStoredText: Package " + callingPkg
+ + "does not belong to " + Binder.getCallingUid());
+ }
if (iccSmsIntMgr != null) {
iccSmsIntMgr.sendStoredText(callingPkg, callingAttributionTag, messageUri, scAddress,
sentIntent, deliveryIntent);
@@ -529,6 +533,10 @@ public class SmsController extends ISmsImplBase {
Uri messageUri, String scAddress, List<PendingIntent> sentIntents,
List<PendingIntent> deliveryIntents) {
IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId);
+ if (!getCallingPackage().equals(callingPkg)) {
+ throw new SecurityException("sendStoredMultipartText: Package " + callingPkg
+ + " does not belong to " + Binder.getCallingUid());
+ }
if (iccSmsIntMgr != null) {
iccSmsIntMgr.sendStoredMultipartText(callingPkg, callingAttributionTag, messageUri,
scAddress, sentIntents, deliveryIntents);
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index 39a5f51bd1..49db160450 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -905,6 +905,19 @@ public class SubscriptionController extends ISub.Stub {
@Override
public List<SubscriptionInfo> getAllSubInfoList(String callingPackage,
String callingFeatureId) {
+ return getAllSubInfoList(callingPackage, callingFeatureId, false);
+ }
+
+ /**
+ * @param callingPackage The package making the IPC.
+ * @param callingFeatureId The feature in the package
+ * @param skipConditionallyRemoveIdentifier if set, skip removing identifier conditionally
+ * @return List of all SubscriptionInfo records in database,
+ * include those that were inserted before, maybe empty but not null.
+ * @hide
+ */
+ public List<SubscriptionInfo> getAllSubInfoList(String callingPackage,
+ String callingFeatureId, boolean skipConditionallyRemoveIdentifier) {
if (VDBG) logd("[getAllSubInfoList]+");
// This API isn't public, so no need to provide a valid subscription ID - we're not worried
@@ -917,22 +930,22 @@ public class SubscriptionController extends ISub.Stub {
// Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
+ List<SubscriptionInfo> subList;
try {
- List<SubscriptionInfo> subList = null;
subList = getSubInfo(null, null);
- if (subList != null) {
- if (VDBG) logd("[getAllSubInfoList]- " + subList.size() + " infos return");
- subList.stream().map(
- subscriptionInfo -> conditionallyRemoveIdentifiers(subscriptionInfo,
- callingPackage, callingFeatureId, "getAllSubInfoList"))
- .collect(Collectors.toList());
- } else {
- if (VDBG) logd("[getAllSubInfoList]- no info return");
- }
- return subList;
} finally {
Binder.restoreCallingIdentity(identity);
}
+ if (subList != null && !skipConditionallyRemoveIdentifier) {
+ if (VDBG) logd("[getAllSubInfoList]- " + subList.size() + " infos return");
+ subList = subList.stream().map(
+ subscriptionInfo -> conditionallyRemoveIdentifiers(subscriptionInfo,
+ callingPackage, callingFeatureId, "getAllSubInfoList"))
+ .collect(Collectors.toList());
+ } else {
+ if (VDBG) logd("[getAllSubInfoList]- no info return");
+ }
+ return subList;
}
private List<SubscriptionInfo> makeCacheListCopyWithLock(List<SubscriptionInfo> cacheSubList) {
@@ -3890,8 +3903,10 @@ public class SubscriptionController extends ISub.Stub {
List<SubscriptionInfo> subInfoList;
try {
+ // need to bypass removing identifier check because that will remove the subList without
+ // group id.
subInfoList = getAllSubInfoList(mContext.getOpPackageName(),
- mContext.getAttributionTag());
+ mContext.getAttributionTag(), true);
if (groupUuid == null || subInfoList == null || subInfoList.isEmpty()) {
return new ArrayList<>();
}
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index 9132e5e2b2..36751a3389 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -419,13 +419,8 @@ public class SubscriptionInfoUpdater extends Handler {
UiccSlot uiccSlot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
String iccId = (uiccSlot != null) ? IccUtils.stripTrailingFs(uiccSlot.getIccId()) : null;
if (!TextUtils.isEmpty(iccId)) {
- // Call updateSubscriptionInfoByIccId() only if was
- // not done earlier from SIM Locked event
- if (sIccId[phoneId] == null) {
- sIccId[phoneId] = iccId;
-
- updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
- }
+ sIccId[phoneId] = iccId;
+ updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
}
cardIds.add(getCardIdFromPhoneId(phoneId));
@@ -457,10 +452,10 @@ public class SubscriptionInfoUpdater extends Handler {
// At this phase, the subscription list is accessible. Treating NOT_READY
// as equivalent to ABSENT, once the rest of the system can handle it.
sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
+ updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */);
} else {
sIccId[phoneId] = null;
}
- updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */);
broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY,
null);
@@ -792,8 +787,8 @@ public class SubscriptionInfoUpdater extends Handler {
if (DBG) logd("SubInfo Initialized");
sIsSubInfoInitialized = true;
mSubscriptionController.notifySubInfoReady();
- MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
}
+ MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
}
/**
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
index 8d7bc0657e..49eb7c5db4 100644
--- a/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnContext.java
@@ -430,9 +430,7 @@ public class ApnContext {
public void releaseNetwork(NetworkRequest networkRequest, @ReleaseNetworkType int type) {
synchronized (mRefCountLock) {
- if (mNetworkRequests.contains(networkRequest) == false) {
- logl("releaseNetwork can't find this request (" + networkRequest + ")");
- } else {
+ if (mNetworkRequests.contains(networkRequest)) {
mNetworkRequests.remove(networkRequest);
if (mDataConnection != null) {
// New network request added. Should re-evaluate properties of
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index 8a892222f2..6ddc6fec82 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -314,6 +314,10 @@ public class DataConnection extends StateMachine {
private boolean mUnmeteredOverride;
private int mRilRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
private int mDataRegState = Integer.MAX_VALUE;
+ // Indicating data connection is suspended due to temporary reasons, for example, out of
+ // service, concurrency voice/data not supported, etc.. Note this flag is only meaningful when
+ // data is in active state. When data is in inactive, connecting, or disconnecting, this flag
+ // is unmeaningful.
private boolean mIsSuspended;
private int mDownlinkBandwidth = 14;
private int mUplinkBandwidth = 14;
@@ -487,28 +491,6 @@ public class DataConnection extends StateMachine {
return new LinkProperties(mLinkProperties);
}
- boolean isSuspended() {
- // Data can only be (temporarily) suspended while data is in active state
- if (getCurrentState() != mActiveState) return false;
-
- // never set suspend for emergency apn
- if (mApnSetting != null && mApnSetting.isEmergencyApn()) {
- return false;
- }
-
- // if we are not in-service change to SUSPENDED
- if (mDataRegState != ServiceState.STATE_IN_SERVICE) {
- return true;
- }
-
- // check for voice call and concurrency issues
- if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
- return mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE;
- }
-
- return false;
- }
-
boolean isDisconnecting() {
return getCurrentState() == mDisconnectingState
|| getCurrentState() == mDisconnectingErrorCreatingConnection;
@@ -1055,6 +1037,8 @@ public class DataConnection extends StateMachine {
}
if (srcDc == null) {
+ loge("requestHandover: Cannot find source data connection.");
+ onRquestHandoverFailed(cp);
return;
}
@@ -1066,8 +1050,7 @@ public class DataConnection extends StateMachine {
mHandoverSourceNetworkAgent = srcDc.getNetworkAgent();
if (mHandoverSourceNetworkAgent == null) {
loge("requestHandover: Cannot get network agent from the source dc " + srcDc.getName());
- notifyConnectCompleted(cp, DataFailCause.UNKNOWN,
- DataCallResponse.HANDOVER_FAILURE_MODE_UNKNOWN, false);
+ onRquestHandoverFailed(cp);
return;
}
@@ -1107,7 +1090,8 @@ public class DataConnection extends StateMachine {
/**
* Called on the source data connection from the target data connection.
*/
- private void startHandover(Consumer<Integer> onTargetDcComplete) {
+ @VisibleForTesting
+ public void startHandover(Consumer<Integer> onTargetDcComplete) {
logd("startHandover: " + toStringSimple());
// Set the handover state to being transferred on "this" data connection which is the src.
setHandoverState(HANDOVER_STATE_BEING_TRANSFERRED);
@@ -1340,7 +1324,7 @@ public class DataConnection extends StateMachine {
/**
* Clear all settings called when entering mInactiveState.
*/
- private void clearSettings() {
+ private synchronized void clearSettings() {
if (DBG) log("clearSettings");
mCreateTime = -1;
@@ -1417,6 +1401,7 @@ public class DataConnection extends StateMachine {
} else if (cp.mApnContext.getApnTypeBitmask() == ApnSetting.TYPE_ENTERPRISE
&& !mDcController.isDefaultDataActive()) {
if (DBG) log("No default data connection currently active");
+ mCid = response.getId();
result = SetupResult.ERROR_NO_DEFAULT_CONNECTION;
result.mFailCause = DataFailCause.NO_DEFAULT_DATA;
} else {
@@ -2338,8 +2323,8 @@ public class DataConnection extends StateMachine {
mRilRat = drsRatPair.second;
if (DBG) {
log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"
- + " drs=" + mDataRegState
- + " mRilRat=" + mRilRat);
+ + " regState=" + ServiceState.rilServiceStateToString(mDataRegState)
+ + " RAT=" + ServiceState.rilRadioTechnologyToString(mRilRat));
}
mDataCallSessionStats.onDrsOrRatChanged(mRilRat);
break;
@@ -2422,12 +2407,28 @@ public class DataConnection extends StateMachine {
Rlog.d(getName(), "Setting suspend state without a NetworkAgent");
}
- boolean suspended = isSuspended();
- if (mIsSuspended != suspended) {
- mIsSuspended = suspended;
+ boolean newSuspendedState = false;
+ // Data can only be (temporarily) suspended while data is in active state
+ if (getCurrentState() == mActiveState) {
+ // Never set suspended for emergency apn. Emergency data connection
+ // can work while device is not in service.
+ if (mApnSetting != null && mApnSetting.isEmergencyApn()) {
+ newSuspendedState = false;
+ // If we are not in service, change to suspended.
+ } else if (mDataRegState != ServiceState.STATE_IN_SERVICE) {
+ newSuspendedState = true;
+ // Check voice/data concurrency.
+ } else if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
+ newSuspendedState = mPhone.getCallTracker().getState() != PhoneConstants.State.IDLE;
+ }
+ }
+
+ // Only notify when there is a change.
+ if (mIsSuspended != newSuspendedState) {
+ mIsSuspended = newSuspendedState;
// If data connection is active, we need to notify the new data connection state
- // changed event.
+ // changed event reflecting the latest suspended state.
if (isActive()) {
notifyDataConnectionState();
}
@@ -3829,7 +3830,7 @@ public class DataConnection extends StateMachine {
}
/** Doesn't print mApnList of ApnContext's which would be recursive */
- public String toStringSimple() {
+ public synchronized String toStringSimple() {
return getName() + ": State=" + getCurrentState().getName()
+ " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size()
+ " mCid=" + mCid + " mCreateTime=" + mCreateTime
@@ -3940,7 +3941,7 @@ public class DataConnection extends StateMachine {
return TelephonyManager.DATA_CONNECTING;
} else if (isActive()) {
// The data connection can only be suspended when it's in active state.
- if (isSuspended()) {
+ if (mIsSuspended) {
return TelephonyManager.DATA_SUSPENDED;
}
return TelephonyManager.DATA_CONNECTED;
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index 8d60477004..2156e663cd 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -29,6 +29,7 @@ import android.telephony.DataFailCause;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.dataconnection.DataConnection.UpdateLinkPropertyResult;
@@ -89,8 +90,8 @@ public class DcController extends Handler {
/**
* Aggregated physical link state from all data connections. This reflects the device's RRC
* connection state.
- * // TODO: Instead of tracking the RRC state here, we should make PhysicalChannelConfig work in
- * S.
+ * If {@link CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL} is true,
+ * then This reflects "internet data connection" instead of RRC state.
*/
private @PhysicalLinkState int mPhysicalLinkState = PHYSICAL_LINK_UNKNOWN;
@@ -229,6 +230,7 @@ public class DcController extends Handler {
boolean isAnyDataCallDormant = false;
boolean isAnyDataCallActive = false;
+ boolean isInternetDataCallActive = false;
for (DataCallResponse newState : dcsList) {
@@ -249,6 +251,11 @@ public class DcController extends Handler {
log("onDataStateChanged: Found ConnId=" + newState.getId()
+ " newState=" + newState.toString());
}
+ if (apnContexts.stream().anyMatch(
+ i -> ApnSetting.TYPE_DEFAULT_STRING.equals(i.getApnType()))
+ && newState.getLinkStatus() == DataConnActiveStatus.ACTIVE) {
+ isInternetDataCallActive = true;
+ }
if (newState.getLinkStatus() == DataConnActiveStatus.INACTIVE) {
if (mDct.isCleanupRequired.get()) {
apnsToCleanup.addAll(apnContexts);
@@ -360,8 +367,12 @@ public class DcController extends Handler {
if (mDataServiceManager.getTransportType()
== AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
- int physicalLinkState = isAnyDataCallActive
- ? PHYSICAL_LINK_ACTIVE : PHYSICAL_LINK_NOT_ACTIVE;
+ boolean isPhysicalLinkStateFocusingOnInternetData =
+ mDct.getLteEndcUsingUserDataForIdleDetection();
+ int physicalLinkState =
+ (isPhysicalLinkStateFocusingOnInternetData
+ ? isInternetDataCallActive : isAnyDataCallActive)
+ ? PHYSICAL_LINK_ACTIVE : PHYSICAL_LINK_NOT_ACTIVE;
if (mPhysicalLinkState != physicalLinkState) {
mPhysicalLinkState = physicalLinkState;
mPhysicalLinkStateChangedRegistrants.notifyResult(mPhysicalLinkState);
@@ -409,11 +420,13 @@ public class DcController extends Handler {
/**
* Register for physical link state (i.e. RRC state) changed event.
- *
+ * if {@link CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL} is true,
+ * then physical link state is focusing on "internet data connection" instead of RRC state.
* @param h The handler
* @param what The event
*/
- void registerForPhysicalLinkStateChanged(Handler h, int what) {
+ @VisibleForTesting
+ public void registerForPhysicalLinkStateChanged(Handler h, int what) {
mPhysicalLinkStateChangedRegistrants.addUnique(h, what, null);
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
index d7d7edc41f..ab04bc1302 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcNetworkAgent.java
@@ -86,7 +86,7 @@ public class DcNetworkAgent extends NetworkAgent {
public final DcKeepaliveTracker keepaliveTracker = new DcKeepaliveTracker();
- private final QosCallbackTracker mQosCallbackTracker = new QosCallbackTracker(this);
+ private final QosCallbackTracker mQosCallbackTracker;
private final Executor mQosCallbackExecutor = Executors.newSingleThreadExecutor();
@@ -119,6 +119,7 @@ public class DcNetworkAgent extends NetworkAgent {
} else {
loge("The connection does not have a valid link properties.");
}
+ mQosCallbackTracker = new QosCallbackTracker(this);
}
private @NetworkType int getNetworkType() {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 8def434c69..5bfe15bca7 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -352,6 +352,9 @@ public class DcTracker extends Handler {
private boolean mNrSaSub6Unmetered = false;
private boolean mNrNsaRoamingUnmetered = false;
+ // it effect the PhysicalLinkStateChanged
+ private boolean mLteEndcUsingUserDataForRrcDetection = false;
+
// stats per data call recovery event
private DataStallRecoveryStats mDataStallRecoveryStats;
@@ -1647,7 +1650,12 @@ public class DcTracker extends Handler {
if (DBG) log(str.toString());
apnContext.requestLog(str.toString());
if (requestType == REQUEST_TYPE_HANDOVER) {
- sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, false);
+ // If fails due to latest preference already changed back to source transport, then
+ // just fallback (will not attempt handover anymore, and will not tear down the
+ // data connection on source transport.
+ boolean fallback = dataConnectionReasons.contains(
+ DataDisallowedReasonType.ON_OTHER_TRANSPORT);
+ sendHandoverCompleteMessages(apnContext.getApnTypeBitmask(), false, fallback);
}
return;
}
@@ -2311,6 +2319,7 @@ public class DcTracker extends Handler {
// TODO: It'd be nice to only do this if the changed entrie(s)
// match the current operator.
if (DBG) log("onApnChanged: createAllApnList and cleanUpAllConnections");
+ mDataThrottler.reset();
setDefaultPreferredApnIfNeeded();
createAllApnList();
setDataProfilesAsNeeded();
@@ -2538,6 +2547,7 @@ public class DcTracker extends Handler {
if (mSimState == TelephonyManager.SIM_STATE_ABSENT) {
onSimAbsent();
} else if (mSimState == TelephonyManager.SIM_STATE_LOADED) {
+ mDataThrottler.reset();
if (mConfigReady) {
createAllApnList();
setDataProfilesAsNeeded();
@@ -3676,7 +3686,15 @@ public class DcTracker extends Handler {
if (mPreferredApn.getOperatorNumeric().equals(operator)) {
if (mPreferredApn.canSupportNetworkType(
ServiceState.rilRadioTechnologyToNetworkType(radioTech))) {
- apnList.add(mPreferredApn);
+ // Create a new instance of ApnSetting for ENTERPRISE because each
+ // DataConnection should have its own ApnSetting. ENTERPRISE uses the same
+ // APN as DEFAULT but is a separate DataConnection
+ if (ApnSetting.getApnTypesBitmaskFromString(requestedApnType)
+ == ApnSetting.TYPE_ENTERPRISE) {
+ apnList.add(ApnSetting.makeApnSetting(mPreferredApn));
+ } else {
+ apnList.add(mPreferredApn);
+ }
if (DBG) log("buildWaitingApns: X added preferred apnList=" + apnList);
return apnList;
}
@@ -3695,7 +3713,15 @@ public class DcTracker extends Handler {
if (apn.getApnSetId() == Telephony.Carriers.MATCH_ALL_APN_SET_ID
|| preferredApnSetId == apn.getApnSetId()) {
if (VDBG) log("buildWaitingApns: adding apn=" + apn);
- apnList.add(apn);
+ // Create a new instance of ApnSetting for ENTERPRISE because each
+ // DataConnection should have its own ApnSetting. ENTERPRISE uses the same
+ // APN as DEFAULT but is a separate DataConnection
+ if (ApnSetting.getApnTypesBitmaskFromString(requestedApnType)
+ == ApnSetting.TYPE_ENTERPRISE) {
+ apnList.add(ApnSetting.makeApnSetting(apn));
+ } else {
+ apnList.add(apn);
+ }
} else {
log("buildWaitingApns: APN set id " + apn.getApnSetId()
+ " does not match the preferred set id " + preferredApnSetId);
@@ -5575,13 +5601,21 @@ public class DcTracker extends Handler {
CarrierConfigManager.KEY_UNMETERED_NR_SA_SUB6_BOOL);
mNrNsaRoamingUnmetered = b.getBoolean(
CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL);
+ mLteEndcUsingUserDataForRrcDetection = b.getBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
}
}
updateLinkBandwidths(bandwidths, useLte);
}
+ public boolean getLteEndcUsingUserDataForIdleDetection() {
+ return mLteEndcUsingUserDataForRrcDetection;
+ }
+
/**
* Register for physical link state (i.e. RRC state) changed event.
+ * if {@link CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL} is true,
+ * then physical link state is focusing on "internet data connection" instead of RRC state.
*
* @param h The handler
* @param what The event
diff --git a/src/java/com/android/internal/telephony/dataconnection/QosCallbackTracker.java b/src/java/com/android/internal/telephony/dataconnection/QosCallbackTracker.java
index d1021fea28..795ed147b4 100644
--- a/src/java/com/android/internal/telephony/dataconnection/QosCallbackTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/QosCallbackTracker.java
@@ -44,7 +44,7 @@ import java.util.Map;
* {@hide}
*/
public class QosCallbackTracker {
- private static final String LOG_TAG = QosCallbackTracker.class.getSimpleName();
+ @NonNull private final String mTag;
@NonNull private final DcNetworkAgent mDcNetworkAgent;
@NonNull private final Map<Integer, QosBearerSession> mQosBearerSessions;
@@ -59,6 +59,7 @@ public class QosCallbackTracker {
mQosBearerSessions = new HashMap<>();
mCallbacksToFilter = new HashMap<>();
mDcNetworkAgent = dcNetworkAgent;
+ mTag = "QosCallbackTracker" + "-" + mDcNetworkAgent.getNetwork().getNetId();
}
/**
@@ -206,15 +207,19 @@ public class QosCallbackTracker {
for (final QosBearerFilter sessionFilter : qosBearerSession.getQosBearerFilterList()) {
if (!sessionFilter.getLocalAddresses().isEmpty()
- && !sessionFilter.getRemoteAddresses().isEmpty()) {
+ && !sessionFilter.getRemoteAddresses().isEmpty()
+ && sessionFilter.getLocalPortRange().isValid()
+ && sessionFilter.getRemotePortRange().isValid()) {
if (matchesByRemoteAndLocalAddress(sessionFilter, filter)) {
qosFilter = getFilterByPrecedence(qosFilter, sessionFilter);
}
- } else if (!sessionFilter.getRemoteAddresses().isEmpty()) {
+ } else if (!sessionFilter.getRemoteAddresses().isEmpty()
+ && sessionFilter.getRemotePortRange().isValid()) {
if (matchesByRemoteAddress(sessionFilter, filter)) {
qosFilter = getFilterByPrecedence(qosFilter, sessionFilter);
}
- } else if (!sessionFilter.getLocalAddresses().isEmpty()) {
+ } else if (!sessionFilter.getLocalAddresses().isEmpty()
+ && sessionFilter.getLocalPortRange().isValid()) {
if (matchesByLocalAddress(sessionFilter, filter)) {
qosFilter = getFilterByPrecedence(qosFilter, sessionFilter);
}
@@ -256,12 +261,15 @@ public class QosCallbackTracker {
mDcNetworkAgent.notifyQosSessionAvailable(
callbackId, session.getQosBearerSessionId(), nrQosAttr);
}
+
+ logd("sendSessionAvailable, callbackId=" + callbackId);
}
private void sendSessionLost(final int callbackId, @NonNull final QosBearerSession session) {
mDcNetworkAgent.notifyQosSessionLost(callbackId, session.getQosBearerSessionId(),
session.getQos() instanceof EpsQos ?
QosSession.TYPE_EPS_BEARER : QosSession.TYPE_NR_BEARER);
+ logd("sendSessionLost, callbackId=" + callbackId);
}
public interface IFilter {
@@ -275,6 +283,6 @@ public class QosCallbackTracker {
* @param s is string log
*/
private void logd(String s) {
- Rlog.d(LOG_TAG, s);
+ Rlog.d(mTag, s);
}
}
diff --git a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
index 2889e7aa6c..279da92b67 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
@@ -338,8 +338,16 @@ public class TelephonyNetworkFactory extends NetworkFactory {
logl("onReleaseNetworkFor " + networkRequest + " applied " + applied);
if (applied) {
- int transport = getTransportTypeFromNetworkRequest(networkRequest);
- releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL, transport);
+ // Most of the time, the network request only exists in one of the DcTracker, but in the
+ // middle of handover, the network request temporarily exists in both DcTrackers. If
+ // connectivity service releases the network request while handover is ongoing, we need
+ // to remove network requests from both DcTrackers.
+ // Note that this part will be refactored in T, where we won't even have DcTracker at
+ // all.
+ releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
}
}
@@ -442,12 +450,6 @@ public class TelephonyNetworkFactory extends NetworkFactory {
if (mNetworkRequests.containsKey(networkRequest)) {
// Update it with the target transport.
mNetworkRequests.put(networkRequest, targetTransport);
- } else {
- log("Network request was released before handover is completed. Now"
- + " we need to release this network request. "
- + networkRequest);
- releaseNetworkInternal(networkRequest, DcTracker.RELEASE_TYPE_NORMAL,
- targetTransport);
}
} else {
// If handover fails and requires to fallback, the context of target transport needs to
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 0226b072c5..fb892e4fd4 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -457,7 +457,7 @@ public class EmergencyNumberTracker extends Handler {
}
EmergencyNumber.mergeSameNumbersInEmergencyNumberList(updatedAssetEmergencyNumberList);
} catch (IOException ex) {
- loge("Cache asset emergency database failure: " + ex);
+ logw("Cache asset emergency database failure: " + ex);
} finally {
// close quietly by catching non-runtime exceptions.
if (inputStream != null) {
@@ -1143,6 +1143,10 @@ public class EmergencyNumberTracker extends Handler {
Rlog.d(TAG, str);
}
+ private static void logw(String str) {
+ Rlog.w(TAG, str);
+ }
+
private static void loge(String str) {
Rlog.e(TAG, str);
}
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index d2f0387d55..dec246836c 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -1228,7 +1228,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
onUssdFinishedError() {
if (mState == State.PENDING) {
mState = State.FAILED;
- if (mMessage.length() == 0) {
+ if (TextUtils.isEmpty(mMessage)) {
mMessage = mContext.getText(com.android.internal.R.string.mmiError);
}
Rlog.d(LOG_TAG, "onUssdFinishedError");
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index d990da494d..188e69582c 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -274,15 +274,18 @@ public class ImsResolver implements ImsServiceController.ImsServiceControllerCal
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
int slotSimState = mTelephonyManagerProxy.getSimState(mContext, slotId);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
- && slotSimState != TelephonyManager.SIM_STATE_ABSENT) {
+ && (slotSimState != TelephonyManager.SIM_STATE_ABSENT
+ && slotSimState != TelephonyManager.SIM_STATE_NOT_READY)) {
// We only care about carrier config updates that happen when a slot is known to be
- // absent or populated and the carrier config has been loaded.
+ // absent, the subscription is disabled (not ready), or populated and the carrier
+ // config has been loaded.
Log.i(TAG, "Received CCC for slot " + slotId + " and sim state "
+ slotSimState + ", ignoring.");
return;
}
- Log.i(TAG, "Received Carrier Config Changed for SlotId: " + slotId);
+ Log.i(TAG, "Received Carrier Config Changed for SlotId: " + slotId
+ + ", sim state: " + slotSimState);
mHandler.obtainMessage(HANDLER_CONFIG_CHANGED, slotId).sendToTarget();
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 028f3c2500..786bbcfea2 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -919,7 +919,9 @@ public class ImsPhone extends ImsPhoneBase {
}
@Override
- public Connection dial(String dialString, DialArgs dialArgs) throws CallStateException {
+ public Connection dial(String dialString, DialArgs dialArgs,
+ Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
+ chosenPhoneConsumer.accept(this);
return dialInternal(dialString, dialArgs, null);
}
@@ -1580,7 +1582,31 @@ public class ImsPhone extends ImsPhoneBase {
new SilentRedialParam(mLastDialString, cause, dialArgs),
null);
if (ar != null) {
- mSilentRedialRegistrants.notifyRegistrants(ar);
+ // There is a race condition that can happen in some cases:
+ // (Main thread) dial start
+ // (Binder Thread) onCallSessionFailed
+ // (Binder Thread) schedule a redial for CS on the main thread
+ // (Main Thread) dial finish
+ // (Main Thread) schedule to associate ImsPhoneConnection with
+ // GsmConnection on the main thread
+ // If scheduling the CS redial occurs before the command to schedule the
+ // ImsPhoneConnection to be associated with the GsmConnection, the CS redial will occur
+ // before GsmConnection has had callbacks to ImsPhone correctly updated. This will cause
+ // Callbacks back to GsmCdmaPhone to never be set up correctly and we will lose track of
+ // the instance.
+ // Instead, schedule this redial to happen on the main thread, so that we know dial has
+ // finished before scheduling a redial:
+ // (Main thread) dial start
+ // (Binder Thread) onCallSessionFailed -> move notify registrants to main thread
+ // (Main Thread) dial finish
+ // (Main Thread) schedule on main thread to associate ImsPhoneConnection with
+ // GsmConnection
+ // (Main Thread) schedule a redial for CS
+ mContext.getMainExecutor().execute(() -> {
+ logd("initiateSilentRedial: notifying registrants, isEmergency=" + isEmergency
+ + ", eccCategory=" + eccCategory);
+ mSilentRedialRegistrants.notifyRegistrants(ar);
+ });
}
}
@@ -1888,6 +1914,7 @@ public class ImsPhone extends ImsPhoneBase {
}
break;
case EVENT_INITIATE_VOLTE_SILENT_REDIAL: {
+ // This is a CS -> IMS redial
if (VDBG) logd("EVENT_INITIATE_VOLTE_SILENT_REDIAL");
ar = (AsyncResult) msg.obj;
if (ar.exception == null && ar.result != null) {
@@ -1900,6 +1927,10 @@ public class ImsPhone extends ImsPhoneBase {
try {
Connection cn = dial(dialString,
updateDialArgsForVolteSilentRedial(dialArgs, causeCode));
+ // The GSM/CDMA Connection that is owned by the GsmCdmaPhone is currently
+ // the one with a callback registered to TelephonyConnection. Notify the
+ // redial happened over that Phone so that it can be replaced with the
+ // new ImsPhoneConnection.
Rlog.d(LOG_TAG, "Notify volte redial connection changed cn: " + cn);
if (mDefaultPhone != null) {
// don't care it is null or not.
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 7b1f020169..f67082a3da 100755
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -2715,6 +2715,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
case ImsReasonInfo.CODE_LOCAL_CALL_DECLINE:
case ImsReasonInfo.CODE_REMOTE_CALL_DECLINE:
+ case ImsReasonInfo.CODE_REJECTED_ELSEWHERE:
// If the call has been declined locally (on this device), or on remotely (on
// another device using multiendpoint functionality), mark it as rejected.
return DisconnectCause.INCOMING_REJECTED;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 87790a3a6d..359079d560 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -346,8 +346,8 @@ public final class ImsPhoneMmiCode extends Handler implements MmiCode {
return dialString;
}
- static ImsPhoneMmiCode
- newNetworkInitiatedUssd(String ussdMessage, boolean isUssdRequest, ImsPhone phone) {
+ public static ImsPhoneMmiCode newNetworkInitiatedUssd(String ussdMessage,
+ boolean isUssdRequest, ImsPhone phone) {
ImsPhoneMmiCode ret;
ret = new ImsPhoneMmiCode(phone);
@@ -1194,12 +1194,10 @@ public final class ImsPhoneMmiCode extends Handler implements MmiCode {
*
* The radio has reset, and this is still pending
*/
-
- void
- onUssdFinishedError() {
+ public void onUssdFinishedError() {
if (mState == State.PENDING) {
mState = State.FAILED;
- if (mMessage.length() == 0) {
+ if (TextUtils.isEmpty(mMessage)) {
mMessage = mContext.getText(com.android.internal.R.string.mmiError);
}
Rlog.d(LOG_TAG, "onUssdFinishedError: mmi=" + this);
diff --git a/src/java/com/android/internal/telephony/sip/SipPhone.java b/src/java/com/android/internal/telephony/sip/SipPhone.java
index c88d01f9bb..4ac1ddf3ae 100755
--- a/src/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/src/java/com/android/internal/telephony/sip/SipPhone.java
@@ -43,6 +43,7 @@ import com.android.internal.telephony.PhoneNotifier;
import com.android.telephony.Rlog;
import java.text.ParseException;
+import java.util.function.Consumer;
import java.util.regex.Pattern;
/**
@@ -192,7 +193,9 @@ public class SipPhone extends SipPhoneBase {
}
@Override
- public Connection dial(String dialString, DialArgs dialArgs) throws CallStateException {
+ public Connection dial(String dialString, DialArgs dialArgs,
+ Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
+ chosenPhoneConsumer.accept(this);
synchronized (SipPhone.class) {
return dialInternal(dialString, dialArgs.videoState);
}
diff --git a/src/java/com/android/internal/telephony/uicc/PinStorage.java b/src/java/com/android/internal/telephony/uicc/PinStorage.java
index b348c61286..28851247c2 100644
--- a/src/java/com/android/internal/telephony/uicc/PinStorage.java
+++ b/src/java/com/android/internal/telephony/uicc/PinStorage.java
@@ -250,14 +250,14 @@ public class PinStorage extends Handler {
}
/**
- * Return the cached pin for the {@code slotId}, or an empty string if it is not available.
+ * Return the cached pin for the SIM card identified by {@code slotId} and {@code iccid}, or
+ * an empty string if it is not available.
*
* The method returns the PIN only if the state is VERIFICATION_READY. If the PIN is found,
* its state changes to AVAILABLE, so that it cannot be retrieved a second time during the
* same boot cycle. If the PIN verification fails, it will be removed after the failed attempt.
*/
- public synchronized String getPin(int slotId) {
- String iccid = getIccid(slotId);
+ public synchronized String getPin(int slotId, String iccid) {
if (!validateSlotId(slotId) || !validateIccid(iccid)) {
return "";
}
@@ -874,7 +874,7 @@ public class PinStorage extends Handler {
private void verifyPendingPin(int slotId) {
// We intentionally invoke getPin() here, as it updates the status and makes sure that
// same PIN is not used more than once
- String pin = getPin(slotId);
+ String pin = getPin(slotId, getIccid(slotId));
if (pin.isEmpty()) {
// PIN is not available for verification: return.
return;
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 36cad5f442..fb64b6a3cc 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -1103,12 +1103,16 @@ public class UiccController extends Handler {
options.toBundle());
}
- private boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) {
+ /**
+ * Check if slot status has changed from the last received one
+ */
+ @VisibleForTesting
+ public boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) {
if (sLastSlotStatus == null || sLastSlotStatus.size() != slotStatusList.size()) {
return true;
}
- for (IccSlotStatus iccSlotStatus : slotStatusList) {
- if (!sLastSlotStatus.contains(iccSlotStatus)) {
+ for (int i = 0; i < slotStatusList.size(); i++) {
+ if (!sLastSlotStatus.get(i).equals(slotStatusList.get(i))) {
return true;
}
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java b/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
index 12540672ea..9543908e71 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPkcs15.java
@@ -90,7 +90,7 @@ public class UiccPkcs15 extends Handler {
private void readBinary() {
if (mChannelId >=0 ) {
mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, 0x00, 0xB0, 0x00, 0x00, 0x00,
- mFileId, obtainMessage(EVENT_READ_BINARY_DONE));
+ "", obtainMessage(EVENT_READ_BINARY_DONE));
} else {
log("EF based");
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 6d5357f74b..9b601853f3 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -121,6 +121,7 @@ public class UiccProfile extends IccCard {
private RegistrantList mOperatorBrandOverrideRegistrants = new RegistrantList();
private final int mPhoneId;
+ private final PinStorage mPinStorage;
private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1;
private static final int EVENT_ICC_LOCKED = 2;
@@ -280,7 +281,7 @@ public class UiccProfile extends IccCard {
// An error occurred during automatic PIN verification. At this point,
// clear the cache and propagate the state.
loge("An error occurred during internal PIN verification");
- UiccController.getInstance().getPinStorage().clearPin(mPhoneId);
+ mPinStorage.clearPin(mPhoneId);
updateExternalState();
} else {
log("Internal PIN verification was successful!");
@@ -320,6 +321,7 @@ public class UiccProfile extends IccCard {
// for RadioConfig<1.2 eid is not known when the EuiccCard is constructed
((EuiccCard) mUiccCard).registerForEidReady(mHandler, EVENT_EID_READY, null);
}
+ mPinStorage = UiccController.getInstance().getPinStorage();
update(c, ci, ics);
ci.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
@@ -521,6 +523,9 @@ public class UiccProfile extends IccCard {
}
}
+ /**
+ * ICC availability/state changed. Update corresponding fields and external state if needed.
+ */
private void updateIccAvailability(boolean allAppsChanged) {
synchronized (mLock) {
UiccCardApplication newApp;
@@ -625,7 +630,7 @@ public class UiccProfile extends IccCard {
// If the PIN code is required and an available cached PIN is available, intercept
// the update of external state and perform an internal PIN verification.
if (lockedState == IccCardConstants.State.PIN_REQUIRED) {
- String pin = UiccController.getInstance().getPinStorage().getPin(mPhoneId);
+ String pin = mPinStorage.getPin(mPhoneId, mIccRecords.getFullIccId());
if (!pin.isEmpty()) {
log("PIN_REQUIRED[" + mPhoneId + "] - Cache present");
mCi.supplyIccPin(pin, mHandler.obtainMessage(EVENT_SUPPLY_ICC_PIN_DONE));
diff --git a/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java b/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java
new file mode 100644
index 0000000000..11b1d22ae6
--- /dev/null
+++ b/tests/telephonytests/src/android/telephony/ims/SipTransportImplBaseTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.os.IBinder;
+import android.telephony.ims.aidl.ISipDelegate;
+import android.telephony.ims.aidl.ISipDelegateMessageCallback;
+import android.telephony.ims.aidl.ISipDelegateStateCallback;
+import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.stub.SipDelegate;
+import android.telephony.ims.stub.SipTransportImplBase;
+import android.util.ArraySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public class SipTransportImplBaseTest {
+
+ private static final int TEST_SUB_ID = 1;
+
+ private static class TestSipTransport extends SipTransportImplBase {
+
+ private static class SipDelegateContainer {
+ public final int subId;
+ public final DelegateRequest delegateRequest;
+ public final DelegateStateCallback delegateStateCallback;
+ public final DelegateMessageCallback delegateMessageCallback;
+ public final SipDelegate sipDelegate;
+
+ SipDelegateContainer(int subId, DelegateRequest request,
+ DelegateStateCallback dc, DelegateMessageCallback mc, SipDelegate delegate) {
+ this.subId = subId;
+ delegateRequest = request;
+ delegateStateCallback = dc;
+ delegateMessageCallback = mc;
+ sipDelegate = delegate;
+ }
+ }
+
+ private final Set<SipDelegateContainer> mDelegates = new ArraySet<>();
+
+ TestSipTransport(Executor executor) {
+ super(executor);
+ }
+
+ @Override
+ public void createSipDelegate(int subscriptionId, DelegateRequest request,
+ DelegateStateCallback dc, DelegateMessageCallback mc) {
+ SipDelegate mockDelegate = mock(SipDelegate.class);
+ SipDelegateContainer container = new SipDelegateContainer(subscriptionId, request, dc,
+ mc, mockDelegate);
+ mDelegates.add(container);
+ dc.onCreated(mockDelegate, Collections.emptySet());
+ }
+
+ @Override
+ public void destroySipDelegate(SipDelegate delegate, int reason) {
+ mDelegates.removeIf(candidate -> {
+ if (delegate.equals(candidate.sipDelegate)) {
+ candidate.delegateStateCallback.onDestroyed(reason);
+ return true;
+ }
+ return false;
+ });
+ }
+
+ public boolean isTrackedDelegateSetEmpty() {
+ return mDelegates.isEmpty();
+ }
+ }
+
+ @Test
+ public void createDestroyDelegate() throws Exception {
+ // Set up the executor to simply run inline
+ TestSipTransport t = new TestSipTransport(Runnable::run);
+
+ ISipDelegateStateCallback stateCb = mock(ISipDelegateStateCallback.class);
+ IBinder stateBinder = mock(IBinder.class);
+ doReturn(stateBinder).when(stateCb).asBinder();
+ ISipDelegateMessageCallback messageCb = mock(ISipDelegateMessageCallback.class);
+
+ ISipDelegate delegate = createSipDelegate(t, stateCb, messageCb);
+ assertFalse(t.isTrackedDelegateSetEmpty());
+ ArgumentCaptor<IBinder.DeathRecipient> captor =
+ ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
+ verify(stateBinder).linkToDeath(captor.capture(), anyInt());
+ assertNotNull(captor.getValue());
+
+ destroySipDelegate(t, delegate,
+ SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP);
+ verify(stateBinder).unlinkToDeath(eq(captor.getValue()), anyInt());
+ verify(stateCb).onDestroyed(
+ eq(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_REQUESTED_BY_APP));
+ }
+
+
+ @Test
+ public void testPhoneProcessCrash() throws Exception {
+ // Set up the executor to simply run inline
+ TestSipTransport t = new TestSipTransport(Runnable::run);
+
+ ISipDelegateStateCallback stateCb = mock(ISipDelegateStateCallback.class);
+ IBinder stateBinder = mock(IBinder.class);
+ doReturn(stateBinder).when(stateCb).asBinder();
+ ISipDelegateMessageCallback messageCb = mock(ISipDelegateMessageCallback.class);
+
+ createSipDelegate(t, stateCb, messageCb);
+ assertFalse(t.isTrackedDelegateSetEmpty());
+ ArgumentCaptor<IBinder.DeathRecipient> captor =
+ ArgumentCaptor.forClass(IBinder.DeathRecipient.class);
+ verify(stateBinder).linkToDeath(captor.capture(), anyInt());
+ assertNotNull(captor.getValue());
+ IBinder.DeathRecipient recipient = captor.getValue();
+
+ // simulate phone process crash
+ recipient.binderDied(stateBinder);
+ verify(stateCb).onDestroyed(SipDelegateManager.SIP_DELEGATE_DESTROY_REASON_SERVICE_DEAD);
+ assertTrue(t.isTrackedDelegateSetEmpty());
+ }
+
+ private ISipDelegate createSipDelegate(TestSipTransport transport,
+ ISipDelegateStateCallback stateCb,
+ ISipDelegateMessageCallback messageCb) throws Exception {
+ ISipTransport transportBinder = transport.getBinder();
+ transportBinder.createSipDelegate(TEST_SUB_ID, new DelegateRequest(Collections.emptySet()),
+ stateCb, messageCb);
+ ArgumentCaptor<ISipDelegate> captor = ArgumentCaptor.forClass(ISipDelegate.class);
+ verify(stateCb).onCreated(captor.capture(), anyList());
+ assertNotNull(captor.getValue());
+ return captor.getValue();
+ }
+
+ private void destroySipDelegate(TestSipTransport transport, ISipDelegate delegate,
+ int reason) throws Exception {
+ ISipTransport transportBinder = transport.getBinder();
+ transportBinder.destroySipDelegate(delegate, reason);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index f04e69f321..14f5aa14cf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -424,6 +424,12 @@ public class ContextFixture implements TestFixture<Context> {
}
@Override
+ public void sendBroadcast(Intent intent, String receiverPermission, Bundle initialExtras) {
+ logd("sendBroadcast called for " + intent.getAction());
+ sendBroadcast(intent);
+ }
+
+ @Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
logd("sendOrderedBroadcast called for " + intent.getAction());
sendBroadcast(intent);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
index a5d0b4d790..a078642b1a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaConnectionTest.java
@@ -278,4 +278,22 @@ public class GsmCdmaConnectionTest extends TelephonyTest {
assertEquals(new ArrayList<String>(Arrays.asList(forwardedNumber)),
connection.getForwardedNumber());
}
+
+ @Test @SmallTest
+ public void testForwardedNumberEmptyNull() {
+ mDC.state = DriverCall.State.INCOMING;
+ mDC.forwardedNumber = "";
+ connection = new GsmCdmaConnection(mPhone, mDC, mCT, 0);
+ assertNull(connection.getForwardedNumber());
+ mDC.forwardedNumber = null;
+ connection.update(mDC);
+ assertNull(connection.getForwardedNumber());
+
+ mDC.forwardedNumber = null;
+ connection = new GsmCdmaConnection(mPhone, mDC, mCT, 0);
+ assertNull(connection.getForwardedNumber());
+ mDC.forwardedNumber = "";
+ connection.update(mDC);
+ assertNull(connection.getForwardedNumber());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index e56ed3e58f..2f98164b68 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -1622,4 +1622,33 @@ public class GsmCdmaPhoneTest extends TelephonyTest {
assertEquals(LinkCapacityEstimate.INVALID, lce3.getUplinkCapacityKbps());
assertEquals(LinkCapacityEstimate.LCE_TYPE_COMBINED, lce3.getType());
}
+
+ @Test
+ @SmallTest
+ public void testLoadAllowedNetworksFromSubscriptionDatabase_loadTheNullValue_isLoadedTrue() {
+ int subId = 1;
+ doReturn(subId).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
+
+ doReturn(null).when(mSubscriptionController).getSubscriptionProperty(anyInt(),
+ eq(SubscriptionManager.ALLOWED_NETWORK_TYPES));
+
+ mPhoneUT.loadAllowedNetworksFromSubscriptionDatabase();
+
+ assertEquals(true, mPhoneUT.isAllowedNetworkTypesLoadedFromDb());
+ }
+
+ @Test
+ @SmallTest
+ public void testLoadAllowedNetworksFromSubscriptionDatabase_subIdNotValid_isLoadedFalse() {
+ int subId = -1;
+ doReturn(subId).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
+
+ when(mSubscriptionController.getSubscriptionProperty(anyInt(),
+ eq(SubscriptionManager.ALLOWED_NETWORK_TYPES))).thenReturn(null);
+
+
+ mPhoneUT.loadAllowedNetworksFromSubscriptionDatabase();
+
+ assertEquals(false, mPhoneUT.isAllowedNetworkTypesLoadedFromDb());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index 2551678818..56689f4fc2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -210,6 +210,14 @@ public class MultiSimSettingControllerTest extends TelephonyTest {
mMultiSimSettingControllerUT.notifyCarrierConfigChanged(1, 2);
processAllMessages();
+ // Ensure all subscription loaded only updates state once
+ clearInvocations(mSubControllerMock);
+ mMultiSimSettingControllerUT.notifyAllSubscriptionLoaded();
+ processAllMessages();
+ verify(mSubControllerMock, never()).setDefaultDataSubId(anyInt());
+ verify(mSubControllerMock, never()).setDefaultVoiceSubId(anyInt());
+ verify(mSubControllerMock, never()).setDefaultSmsSubId(anyInt());
+
// Notify radio unavailable.
replaceInstance(BaseCommands.class, "mState", mSimulatedCommands,
TelephonyManager.RADIO_POWER_UNAVAILABLE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 1fc5d37e89..be23df8ba1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -302,6 +302,27 @@ public class NetworkTypeControllerTest extends TelephonyTest {
}
@Test
+ public void testTransitionToCurrentStateIdle_usingUserDataForRrcDetection() throws Exception {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
+ doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
+ TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
+ mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ broadcastCarrierConfigs();
+ processAllMessages();
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_PHYSICAL_LINK_STATE_CHANGED,
+ new AsyncResult(null, DcController.PHYSICAL_LINK_NOT_ACTIVE, null));
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+
+ processAllMessages();
+
+ assertEquals("not_restricted_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
public void testTransitionToCurrentStateLteConnected() throws Exception {
assertEquals("DefaultState", getCurrentState().getName());
doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
@@ -319,6 +340,7 @@ public class NetworkTypeControllerTest extends TelephonyTest {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ broadcastCarrierConfigs();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
@@ -331,6 +353,28 @@ public class NetworkTypeControllerTest extends TelephonyTest {
}
@Test
+ public void testTransitionToCurrentStateLteConnected_usingUserDataForRrcDetection()
+ throws Exception {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
+ doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
+ TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
+ mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ broadcastCarrierConfigs();
+ processAllMessages();
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_PHYSICAL_LINK_STATE_CHANGED,
+ new AsyncResult(null, DcController.PHYSICAL_LINK_ACTIVE, null));
+ mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+
+ processAllMessages();
+
+ assertEquals("not_restricted_rrc_con", getCurrentState().getName());
+ }
+
+ @Test
public void testTransitionToCurrentStateNrConnected() throws Exception {
assertEquals("DefaultState", getCurrentState().getName());
doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
@@ -564,6 +608,30 @@ public class NetworkTypeControllerTest extends TelephonyTest {
assertEquals("not_restricted_rrc_con", getCurrentState().getName());
}
+
+ @Test
+ public void testUsingUserDataForRrcDetection_FromNrConnectedMmwaveToLteConnected()
+ throws Exception {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
+ doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
+ TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
+ mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ broadcastCarrierConfigs();
+ processAllMessages();
+ testTransitionToCurrentStateNrConnectedMmwave();
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+ doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
+ mNetworkTypeController.sendMessage(EVENT_PHYSICAL_LINK_STATE_CHANGED,
+ new AsyncResult(null, DcController.PHYSICAL_LINK_ACTIVE, null));
+ mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED);
+ mNetworkTypeController.sendMessage(EVENT_NR_STATE_CHANGED);
+
+ processAllMessages();
+
+ assertEquals("not_restricted_rrc_con", getCurrentState().getName());
+ }
+
@Test
public void testEventPhysicalChannelChangeFromLteToLteCaInLegacyState() throws Exception {
testTransitionToCurrentStateLegacy();
@@ -669,6 +737,26 @@ public class NetworkTypeControllerTest extends TelephonyTest {
}
@Test
+ public void testEventPhysicalLinkStateChanged_UsingUserDataForRrcDetection()
+ throws Exception {
+ mBundle.putBoolean(
+ CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, true);
+ doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
+ TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
+ mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ broadcastCarrierConfigs();
+ processAllMessages();
+ testTransitionToCurrentStateLteConnected_usingUserDataForRrcDetection();
+ doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+ mNetworkTypeController.sendMessage(EVENT_PHYSICAL_LINK_STATE_CHANGED,
+ new AsyncResult(null, DcController.PHYSICAL_LINK_NOT_ACTIVE, null));
+
+ processAllMessages();
+
+ assertEquals("not_restricted_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
public void testEventPhysicalChannelConfigNotifChanged() throws Exception {
testTransitionToCurrentStateNrConnected();
assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhysicalChannelConfigTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhysicalChannelConfigTest.java
index 1811073f5d..853162a03b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhysicalChannelConfigTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhysicalChannelConfigTest.java
@@ -39,6 +39,7 @@ public class PhysicalChannelConfigTest {
private static final int CELL_BANDWIDTH = 12345;
private static final int FREQUENCY_RANGE = 1;
private static final int CHANNEL_NUMBER = 1234;
+ private static final int CHANNEL_NUMBER_UNKNOWN = PhysicalChannelConfig.CHANNEL_NUMBER_UNKNOWN;
private static final int[] CONTEXT_IDS = new int[] {123, 555, 1, 0};
private static final int PHYSICAL_CELL_ID = 502;
private static final int BAND = 1;
@@ -141,6 +142,25 @@ public class PhysicalChannelConfigTest {
}
@Test
+ public void testUplinkFrequencyForNrArfcnWithUnknownChannelNumber(){
+ setUpPhysicalChannelConfig(NETWORK_TYPE_NR, AccessNetworkConstants.NgranBands.BAND_1,
+ CHANNEL_NUMBER, CHANNEL_NUMBER_UNKNOWN, ServiceState.FREQUENCY_RANGE_MID);
+
+ assertThat(mPhysicalChannelConfig.getUplinkFrequencyKhz()).isEqualTo(INVALID_FREQUENCY);
+ }
+
+ @Test
+ public void testUplinkFrequencyForNrArfcn(){
+ setUpPhysicalChannelConfig(NETWORK_TYPE_NR, AccessNetworkConstants.NgranBands.BAND_1,
+ CHANNEL_NUMBER, CHANNEL_NUMBER, ServiceState.FREQUENCY_RANGE_MID);
+
+ // 3GPP TS 38.104 Table 5.4.2.1-1, {@link AccessNetworkUtils#getFrequencyFromNrArfcn}.
+ // Formula of NR-ARFCN convert to actual frequency:
+ // Actual frequency(kHz) = (RANGE_OFFSET + GLOBAL_KHZ * (ARFCN - ARFCN_OFFSET))
+ assertThat(mPhysicalChannelConfig.getUplinkFrequencyKhz()).isEqualTo(6170);
+ }
+
+ @Test
public void testBuilder() {
setUpPhysicalChannelConfig(NETWORK_TYPE_LTE, BAND, CHANNEL_NUMBER, CHANNEL_NUMBER,
FREQUENCY_RANGE);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index c92d4f9d95..1161792685 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
@@ -246,8 +246,8 @@ public class SubscriptionInfoUpdaterTest extends TelephonyTest {
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
verify(mConfigManager, never()).updateConfigForPhoneId(eq(FAKE_PHONE_ID_1),
eq(IccCardConstants.INTENT_VALUE_ICC_NOT_READY));
- verify(mSubscriptionController).clearSubInfoRecord(FAKE_PHONE_ID_1);
- verify(mSubscriptionController).notifySubscriptionInfoChanged();
+ verify(mSubscriptionController, never()).clearSubInfoRecord(FAKE_PHONE_ID_1);
+ verify(mSubscriptionController, never()).notifySubscriptionInfoChanged();
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 1d5bce64db..d14bbd0801 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -30,6 +30,7 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -273,7 +274,6 @@ public class TelephonyRegistryTest extends TelephonyTest {
assertEquals(phoneCapability, mPhoneCapability);
}
-
@Test @SmallTest
public void testActiveDataSubChanged() {
// mTelephonyRegistry.listen with notifyNow = true should trigger callback immediately.
@@ -616,9 +616,13 @@ public class TelephonyRegistryTest extends TelephonyTest {
int[] events = {TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED};
mTelephonyRegistry.listenWithEventList(2, mContext.getOpPackageName(),
mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ when(mMockConfigurationProvider.isDisplayInfoNrAdvancedSupported(
+ anyString(), any())).thenReturn(true);
+ TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
+ TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
// Notify with invalid subId on default phone. Should NOT trigger callback.
- TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(0, 0);
mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
processAllMessages();
assertEquals(null, mTelephonyDisplayInfo);
@@ -630,6 +634,82 @@ public class TelephonyRegistryTest extends TelephonyTest {
}
@Test
+ public void testDisplayInfoCompatibility() {
+ mContext.sendBroadcast(new Intent(ACTION_DEFAULT_SUBSCRIPTION_CHANGED)
+ .putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 12)
+ .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0));
+ processAllMessages();
+ int[] events = {TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED};
+ mTelephonyRegistry.listenWithEventList(2, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ when(mMockConfigurationProvider.isDisplayInfoNrAdvancedSupported(
+ anyString(), any())).thenReturn(false);
+ TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
+ TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
+ TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
+ TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE);
+
+ // Notify with invalid subId on default phone. Should NOT trigger callback.
+ mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
+ processAllMessages();
+ assertEquals(null, mTelephonyDisplayInfo);
+
+ // Notify with the matching subId on default phone. Should trigger callback.
+ mTelephonyRegistry.notifyDisplayInfoChanged(0, 2, displayInfo);
+ processAllMessages();
+ assertEquals(expectDisplayInfo, mTelephonyDisplayInfo);
+ }
+
+ @Test
+ public void testDisplayInfoCompatibility_moreCallingPackages() {
+ mContext.sendBroadcast(new Intent(ACTION_DEFAULT_SUBSCRIPTION_CHANGED)
+ .putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 12)
+ .putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0));
+ processAllMessages();
+ int[] events = {TelephonyCallback.EVENT_DISPLAY_INFO_CHANGED};
+ TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
+ TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
+ TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
+ TelephonyManager.NETWORK_TYPE_LTE,
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE);
+ TelephonyCallback telephonyCallback2 = new TelephonyCallbackWrapper() {
+ @Override
+ public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfoNotify) {
+ assertEquals(displayInfo, displayInfoNotify);
+ }
+ };
+ Executor mSimpleExecutor2 = new Executor() {
+ @Override
+ public void execute(Runnable r) {
+ r.run();
+ }
+ };
+ telephonyCallback2.init(mSimpleExecutor2);
+ mTelephonyRegistry.listenWithEventList(2, "pkg1",
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, false);
+ mTelephonyRegistry.listenWithEventList(2, "pkg2",
+ mContext.getAttributionTag(), telephonyCallback2.callback, events, false);
+ when(mMockConfigurationProvider.isDisplayInfoNrAdvancedSupported(
+ eq("pkg1"), any())).thenReturn(false);
+ when(mMockConfigurationProvider.isDisplayInfoNrAdvancedSupported(
+ eq("pkg2"), any())).thenReturn(true);
+
+
+ // Notify with invalid subId on default phone. Should NOT trigger callback.
+ mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
+ processAllMessages();
+ assertEquals(null, mTelephonyDisplayInfo);
+
+ // Notify with the matching subId on default phone. Should trigger callback.
+ mTelephonyRegistry.notifyDisplayInfoChanged(0, 2, displayInfo);
+ processAllMessages();
+ assertEquals(expectDisplayInfo, mTelephonyDisplayInfo);
+ }
+
+ @Test
public void testNotifyCellLocationForSubscriberByUserSwitched() throws RemoteException {
final int phoneId = 0;
final int subId = 1;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 7e807fa967..2242d55cb9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -456,7 +456,7 @@ public abstract class TelephonyTest {
TelephonyManager.disableServiceHandleCaching();
SubscriptionController.disableCaching();
// For testing do not allow Log.WTF as it can cause test process to crash
- Log.setWtfHandler((tagString, what, system) -> logd("WTF captured, ignoring. Tag: "
+ Log.setWtfHandler((tagString, what, system) -> Log.d(TAG, "WTF captured, ignoring. Tag: "
+ tagString + ", exception: " + what));
mPhones = new Phone[] {mPhone};
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 9562fad633..ca8abeb603 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -30,6 +30,7 @@ import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_P
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
@@ -38,6 +39,7 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -46,6 +48,7 @@ import android.net.KeepalivePacketData;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NattKeepalivePacketData;
+import android.net.Network;
import android.net.NetworkCapabilities;
import android.os.AsyncResult;
import android.os.Handler;
@@ -55,6 +58,8 @@ import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
+import android.telephony.ServiceState.RegState;
+import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataProfile;
@@ -63,6 +68,7 @@ import android.telephony.data.DataServiceCallback;
import android.telephony.data.TrafficDescriptor;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Pair;
import com.android.internal.R;
import com.android.internal.telephony.PhoneConstants;
@@ -84,6 +90,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.function.Consumer;
public class DataConnectionTest extends TelephonyTest {
private static final int DEFAULT_DC_CID = 10;
@@ -429,9 +436,9 @@ public class DataConnectionTest extends TelephonyTest {
}
private boolean isSuspended() throws Exception {
- Method method = DataConnection.class.getDeclaredMethod("isSuspended");
- method.setAccessible(true);
- return (boolean) method.invoke(mDc);
+ Field field = DataConnection.class.getDeclaredField("mIsSuspended");
+ field.setAccessible(true);
+ return field.getBoolean(mDc);
}
private SetupResult setLinkProperties(DataCallResponse response, LinkProperties linkProperties)
@@ -926,6 +933,12 @@ public class DataConnectionTest extends TelephonyTest {
assertTrue(mDc.isInactive());
}
+ private void serviceStateChangedEvent(@RegState int dataRegState, @RilRadioTechnology int rat) {
+ mDc.obtainMessage(DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED,
+ new AsyncResult(null, new Pair<>(dataRegState, rat), null)).sendToTarget();
+ waitForMs(100);
+ }
+
@Test
@SmallTest
public void testIsIpAddress() {
@@ -1281,24 +1294,56 @@ public class DataConnectionTest extends TelephonyTest {
assertTrue(mDc.isInactive());
doReturn(mApn1).when(mApnContext).getApnSetting();
doReturn(ApnSetting.TYPE_DEFAULT).when(mApnContext).getApnTypeBitmask();
+ doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed();
connectEvent(true);
+ // Before getting any service state event, the connection should not be suspended.
+ assertFalse(isSuspended());
+
// Return true if combined reg state is not in service
- doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegistrationState();
+ serviceStateChangedEvent(ServiceState.STATE_OUT_OF_SERVICE,
+ ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
assertTrue(isSuspended());
// Return false if in service and concurrent voice and data is allowed
- doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getDataRegistrationState();
- doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed();
+ serviceStateChangedEvent(ServiceState.STATE_IN_SERVICE,
+ ServiceState.RIL_RADIO_TECHNOLOGY_LTE);
assertFalse(isSuspended());
// Return false if in service and concurrent voice/data not allowed but call state is idle
doReturn(false).when(mSST).isConcurrentVoiceAndDataAllowed();
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
+ mDc.sendMessage(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED);
+ waitForMs(100);
assertFalse(isSuspended());
// Return true if in service, concurrent voice/data not allowed, and call state not idle
doReturn(PhoneConstants.State.RINGING).when(mCT).getState();
+ mDc.sendMessage(DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED);
+ waitForMs(100);
+ assertTrue(isSuspended());
+ }
+
+ @Test
+ public void testDataCreatedWhenOutOfService() throws Exception {
+ serviceStateChangedEvent(ServiceState.STATE_OUT_OF_SERVICE,
+ ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
+ ArgumentCaptor<NetworkCapabilities> ncCaptor =
+ ArgumentCaptor.forClass(NetworkCapabilities.class);
+ doReturn(mock(Network.class)).when(mConnectivityManager).registerNetworkAgent(
+ any(), any(), any(), ncCaptor.capture(), any(), any(), anyInt());
+
+ doReturn(mApn1).when(mApnContext).getApnSetting();
+ doReturn(ApnSetting.TYPE_DEFAULT).when(mApnContext).getApnTypeBitmask();
+ doReturn(true).when(mSST).isConcurrentVoiceAndDataAllowed();
+ connectEvent(true);
+ waitForMs(100);
+
+ NetworkCapabilities nc = ncCaptor.getValue();
+ // The network must be created with NOT_SUSPENDED capability.
+ assertTrue(nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED));
+
+ // But it's final state must be suspended.
assertTrue(isSuspended());
}
@@ -1316,4 +1361,23 @@ public class DataConnectionTest extends TelephonyTest {
verify(mDataThrottler).setRetryTime(eq(ApnSetting.TYPE_DEFAULT | ApnSetting.TYPE_SUPL),
eq(RetryManager.NO_SUGGESTED_RETRY_DELAY), eq(DcTracker.REQUEST_TYPE_NORMAL));
}
+
+ @Test
+ public void testDataHandoverFailed() throws Exception {
+ doReturn(mDefaultDc).when(mDcTracker).getDataConnectionByApnType(anyString());
+
+ doAnswer(invocation -> {
+ final Consumer<Integer> consumer = (Consumer<Integer>) invocation.getArguments()[0];
+ consumer.accept(DataServiceCallback.RESULT_SUCCESS);
+ return null;
+ }).when(mDefaultDc).startHandover(any(Consumer.class));
+
+ replaceInstance(ConnectionParams.class, "mRequestType", mCp,
+ DcTracker.REQUEST_TYPE_HANDOVER);
+ assertTrue(mDc.isInactive());
+ connectEvent(false);
+
+ // Make sure the data connection is still in inactive state
+ assertTrue(mDc.isInactive());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
index 3c8e7ab29c..003f74eef4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
@@ -22,7 +22,9 @@ import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_G
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_IFNAME;
import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_PCSCF_ADDRESS;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
@@ -33,7 +35,9 @@ import android.net.InetAddresses;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.os.AsyncResult;
+import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
import android.telephony.AccessNetworkConstants;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
@@ -51,6 +55,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import java.lang.reflect.Method;
@@ -63,7 +68,10 @@ import java.util.List;
public class DcControllerTest extends TelephonyTest {
private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT = 1;
+ private static final int DATA_CONNECTION_ACTIVE_PH_LINK_ACTIVE = 2;
+
private static final int EVENT_DATA_STATE_CHANGED = 0x00040007;
+ private static final int EVENT_PHYSICAL_LINK_STATE_CHANGED = 1;
@Mock
private DataConnection mDc;
@@ -71,6 +79,8 @@ public class DcControllerTest extends TelephonyTest {
private List<ApnContext> mApnContexts;
@Mock
private DataServiceManager mDataServiceManager;
+ @Mock
+ private Handler mTestHandler;
UpdateLinkPropertyResult mResult;
@@ -142,4 +152,131 @@ public class DcControllerTest extends TelephonyTest {
verify(mDcTracker, times(1)).sendStopNetStatPoll(eq(DctConstants.Activity.DORMANT));
}
+
+ @Test
+ @SmallTest
+ public void testPhysicalLinkStateChanged_defaultApnTypeAndDormant_registrantNotifyResult()
+ throws Exception {
+ ArrayList<DataCallResponse> l = new ArrayList<>();
+ DataCallResponse dcResponse = new DataCallResponse.Builder()
+ .setCause(0)
+ .setRetryDurationMillis(-1)
+ .setId(1)
+ .setLinkStatus(DATA_CONNECTION_ACTIVE_PH_LINK_DORMANT)
+ .setProtocolType(ApnSetting.PROTOCOL_IP)
+ .setInterfaceName(FAKE_IFNAME)
+ .setAddresses(Arrays.asList(
+ new LinkAddress(InetAddresses.parseNumericAddress(FAKE_ADDRESS), 0)))
+ .setDnsAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_DNS)))
+ .setGatewayAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_GATEWAY)))
+ .setPcscfAddresses(
+ Arrays.asList(InetAddresses.parseNumericAddress(FAKE_PCSCF_ADDRESS)))
+ .setMtuV4(1440)
+ .setMtuV6(1440)
+ .build();
+ l.add(dcResponse);
+ mDc.mCid = 1;
+ mDcc.addActiveDcByCid(mDc);
+ ApnContext apnContext = new ApnContext(mPhone, ApnSetting.TYPE_DEFAULT, TAG, mDcTracker, 1);
+ List<ApnContext> apnContextList = new ArrayList<>();
+ apnContextList.add(apnContext);
+ doReturn(apnContextList).when(mDc).getApnContexts();
+ doReturn(true).when(mDcTracker).getLteEndcUsingUserDataForIdleDetection();
+ mDcc.registerForPhysicalLinkStateChanged(mTestHandler, EVENT_PHYSICAL_LINK_STATE_CHANGED);
+
+ mDcc.sendMessage(mDcc.obtainMessage(EVENT_DATA_STATE_CHANGED,
+ new AsyncResult(null, l, null)));
+ processAllMessages();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mTestHandler, times(1)).sendMessageDelayed(messageCaptor.capture(), anyLong());
+ Message message = messageCaptor.getValue();
+ assertEquals(EVENT_PHYSICAL_LINK_STATE_CHANGED, message.what);
+ AsyncResult ar = (AsyncResult) message.obj;
+ assertEquals(DcController.PHYSICAL_LINK_NOT_ACTIVE, (int) ar.result);
+ }
+
+ @Test
+ @SmallTest
+ public void testPhysicalLinkStateChanged_imsApnTypeAndDormant_NoNotifyResult()
+ throws Exception {
+ testPhysicalLinkStateChanged_defaultApnTypeAndDormant_registrantNotifyResult();
+
+ ArrayList<DataCallResponse> l = new ArrayList<>();
+ DataCallResponse dcResponse = new DataCallResponse.Builder()
+ .setCause(0)
+ .setRetryDurationMillis(-1)
+ .setId(1)
+ .setLinkStatus(DATA_CONNECTION_ACTIVE_PH_LINK_ACTIVE)
+ .setProtocolType(ApnSetting.PROTOCOL_IP)
+ .setInterfaceName(FAKE_IFNAME)
+ .setAddresses(Arrays.asList(
+ new LinkAddress(InetAddresses.parseNumericAddress(FAKE_ADDRESS), 0)))
+ .setDnsAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_DNS)))
+ .setGatewayAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_GATEWAY)))
+ .setPcscfAddresses(
+ Arrays.asList(InetAddresses.parseNumericAddress(FAKE_PCSCF_ADDRESS)))
+ .setMtuV4(1440)
+ .setMtuV6(1440)
+ .build();
+ l.add(dcResponse);
+ mDc.mCid = 1;
+ mDcc.addActiveDcByCid(mDc);
+ ApnContext apnContext = new ApnContext(mPhone, ApnSetting.TYPE_IMS, TAG, mDcTracker, 1);
+ List<ApnContext> apnContextList = new ArrayList<>();
+ apnContextList.add(apnContext);
+ doReturn(apnContextList).when(mDc).getApnContexts();
+ doReturn(true).when(mDcTracker).getLteEndcUsingUserDataForIdleDetection();
+
+ mDcc.sendMessage(mDcc.obtainMessage(EVENT_DATA_STATE_CHANGED,
+ new AsyncResult(null, l, null)));
+ processAllMessages();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mTestHandler, times(1)).sendMessageDelayed(messageCaptor.capture(), anyLong());
+ }
+
+ @Test
+ @SmallTest
+ public void testPhysicalLinkStateChanged_defaultApnTypeAndStateChanged_registrantNotifyResult()
+ throws Exception {
+ testPhysicalLinkStateChanged_imsApnTypeAndDormant_NoNotifyResult();
+
+ ArrayList<DataCallResponse> l = new ArrayList<>();
+ DataCallResponse dcResponse = new DataCallResponse.Builder()
+ .setCause(0)
+ .setRetryDurationMillis(-1)
+ .setId(1)
+ .setLinkStatus(DATA_CONNECTION_ACTIVE_PH_LINK_ACTIVE)
+ .setProtocolType(ApnSetting.PROTOCOL_IP)
+ .setInterfaceName(FAKE_IFNAME)
+ .setAddresses(Arrays.asList(
+ new LinkAddress(InetAddresses.parseNumericAddress(FAKE_ADDRESS), 0)))
+ .setDnsAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_DNS)))
+ .setGatewayAddresses(Arrays.asList(InetAddresses.parseNumericAddress(FAKE_GATEWAY)))
+ .setPcscfAddresses(
+ Arrays.asList(InetAddresses.parseNumericAddress(FAKE_PCSCF_ADDRESS)))
+ .setMtuV4(1440)
+ .setMtuV6(1440)
+ .build();
+ l.add(dcResponse);
+ mDc.mCid = 1;
+ mDcc.addActiveDcByCid(mDc);
+ ApnContext apnContext = new ApnContext(mPhone, ApnSetting.TYPE_DEFAULT, TAG, mDcTracker, 1);
+ List<ApnContext> apnContextList = new ArrayList<>();
+ apnContextList.add(apnContext);
+ doReturn(apnContextList).when(mDc).getApnContexts();
+ doReturn(true).when(mDcTracker).getLteEndcUsingUserDataForIdleDetection();
+
+ mDcc.sendMessage(mDcc.obtainMessage(EVENT_DATA_STATE_CHANGED,
+ new AsyncResult(null, l, null)));
+ processAllMessages();
+
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ verify(mTestHandler, times(2)).sendMessageDelayed(messageCaptor.capture(), anyLong());
+ Message message = messageCaptor.getValue();
+ assertEquals(EVENT_PHYSICAL_LINK_STATE_CHANGED, message.what);
+ AsyncResult ar = (AsyncResult) message.obj;
+ assertEquals(DcController.PHYSICAL_LINK_ACTIVE, (int) ar.result);
+ }
} \ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 951439f6d3..89a59b412f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -58,6 +58,7 @@ import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncResult;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -2896,6 +2897,33 @@ public class DcTrackerTest extends TelephonyTest {
}
@Test
+ public void testDataUnthrottledAfterAPNChanged() throws Exception {
+ initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
+ replaceInstance(DcTracker.class, "mDataThrottler", mDct, mDataThrottler);
+
+ mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_NORMAL, null);
+ sendInitializationEvents();
+ mDct.sendMessage(mDct.obtainMessage(DctConstants.EVENT_APN_CHANGED, null));
+ waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
+
+ // Verify unthrottling
+ verify(mDataThrottler, times(2)).reset();
+ }
+
+ @Test
+ public void testDataUnthrottledOnSimStateChanged() throws Exception {
+ initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
+ replaceInstance(DcTracker.class, "mDataThrottler", mDct, mDataThrottler);
+
+ mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_NORMAL, null);
+ sendInitializationEvents();
+ sendSimStateUpdated("testDataUnthrottledOnSimStateChanged");
+
+ // Verify unthrottling
+ verify(mDataThrottler, times(2)).reset();
+ }
+
+ @Test
public void testHandlingSecondHandoverRequest() throws Exception {
initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
setUpDataConnection();
@@ -2982,4 +3010,19 @@ public class DcTrackerTest extends TelephonyTest {
// Ensure handover is not completed yet
verify(handler, never()).sendMessageDelayed(any(), anyLong());
}
+
+ @Test
+ public void testPreferenceChangedFallback() {
+ Handler handler = Mockito.mock(Handler.class);
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mTransportManager)
+ .getPreferredTransport(anyInt());
+ Message handoverCompleteMessage = Message.obtain(handler);
+ addHandoverCompleteMsg(handoverCompleteMessage, ApnSetting.TYPE_IMS);
+ initApns(ApnSetting.TYPE_IMS_STRING, new String[]{ApnSetting.TYPE_IMS_STRING});
+ mDct.enableApn(ApnSetting.TYPE_IMS, DcTracker.REQUEST_TYPE_HANDOVER,
+ handoverCompleteMessage);
+ waitForLastHandlerAction(mDcTrackerTestHandler.getThreadHandler());
+ Bundle bundle = handoverCompleteMessage.getData();
+ assertTrue(bundle.getBoolean("extra_handover_failure_fallback"));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/QosCallbackTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/QosCallbackTrackerTest.java
index e7c4db43bb..5a8b54028a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/QosCallbackTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/QosCallbackTrackerTest.java
@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -94,12 +95,16 @@ public class QosCallbackTrackerTest extends TelephonyTest {
@Mock
private DcNetworkAgent mDcNetworkAgent;
+ @Mock
+ private Network mNetwork;
private QosCallbackTracker mQosCallbackTracker;
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
+ doReturn(mNetwork).when(mDcNetworkAgent).getNetwork();
+ doReturn(100).when(mNetwork).getNetId();
mQosCallbackTracker = new QosCallbackTracker(mDcNetworkAgent);
processAllMessages();
}
@@ -452,5 +457,34 @@ public class QosCallbackTrackerTest extends TelephonyTest {
verify(mDcNetworkAgent, times(1)).notifyQosSessionLost(eq(1), eq(1234), eq(1));
verify(mDcNetworkAgent, times(1)).notifyQosSessionLost(eq(2), eq(1235), eq(1));
}
+
+ @Test
+ @SmallTest
+ public void testQosSessionWithInvalidPortRange() throws Exception {
+ // Non-matching QosBearerFilter
+ ArrayList<QosBearerFilter> qosFilters1 = new ArrayList<>();
+ qosFilters1.add(createIpv4QosFilter("155.55.55.55",
+ new QosBearerFilter.PortRange(0,0), 45));
+
+ ArrayList<QosBearerSession> qosSessions = new ArrayList<>();
+ qosSessions.add(new QosBearerSession(1234, createEpsQos(5, 6, 7, 8), qosFilters1));
+
+ // Matching QosBearerFilter
+ ArrayList<QosBearerFilter> qosFilters2 = new ArrayList<>();
+ qosFilters2.add(createIpv4QosFilter("122.22.22.22",
+ new QosBearerFilter.PortRange(-1, 1), 45));
+ qosSessions.add(new QosBearerSession(1235, createEpsQos(5, 6, 7, 8), qosFilters2));
+
+ mQosCallbackTracker.updateSessions(qosSessions);
+
+ // Add filter after updateSessions
+ Filter filter = new Filter(new InetSocketAddress(
+ InetAddresses.parseNumericAddress("122.22.22.22"), 2222));
+ mQosCallbackTracker.addFilter(1, filter);
+
+ verify(mDcNetworkAgent, never()).notifyQosSessionAvailable(eq(1),
+ eq(1235), any(EpsBearerQosSessionAttributes.class));
+
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
index 1dfd48584f..30bd8b27ff 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/TelephonyNetworkFactoryTest.java
@@ -36,7 +36,6 @@ import android.net.NetworkProvider;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.AsyncResult;
-import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -465,16 +464,6 @@ public class TelephonyNetworkFactoryTest extends TelephonyTest {
mTelephonyNetworkFactoryUT.releaseNetworkFor(mmsNetworkRequest);
processAllMessages();
- Message msg = mNetworkRequestMessageMap.get(mmsNetworkRequest);
-
- Bundle bundle = msg.getData();
- bundle.putParcelable("extra_network_request", mmsNetworkRequest);
- bundle.putBoolean("extra_success", true);
- bundle.putInt("extra_transport_type", AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- bundle.putBoolean("extra_handover_failure_fallback", false);
- h.sendMessage(msg);
- processAllMessages();
-
// Ensure the release is called one more time after the normal release
verify(mDcTracker, times(2)).releaseNetwork(any(), eq(1));
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
index 08d5b13d64..ee4f6e5a26 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.gsm;
+import static junit.framework.Assert.fail;
+
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -95,6 +97,16 @@ public class GsmMmiCodeTest extends TelephonyTest {
assertTrue(mGsmMmiCode == null);
}
+ @Test
+ public void testNoCrashOnEmptyMessage() {
+ GsmMmiCode mmi = GsmMmiCode.newNetworkInitiatedUssd(null, true, mGsmCdmaPhoneUT, null);
+ try {
+ mmi.onUssdFinishedError();
+ } catch (Exception e) {
+ fail("Shouldn't crash!!!");
+ }
+ }
+
private void setCarrierSupportsCallerIdVerticalServiceCodesCarrierConfig() {
final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index 220e7ce845..aee46b728c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.imsphone;
+import static junit.framework.Assert.fail;
+
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
@@ -101,6 +103,16 @@ public class ImsPhoneMmiCodeTest extends TelephonyTest {
assertTrue(mImsPhoneMmiCode == null);
}
+ @Test
+ public void testNoCrashOnEmptyMessage() {
+ ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+ try {
+ mmi.onUssdFinishedError();
+ } catch (Exception e) {
+ fail("Shouldn't crash!!!");
+ }
+ }
+
private void setCarrierSupportsCallerIdVerticalServiceCodesCarrierConfig() {
final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/PinStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/PinStorageTest.java
index f165a9ef4d..a26c0f905a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/PinStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/PinStorageTest.java
@@ -108,7 +108,7 @@ public class PinStorageTest extends TelephonyTest {
public void storePin_withoutReboot_pinCannotBeRetrieved() {
mPinStorage.storePin("1234", 0);
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -118,7 +118,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -130,7 +130,7 @@ public class PinStorageTest extends TelephonyTest {
mPinStorage = new PinStorage(mContext);
mPinStorage.mShortTermSecretKeyDurationMinutes = 0;
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -144,8 +144,8 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
// PIN can be retrieved only once after unattended reboot
- assertThat(mPinStorage.getPin(0)).isEqualTo("1234");
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("1234");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -164,7 +164,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
// PIN cannot be retrieved
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -181,7 +181,7 @@ public class PinStorageTest extends TelephonyTest {
moveTimeForward(60000);
processAllMessages();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
// Simulate a second unattended reboot to make sure that PIN was deleted.
result = mPinStorage.prepareUnattendedReboot();
@@ -189,7 +189,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -205,7 +205,7 @@ public class PinStorageTest extends TelephonyTest {
processAllMessages();
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -221,12 +221,12 @@ public class PinStorageTest extends TelephonyTest {
// Switch to a different ICCID in the device after the reboot
doReturn(ICCID_2).when(mPhone).getFullIccSerialNumber();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_2)).isEqualTo("");
// Switch back to the initial ICCID to make sure that PIN was deleted.
doReturn(ICCID_1).when(mPhone).getFullIccSerialNumber();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -240,7 +240,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -254,7 +254,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("5678");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("5678");
}
@Test
@@ -267,7 +267,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -280,7 +280,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -293,7 +293,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_INVALID)).isEqualTo("");
}
@Test
@@ -309,7 +309,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -328,7 +328,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -346,7 +346,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -369,7 +369,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -389,7 +389,7 @@ public class PinStorageTest extends TelephonyTest {
simulateReboot();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
@Test
@@ -409,6 +409,6 @@ public class PinStorageTest extends TelephonyTest {
mContext.sendBroadcast(intent);
processAllMessages();
- assertThat(mPinStorage.getPin(0)).isEqualTo("");
+ assertThat(mPinStorage.getPin(0, ICCID_1)).isEqualTo("");
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
index 39ec59dc63..7a16e5bf97 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccCarrierPrivilegeRulesTest.java
@@ -42,7 +42,10 @@ import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -561,9 +564,11 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
}).when(mUiccProfile).iccOpenLogicalChannel(anyString(), anyInt(), any(Message.class));
// Select files
+ AtomicReference<String> currentFileId = new AtomicReference<>();
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
+ currentFileId.set((String) invocation.getArguments()[6]);
Message message = (Message) invocation.getArguments()[7];
AsyncResult ar = new AsyncResult(null, new int[]{2}, null);
message.obj = ar;
@@ -573,85 +578,44 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
}).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xA4), eq(0x00),
eq(0x04), eq(0x02), anyString(), any(Message.class));
- // Read binary - ODF
- String odf = "A706300404025207";
+ // Read binary - since params are identical across files, we need to keep track of which
+ // file was selected most recently and give back that content.
+ Map<String, String> binaryContent =
+ new HashMap<>() {
+ {
+ // ODF
+ put("5031", "A706300404025207");
+ // DODF
+ put(
+ "5207",
+ "A1293000300F0C0D4750205345204163632043746CA1143012060A2A864886FC6B"
+ + "81480101300404024200");
+ // ACMF
+ put("4200", "301004080102030405060708300404024300");
+ // ACRF
+ put("4300", "3010A0080406FFFFFFFFFFFF300404024310");
+ // ACCF
+ put(
+ "4310",
+ "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51"
+ + "465350302204204C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EA"
+ + "FE8226079EF6F676FD1859");
+ }
+ };
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(odf));
+ IccIoResult iir =
+ new IccIoResult(0x90, 0x00,
+ IccUtils.hexStringToBytes(binaryContent.get(currentFileId.get())));
AsyncResult ar = new AsyncResult(null, iir, null);
message.obj = ar;
message.sendToTarget();
return null;
}
}).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("5031"), any(Message.class));
-
- // Read binary - DODF
- String dodf =
- "A1293000300F0C0D4750205345204163632043746CA11"
- + "43012060A2A864886FC6B81480101300404024200";
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(dodf));
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("5207"), any(Message.class));
-
- // Read binary - ACMF
- String acmf = "301004080102030405060708300404024300";
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acmf));
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("4200"), any(Message.class));
-
- // Read binary - ACRF
- String acrf = "3010A0080406FFFFFFFFFFFF300404024310";
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acrf));
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("4300"), any(Message.class));
-
- // Read binary - ACCF
- String accf =
- "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB514653503022042"
- + "04C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859";
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(accf));
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("4310"), any(Message.class));
-
+ eq(0x00), eq(0x00), eq(""), any(Message.class));
doAnswer(new Answer<Void>() {
@Override
@@ -706,9 +670,11 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
}).when(mUiccProfile).iccOpenLogicalChannel(anyString(), anyInt(), any(Message.class));
// Select files
+ AtomicReference<String> currentFileId = new AtomicReference<>();
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
+ currentFileId.set((String) invocation.getArguments()[6]);
Message message = (Message) invocation.getArguments()[7];
AsyncResult ar = new AsyncResult(null, new int[]{2}, null);
message.obj = ar;
@@ -718,52 +684,37 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
}).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xA4), eq(0x00),
eq(0x04), eq(0x02), anyString(), any(Message.class));
- // Read binary ODF failed
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, new byte[]{});
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("5031"), any(Message.class));
-
- // Read binary - ACRF
- String acrf = "3010A0080406FFFFFFFFFFFF300404024310";
+ // Read binary - since params are identical across files, we need to keep track of which
+ // file was selected most recently and give back that content.
+ Map<String, String> binaryContent =
+ new HashMap<>() {
+ {
+ // ODF fails
+ put("5031", "");
+ // ACRF
+ put("4300", "3010A0080406FFFFFFFFFFFF300404024310");
+ // ACCF
+ put(
+ "4310",
+ "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51"
+ + "465350302204204C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EA"
+ + "FE8226079EF6F676FD1859");
+ }
+ };
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acrf));
+ IccIoResult iir =
+ new IccIoResult(0x90, 0x00,
+ IccUtils.hexStringToBytes(binaryContent.get(currentFileId.get())));
AsyncResult ar = new AsyncResult(null, iir, null);
message.obj = ar;
message.sendToTarget();
return null;
}
}).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("4300"), any(Message.class));
-
- // Read binary - ACCF
- String accf =
- "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB514653503022042"
- + "04C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859";
- doAnswer(new Answer<Void>() {
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Message message = (Message) invocation.getArguments()[7];
- IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(accf));
- AsyncResult ar = new AsyncResult(null, iir, null);
- message.obj = ar;
- message.sendToTarget();
- return null;
- }
- }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
- eq(0x00), eq(0x00), eq("4310"), any(Message.class));
-
+ eq(0x00), eq(0x00), eq(""), any(Message.class));
doAnswer(new Answer<Void>() {
@Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index e518f3ec0f..a00e110f5a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -18,6 +18,7 @@ package com.android.internal.telephony.uicc;
import static junit.framework.Assert.fail;
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.assertTrue;
@@ -60,6 +61,7 @@ public class UiccControllerTest extends TelephonyTest {
private static final int ICC_CHANGED_EVENT = 0;
private static final int EVENT_GET_ICC_STATUS_DONE = 3;
private static final int EVENT_GET_SLOT_STATUS_DONE = 4;
+ private static final int EVENT_SIM_REFRESH = 8;
private static final int EVENT_EID_READY = 9;
@Mock
private Handler mMockedHandler;
@@ -73,6 +75,8 @@ public class UiccControllerTest extends TelephonyTest {
private UiccCard mMockCard;
@Mock
private EuiccCard mMockEuiccCard;
+ @Mock
+ private UiccProfile mMockProfile;
private IccCardApplicationStatus composeUiccApplicationStatus(
IccCardApplicationStatus.AppType appType,
@@ -631,4 +635,32 @@ public class UiccControllerTest extends TelephonyTest {
assertEquals(mUiccControllerUT.convertToPublicCardId(knownEidFromApdu),
mUiccControllerUT.getCardIdForDefaultEuicc());
}
+
+ @Test
+ public void testSlotStatusChanged() {
+ // simulate slot status loaded so that the UiccController sets the last slot status
+ IccSlotStatus iss1 = new IccSlotStatus();
+ iss1.setSlotState(1 /* active */);
+ iss1.eid = "eid1";
+ IccSlotStatus iss2 = new IccSlotStatus();
+ iss2.setSlotState(1 /* active */);
+ iss2.eid = "eid2";
+ ArrayList<IccSlotStatus> status = new ArrayList<IccSlotStatus>();
+ status.add(iss1);
+ status.add(iss2);
+ AsyncResult ar = new AsyncResult(null, status, null);
+ Message msg = Message.obtain(mUiccControllerUT, EVENT_GET_SLOT_STATUS_DONE, ar);
+ mUiccControllerUT.handleMessage(msg);
+ processAllMessages();
+
+ assertFalse(mUiccControllerUT.slotStatusChanged(status));
+
+ // change the order of the IccSlotStatus in the list
+ status = new ArrayList<>();
+ status.add(iss2);
+ status.add(iss1);
+
+ // status should be treated different from last status
+ assertTrue(mUiccControllerUT.slotStatusChanged(status));
+ }
}