Merge "Introduce aconfig flag to guard Reset mobile network feature" into main
diff --git a/flags/network.aconfig b/flags/network.aconfig
index c3f33b4..ec12aab 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -27,3 +27,10 @@
description: "Used in the Preferred Network Types menu to determine if the 3G option is displayed."
bug: "310639009"
}
+
+flag {
+ name: "support_nr_sa_rrc_idle"
+ namespace: "telephony"
+ description: "Support RRC idle for NR SA."
+ bug: "301467052"
+}
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index 945b640..e8a0566 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -108,7 +108,7 @@
TelephonyManager.NETWORK_TYPE_UNKNOWN,
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
false);
- mNetworkTypeController = new NetworkTypeController(phone, this);
+ mNetworkTypeController = new NetworkTypeController(phone, this, featureFlags);
// EVENT_UPDATE will transition from DefaultState to the current state
// and update the TelephonyDisplayInfo based on the current state.
mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index e6fb84e..ea7a6de 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -41,6 +41,7 @@
import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
import com.android.internal.telephony.data.DataUtils;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.IState;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
@@ -74,6 +75,7 @@
private static final String ICON_5G = "5g";
private static final String ICON_5G_PLUS = "5g_plus";
private static final String STATE_CONNECTED_NR_ADVANCED = "connected_mmwave";
+ private static final String STATE_CONNECTED_RRC_IDLE = "connected_rrc_idle";
private static final String STATE_CONNECTED = "connected";
private static final String STATE_NOT_RESTRICTED_RRC_IDLE = "not_restricted_rrc_idle";
private static final String STATE_NOT_RESTRICTED_RRC_CON = "not_restricted_rrc_con";
@@ -81,8 +83,8 @@
private static final String STATE_ANY = "any";
private static final String STATE_LEGACY = "legacy";
private static final String[] ALL_STATES = {STATE_CONNECTED_NR_ADVANCED, STATE_CONNECTED,
- STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON, STATE_RESTRICTED,
- STATE_LEGACY };
+ STATE_CONNECTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_IDLE, STATE_NOT_RESTRICTED_RRC_CON,
+ STATE_RESTRICTED, STATE_LEGACY };
/** Stop all timers and go to current state. */
public static final int EVENT_UPDATE = 0;
@@ -131,6 +133,7 @@
@NonNull private final Phone mPhone;
@NonNull private final DisplayInfoController mDisplayInfoController;
+ @NonNull private final FeatureFlags mFeatureFlags;
@NonNull private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -177,6 +180,7 @@
private boolean mIsUsingUserDataForRrcDetection = false;
private boolean mEnableNrAdvancedWhileRoaming = true;
private boolean mIsDeviceIdleMode = false;
+ private boolean mPrimaryCellChangedWhileIdle = false;
@Nullable private DataNetworkControllerCallback mNrAdvancedCapableByPcoChangedCallback = null;
@Nullable private DataNetworkControllerCallback mNrPhysicalLinkStatusChangedCallback = null;
@@ -189,16 +193,20 @@
@NonNull private Set<Integer> mRatchetedNrBands = new HashSet<>();
private int mRatchetedNrBandwidths = 0;
private int mLastAnchorNrCellId = PhysicalChannelConfig.PHYSICAL_CELL_ID_UNKNOWN;
+ private boolean mDoesPccListIndicateIdle = false;
/**
* NetworkTypeController constructor.
*
* @param phone Phone object.
* @param displayInfoController DisplayInfoController to send override network types to.
+ * @param featureFlags FeatureFlags controlling what icon features are enabled.
*/
- public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController) {
+ public NetworkTypeController(Phone phone, DisplayInfoController displayInfoController,
+ FeatureFlags featureFlags) {
super(TAG, displayInfoController);
mPhone = phone;
+ mFeatureFlags = featureFlags;
mDisplayInfoController = displayInfoController;
mOverrideNetworkType = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
mIsPhysicalChannelConfigOn = true;
@@ -210,6 +218,7 @@
addState(mLegacyState, defaultState);
addState(mIdleState, defaultState);
addState(mLteConnectedState, defaultState);
+ addState(mNrIdleState, defaultState);
addState(mNrConnectedState, defaultState);
addState(mNrConnectedAdvancedState, defaultState);
setInitialState(defaultState);
@@ -370,6 +379,9 @@
if (DBG) loge("Invalid 5G icon configuration, config = " + pair);
continue;
}
+ if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
int icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
if (kv[1].equals(ICON_5G)) {
icon = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
@@ -397,6 +409,9 @@
if (DBG) loge("Invalid 5G icon timer configuration, config = " + triple);
continue;
}
+ if (!mFeatureFlags.supportNrSaRrcIdle() && kv[0].equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
int duration;
try {
duration = Integer.parseInt(kv[2]);
@@ -405,6 +420,10 @@
}
if (kv[0].equals(STATE_ANY)) {
for (String state : ALL_STATES) {
+ if (!mFeatureFlags.supportNrSaRrcIdle()
+ && state.equals(STATE_CONNECTED_RRC_IDLE)) {
+ continue;
+ }
OverrideTimerRule node = tempRules.get(state);
node.addTimer(kv[1], duration);
}
@@ -425,6 +444,9 @@
}
continue;
}
+ if (kv[0].equals(STATE_CONNECTED_RRC_IDLE) && !mFeatureFlags.supportNrSaRrcIdle()) {
+ continue;
+ }
int duration;
try {
duration = Integer.parseInt(kv[2]);
@@ -433,6 +455,10 @@
}
if (kv[0].equals(STATE_ANY)) {
for (String state : ALL_STATES) {
+ if (state.equals(STATE_CONNECTED_RRC_IDLE)
+ && !mFeatureFlags.supportNrSaRrcIdle()) {
+ continue;
+ }
OverrideTimerRule node = tempRules.get(state);
node.addSecondaryTimer(kv[1], duration);
}
@@ -443,6 +469,23 @@
}
}
+ // TODO: Remove this workaround to make STATE_CONNECTED_RRC_IDLE backwards compatible with
+ // STATE_CONNECTED once carrier configs are updated.
+ if (mFeatureFlags.supportNrSaRrcIdle()) {
+ OverrideTimerRule nrRules = tempRules.get(STATE_CONNECTED);
+ if (!tempRules.get(STATE_CONNECTED_RRC_IDLE).isDefined() && nrRules.isDefined()) {
+ OverrideTimerRule nrIdleRules =
+ new OverrideTimerRule(STATE_CONNECTED_RRC_IDLE, nrRules.mOverrideType);
+ for (Map.Entry<String, Integer> entry : nrIdleRules.mPrimaryTimers.entrySet()) {
+ nrIdleRules.addTimer(entry.getKey(), entry.getValue());
+ }
+ for (Map.Entry<String, Integer> entry : nrIdleRules.mSecondaryTimers.entrySet()) {
+ nrIdleRules.addSecondaryTimer(entry.getKey(), entry.getValue());
+ }
+ tempRules.put(STATE_CONNECTED_RRC_IDLE, nrIdleRules);
+ }
+ }
+
mOverrideTimerRules = tempRules;
if (DBG) log("mOverrideTimerRules: " + mOverrideTimerRules);
}
@@ -688,7 +731,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (isLte(rat) && isNrNotRestricted()) {
transitionWithTimerTo(isPhysicalLinkActive()
@@ -768,7 +813,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (!isLte(rat) || !isNrNotRestricted()) {
transitionWithTimerTo(mLegacyState);
@@ -850,7 +897,9 @@
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
} else {
- transitionTo(mNrConnectedState);
+ transitionTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (!isLte(rat) || !isNrNotRestricted()) {
transitionWithTimerTo(mLegacyState);
@@ -903,6 +952,84 @@
private final LteConnectedState mLteConnectedState = new LteConnectedState();
/**
+ * Device is connected to 5G NR as the primary or secondary cell but not actively using data.
+ */
+ private final class NrIdleState extends State {
+ @Override
+ public void enter() {
+ if (DBG) log("Entering NrIdleState");
+ updateTimers();
+ updateOverrideNetworkType();
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("NrIdleState: process " + getEventName(msg.what));
+ updateTimers();
+ switch (msg.what) {
+ case EVENT_SERVICE_STATE_CHANGED:
+ mServiceState = mPhone.getServiceStateTracker().getServiceState();
+ if (DBG) log("ServiceState updated: " + mServiceState);
+ // fallthrough
+ case EVENT_UPDATE:
+ int rat = getDataNetworkType();
+ if (rat == TelephonyManager.NETWORK_TYPE_NR
+ || (isLte(rat) && isNrConnected())) {
+ if (isNrAdvanced()) {
+ transitionTo(mNrConnectedAdvancedState);
+ } else if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ } else {
+ // Update in case the override network type changed
+ updateOverrideNetworkType();
+ }
+ } else if (isLte(rat) && isNrNotRestricted()) {
+ transitionWithTimerTo(isPhysicalLinkActive()
+ ? mLteConnectedState : mIdleState);
+ } else {
+ transitionWithTimerTo(mLegacyState);
+ }
+ break;
+ case EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED:
+ updatePhysicalChannelConfigs();
+ if (isUsingPhysicalChannelConfigForRrcDetection()) {
+ mPhysicalLinkStatus = getPhysicalLinkStatusFromPhysicalChannelConfig();
+ }
+ // Check NR advanced in case NR advanced bands were added
+ if (isNrAdvanced()) {
+ transitionTo(mNrConnectedAdvancedState);
+ } else if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ }
+ break;
+ case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mPhysicalLinkStatus = (int) ar.result;
+ if (isPhysicalLinkActive()) {
+ transitionWithTimerTo(mNrConnectedState);
+ }
+ break;
+ default:
+ return NOT_HANDLED;
+ }
+ if (!mIsPrimaryTimerActive && !mIsSecondaryTimerActive) {
+ mPreviousState = getName();
+ }
+ return HANDLED;
+ }
+
+ @Override
+ public String getName() {
+ return mFeatureFlags.supportNrSaRrcIdle() ? STATE_CONNECTED_RRC_IDLE : STATE_CONNECTED;
+ }
+ }
+
+ private final NrIdleState mNrIdleState = new NrIdleState();
+
+ /**
* Device is connected to 5G NR as the primary or secondary cell.
*/
private final class NrConnectedState extends State {
@@ -931,6 +1058,8 @@
|| (isLte(rat) && isNrConnected())) {
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
+ } else if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
} else {
// Update in case the override network type changed
updateOverrideNetworkType();
@@ -950,11 +1079,16 @@
// Check NR advanced in case NR advanced bands were added
if (isNrAdvanced()) {
transitionTo(mNrConnectedAdvancedState);
+ } else if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
}
break;
case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
AsyncResult ar = (AsyncResult) msg.obj;
mPhysicalLinkStatus = (int) ar.result;
+ if (!isPhysicalLinkActive() && mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionWithTimerTo(mNrIdleState);
+ }
break;
default:
return NOT_HANDLED;
@@ -1012,7 +1146,9 @@
mOverrideNetworkType =
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE;
}
- transitionWithTimerTo(mNrConnectedState);
+ transitionWithTimerTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
} else if (isLte(rat) && isNrNotRestricted()) {
transitionWithTimerTo(isPhysicalLinkActive()
@@ -1028,7 +1164,9 @@
}
// Check NR advanced in case NR advanced bands were removed
if (!isNrAdvanced()) {
- transitionWithTimerTo(mNrConnectedState);
+ transitionWithTimerTo(isPhysicalLinkActive()
+ || !mFeatureFlags.supportNrSaRrcIdle()
+ ? mNrConnectedState : mNrIdleState);
}
break;
case EVENT_PHYSICAL_LINK_STATUS_CHANGED:
@@ -1060,7 +1198,9 @@
if (isPccListEmpty && isUsingPhysicalChannelConfigForRrcDetection()) {
log("Physical channel configs updated: not updating PCC fields for empty PCC list "
+ "indicating RRC idle.");
+ mPrimaryCellChangedWhileIdle = false;
mPhysicalChannelConfigs = physicalChannelConfigs;
+ mDoesPccListIndicateIdle = true;
return;
}
@@ -1107,6 +1247,16 @@
mRatchetedNrBandwidths = Math.max(mRatchetedNrBandwidths, nrBandwidths);
mRatchetedNrBands.addAll(nrBands);
} else {
+ if (mFeatureFlags.supportNrSaRrcIdle() && mDoesPccListIndicateIdle
+ && isUsingPhysicalChannelConfigForRrcDetection()
+ && !mPrimaryCellChangedWhileIdle && isTimerActiveForNrSaRrcIdle()
+ && !isNrAdvancedForPccFields(nrBandwidths, nrBands)) {
+ log("Allow primary cell change during RRC idle timer without changing state: "
+ + mLastAnchorNrCellId + " -> " + anchorNrCellId);
+ mPrimaryCellChangedWhileIdle = true;
+ mLastAnchorNrCellId = anchorNrCellId;
+ return;
+ }
if (mRatchetPccFieldsForSameAnchorNrCell) {
log("Not ratcheting physical channel config fields since anchor NR cell changed: "
+ mLastAnchorNrCellId + " -> " + anchorNrCellId);
@@ -1117,6 +1267,7 @@
mLastAnchorNrCellId = anchorNrCellId;
mPhysicalChannelConfigs = physicalChannelConfigs;
+ mDoesPccListIndicateIdle = false;
if (DBG) {
log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId
+ ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" + mRatchetedNrBands
@@ -1165,7 +1316,11 @@
if (isNrAdvanced()) {
transitionState = mNrConnectedAdvancedState;
} else {
- transitionState = mNrConnectedState;
+ if (isPhysicalLinkActive() || !mFeatureFlags.supportNrSaRrcIdle()) {
+ transitionState = mNrConnectedState;
+ } else {
+ transitionState = mNrIdleState;
+ }
}
} else if (isLte(dataRat) && isNrNotRestricted()) {
if (isPhysicalLinkActive()) {
@@ -1248,6 +1403,16 @@
mSecondaryTimerState = "";
}
+ private boolean isTimerActiveForNrSaRrcIdle() {
+ if (mIsPrimaryTimerActive) {
+ return mPrimaryTimerState.equals(STATE_CONNECTED_RRC_IDLE);
+ } else if (mIsSecondaryTimerActive) {
+ return mSecondaryTimerState.equals(STATE_CONNECTED_RRC_IDLE);
+ } else {
+ return false;
+ }
+ }
+
/**
* Private class defining timer rules between states to prevent flickering. These rules are
* created in {@link #parseCarrierConfigs()} based on various carrier configs.
@@ -1320,6 +1485,16 @@
return secondaryTimer == null ? 0 : secondaryTimer;
}
+ /**
+ * @return Whether timer rules have been defined for this {@link #mState}.
+ */
+ public boolean isDefined() {
+ // TODO: Remove this method added to make STATE_CONNECTED_RRC_IDLE backwards compatible
+ // with STATE_CONNECTED once carrier configs are updated.
+ return mOverrideType != TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
+ || !mPrimaryTimers.isEmpty() || !mSecondaryTimers.isEmpty();
+ }
+
@Override
public String toString() {
return "{mState=" + mState
@@ -1346,6 +1521,10 @@
* @return {@code true} if the device is in NR advanced mode (i.e. 5G+).
*/
private boolean isNrAdvanced() {
+ return isNrAdvancedForPccFields(mRatchetedNrBandwidths, mRatchetedNrBands);
+ }
+
+ private boolean isNrAdvancedForPccFields(int bandwidths, Set<Integer> bands) {
// Check PCO requirement. For carriers using PCO to indicate whether the data connection is
// NR advanced capable, mNrAdvancedCapablePcoId should be configured to non-zero.
if (mNrAdvancedCapablePcoId > 0 && !mIsNrAdvancedAllowedByPco) {
@@ -1362,10 +1541,9 @@
// Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum
// bandwidth requirement and mNrAdvancedThresholdBandwidth is 0.
- if (mNrAdvancedThresholdBandwidth > 0
- && mRatchetedNrBandwidths < mNrAdvancedThresholdBandwidth) {
+ if (mNrAdvancedThresholdBandwidth > 0 && bandwidths < mNrAdvancedThresholdBandwidth) {
if (DBG) {
- log("isNrAdvanced: false because bandwidths=" + mRatchetedNrBandwidths
+ log("isNrAdvanced: false because bandwidths=" + bandwidths
+ " does not meet the threshold=" + mNrAdvancedThresholdBandwidth);
}
return false;
@@ -1373,24 +1551,24 @@
// If all above tests passed, then check if the device is using millimeter wave bands or
// carrier designated bands.
- return isNrMmwave() || isAdditionalNrAdvancedBand();
+ return isNrMmwave() || isAdditionalNrAdvancedBand(bands);
}
private boolean isNrMmwave() {
return mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE;
}
- private boolean isAdditionalNrAdvancedBand() {
- if (mAdditionalNrAdvancedBands.isEmpty() || mRatchetedNrBands.isEmpty()) {
+ private boolean isAdditionalNrAdvancedBand(Set<Integer> bands) {
+ if (mAdditionalNrAdvancedBands.isEmpty() || bands.isEmpty()) {
if (DBG && !mAdditionalNrAdvancedBands.isEmpty()) {
// Only log if mAdditionalNrAdvancedBands is empty to prevent log spam
log("isAdditionalNrAdvancedBand: false because bands are empty; configs="
- + mAdditionalNrAdvancedBands + ", bands=" + mRatchetedNrBands);
+ + mAdditionalNrAdvancedBands + ", bands=" + bands);
}
return false;
}
Set<Integer> intersection = new HashSet<>(mAdditionalNrAdvancedBands);
- intersection.retainAll(mRatchetedNrBands);
+ intersection.retainAll(bands);
return !intersection.isEmpty();
}
@@ -1404,7 +1582,8 @@
}
private int getPhysicalLinkStatusFromPhysicalChannelConfig() {
- return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty())
+ return (mPhysicalChannelConfigs == null || mPhysicalChannelConfigs.isEmpty()
+ || mDoesPccListIndicateIdle)
? DataCallResponse.LINK_STATUS_DORMANT : DataCallResponse.LINK_STATUS_ACTIVE;
}
@@ -1449,6 +1628,7 @@
pw.flush();
pw.increaseIndent();
pw.println("mSubId=" + mPhone.getSubId());
+ pw.println("supportNrSaRrcIdle=" + mFeatureFlags.supportNrSaRrcIdle());
pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
@@ -1465,6 +1645,7 @@
pw.println("mAdditionalNrAdvancedBandsList=" + mAdditionalNrAdvancedBands);
pw.println("mRatchetedNrBands=" + mRatchetedNrBands);
pw.println("mLastAnchorNrCellId=" + mLastAnchorNrCellId);
+ pw.println("mDoesPccListIndicateIdle=" + mDoesPccListIndicateIdle);
pw.println("mPrimaryTimerState=" + mPrimaryTimerState);
pw.println("mSecondaryTimerState=" + mSecondaryTimerState);
pw.println("mPreviousState=" + mPreviousState);
@@ -1473,6 +1654,7 @@
pw.println("mIsNrAdvancedAllowedByPco=" + mIsNrAdvancedAllowedByPco);
pw.println("mNrAdvancedCapablePcoId=" + mNrAdvancedCapablePcoId);
pw.println("mIsUsingUserDataForRrcDetection=" + mIsUsingUserDataForRrcDetection);
+ pw.println("mPrimaryCellChangedWhileIdle=" + mPrimaryCellChangedWhileIdle);
pw.println("mEnableNrAdvancedWhileRoaming=" + mEnableNrAdvancedWhileRoaming);
pw.println("mIsDeviceIdleMode=" + mIsDeviceIdleMode);
pw.decreaseIndent();
diff --git a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
index d7a70be..e74e40e 100644
--- a/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
+++ b/src/java/com/android/internal/telephony/analytics/TelephonyAnalytics.java
@@ -264,7 +264,11 @@
callType = CallType.NORMAL_CALL.value;
}
if (isOverIms) {
- disconnectCauseString = sImsCodeMap.get(disconnectCause);
+ disconnectCauseString =
+ sImsCodeMap.getOrDefault(disconnectCause, "UNKNOWN_REJECT_CAUSE");
+ if (disconnectCauseString.equals("UNKNOWN_REJECT_CAUSE")) {
+ Rlog.d(TAG, "UNKNOWN_REJECT_CAUSE: " + disconnectCause);
+ }
status =
disconnectCause == ImsReasonInfo.CODE_USER_TERMINATED
|| disconnectCause
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index 0692f7d..f3c0a6c 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -512,6 +512,17 @@
if (isSamePhone(mPhone, phone) && (!mActiveEmergencyCalls.isEmpty() || isInEcm())) {
mOngoingCallId = callId;
mIsTestEmergencyNumber = isTestEmergencyNumber;
+ // Ensure that domain selector requests scan.
+ mLastEmergencyRegResult = new EmergencyRegResult(
+ AccessNetworkConstants.AccessNetworkType.UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN,
+ NetworkRegistrationInfo.DOMAIN_UNKNOWN, false, false, 0, 0, "", "", "");
+ if (isInEcm()) {
+ // Remove pending exit ECM runnable.
+ mHandler.removeCallbacks(mExitEcmRunnable);
+ releaseWakeLock();
+ ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.TRUE);
+ }
return CompletableFuture.completedFuture(DisconnectCause.NOT_DISCONNECTED);
}
@@ -578,8 +589,7 @@
// If the emergency call was initiated during the emergency callback mode,
// the emergency callback mode should be restored when the emergency call is ended.
if (mActiveEmergencyCalls.isEmpty()) {
- setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
- MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
+ enterEmergencyCallbackMode();
}
} else {
exitEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, false);
@@ -960,20 +970,23 @@
// ECBM (see ImsPhone#handleEnterEmergencyCallbackMode)
((GsmCdmaPhone) mPhone).notifyEmergencyCallRegistrants(true);
}
-
- // Set emergency mode on modem.
- setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
- MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
-
- // Post this runnable so we will automatically exit if no one invokes
- // exitEmergencyCallbackMode() directly.
- long delayInMillis = TelephonyProperties.ecm_exit_timer()
- .orElse(mEcmExitTimeoutMs);
- mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
-
- // We don't want to go to sleep while in ECM.
- if (mWakeLock != null) mWakeLock.acquire(delayInMillis);
+ } else {
+ // Inform to reset the ECBM timer.
+ ((GsmCdmaPhone) mPhone).notifyEcbmTimerReset(Boolean.FALSE);
}
+
+ // Set emergency mode on modem.
+ setEmergencyMode(mPhone, EMERGENCY_TYPE_CALL, MODE_EMERGENCY_CALLBACK,
+ MSG_SET_EMERGENCY_CALLBACK_MODE_DONE);
+
+ // Post this runnable so we will automatically exit if no one invokes
+ // exitEmergencyCallbackMode() directly.
+ long delayInMillis = TelephonyProperties.ecm_exit_timer()
+ .orElse(mEcmExitTimeoutMs);
+ mHandler.postDelayed(mExitEcmRunnable, delayInMillis);
+
+ // We don't want to go to sleep while in ECM.
+ if (mWakeLock != null) mWakeLock.acquire(delayInMillis);
}
/**
@@ -991,14 +1004,7 @@
}
// Release wakeLock.
- if (mWakeLock != null && mWakeLock.isHeld()) {
- try {
- mWakeLock.release();
- } catch (Exception e) {
- // Ignore the exception if the system has already released this WakeLock.
- Rlog.d(TAG, "WakeLock already released: " + e.toString());
- }
- }
+ releaseWakeLock();
GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) mPhone;
// Send intents that ECM has changed.
@@ -1016,6 +1022,18 @@
mPhone = null;
}
+ private void releaseWakeLock() {
+ // Release wakeLock.
+ if (mWakeLock != null && mWakeLock.isHeld()) {
+ try {
+ mWakeLock.release();
+ } catch (Exception e) {
+ // Ignore the exception if the system has already released this WakeLock.
+ Rlog.d(TAG, "WakeLock already released: " + e.toString());
+ }
+ }
+ }
+
/**
* Exits emergency callback mode and triggers runnable after exit response is received.
*/
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 7f15af8..0869bab 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -107,7 +107,8 @@
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
@@ -277,7 +278,8 @@
public void testTransitionToCurrentStateIdleSupportPhysicalChannelConfig1_6() throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -295,7 +297,8 @@
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);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -324,7 +327,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -344,7 +348,8 @@
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);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
assertEquals("DefaultState", getCurrentState().getName());
@@ -358,6 +363,19 @@
}
@Test
+ public void testTransitionToCurrentStateNrConnectedIdle() throws Exception {
+ assertEquals("DefaultState", getCurrentState().getName());
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(new ArrayList<>()).when(mSST).getPhysicalChannelConfigList();
+ sendCarrierConfigChanged();
+
+ mNetworkTypeController.sendMessage(3 /* EVENT_SERVICE_STATE_CHANGED */);
+ processAllMessages();
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ }
+
+ @Test
public void testTransitionToCurrentStateNrConnected() throws Exception {
assertEquals("DefaultState", getCurrentState().getName());
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
@@ -745,7 +763,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
testTransitionToCurrentStateNrConnectedMmwave();
doReturn(NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED).when(mServiceState).getNrState();
@@ -764,7 +783,8 @@
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);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
testTransitionToCurrentStateNrConnectedMmwave();
@@ -865,7 +885,8 @@
throws Exception {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
- mNetworkTypeController = new NetworkTypeController(mPhone, mDisplayInfoController);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
processAllMessages();
testTransitionToCurrentStateLteConnectedSupportPhysicalChannelConfig1_6();
doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
@@ -883,7 +904,8 @@
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);
+ mNetworkTypeController =
+ new NetworkTypeController(mPhone, mDisplayInfoController, mFeatureFlags);
sendCarrierConfigChanged();
processAllMessages();
testTransitionToCurrentStateLteConnected_usingUserDataForRrcDetection();
@@ -1317,6 +1339,229 @@
}
@Test
+ public void testSecondaryTimerExpireNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertFalse(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
+ public void testSecondaryTimerResetNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // reconnect to NR in the middle of the timer
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+
+ // secondary timer expires
+ moveTimeForward(30 * 1000);
+ processAllMessages();
+
+ // timer should not have gone off
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertFalse(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
+ public void testSecondaryTimerPrimaryCellChangeNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .setBand(41)
+ .build());
+ doReturn(physicalChannelConfigs).when(mSST).getPhysicalChannelConfigList();
+ mBundle.putIntArray(CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY,
+ new int[]{41});
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,10");
+ mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_SECONDARY_GRACE_PERIOD_STRING,
+ "connected_mmwave,any,30");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // should trigger 10 second primary timer
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(1)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // switch to connected_rrc_idle
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary timer expires
+ moveTimeForward(10 * 1000);
+ processAllMessages();
+
+ // should trigger 30 second secondary timer
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // primary cell changes
+ physicalChannelConfigs.clear();
+ physicalChannelConfigs.add(new PhysicalChannelConfig.Builder()
+ .setPhysicalCellId(2)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+ .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+ .build());
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+ }
+
+ @Test
public void testNrTimerResetIn3g() throws Exception {
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
index 0403232..60cdac9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnectionTest.java
@@ -40,9 +40,6 @@
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.AccessNetworksManager;
-import com.android.internal.telephony.domainselection.DomainSelectionConnection;
-import com.android.internal.telephony.domainselection.DomainSelectionController;
-import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
import org.junit.After;
import org.junit.Before;
@@ -58,6 +55,7 @@
public class NormalCallDomainSelectionConnectionTest extends TelephonyTest {
private static final String TELECOM_CALL_ID1 = "TC1";
+ private static final int TEST_PHONE_ID = 111;
@Mock
private DomainSelectionController mMockDomainSelectionController;
@@ -74,6 +72,7 @@
super.setUp(this.getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
doReturn(mMockAccessNetworksManager).when(mPhone).getAccessNetworksManager();
+ doReturn(TEST_PHONE_ID).when(mPhone).getPhoneId();
mNormalCallDomainSelectionConnection =
new NormalCallDomainSelectionConnection(mPhone, mMockDomainSelectionController);
mTransportCallback = mNormalCallDomainSelectionConnection.getTransportSelectorCallback();
@@ -189,4 +188,24 @@
assertEquals(10, attributes.getCsDisconnectCause());
assertEquals(imsReasonInfo, attributes.getPsDisconnectCause());
}
+
+ @Test
+ public void testGetSetMethods() throws Exception {
+ ImsReasonInfo imsReasonInfo = new ImsReasonInfo();
+ DomainSelectionService.SelectionAttributes attributes =
+ NormalCallDomainSelectionConnection.getSelectionAttributes(1, 2,
+ TELECOM_CALL_ID1, "123", false, 0, imsReasonInfo);
+
+ mNormalCallDomainSelectionConnection
+ .createNormalConnection(attributes, mMockConnectionCallback);
+
+ mNormalCallDomainSelectionConnection.setDisconnectCause(100, 101,
+ "Test disconnect cause");
+ assertEquals(100, mNormalCallDomainSelectionConnection.getDisconnectCause());
+ assertEquals(101, mNormalCallDomainSelectionConnection.getPreciseDisconnectCause());
+ assertEquals("Test disconnect cause",
+ mNormalCallDomainSelectionConnection.getReasonMessage());
+ assertEquals(imsReasonInfo, mNormalCallDomainSelectionConnection.getImsReasonInfo());
+ assertEquals(TEST_PHONE_ID, mNormalCallDomainSelectionConnection.getPhoneId());
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index fff1b68..5a7f763 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -1956,6 +1956,168 @@
assertFalse(testEst.isEmergencyCallbackModeSupported());
}
+ /**
+ * Test that new emergency call is dialed while in emergency callback mode and completes.
+ */
+ @Test
+ @SmallTest
+ public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndCompletes() {
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phone
+ GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
+ /* isRoaming= */ true, /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
+ setUpAsyncResultForExitEmergencyMode(testPhone);
+ // Start emergency call then enter ECM
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ processAllMessages();
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // Set ecm as supported
+ setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // 2nd call while in emergency callback mode
+ unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ emergencyStateTracker.onEmergencyTransportChanged(
+ EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
+ processAllMessages();
+ processAllFutureMessages();
+
+ // verify ecbm states are not changed.
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ // Verify ECBM timer cancel.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify ECBM timer reset.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ processAllFutureMessages();
+
+ // Ensure ECBM states are all correctly false after we exit.
+ assertFalse(emergencyStateTracker.isInEcm());
+ assertFalse(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is called.
+ verify(testPhone).exitEmergencyMode(any(Message.class));
+ }
+
+ /**
+ * Test that new emergency call is dialed while in emergency callback mode and it fails.
+ */
+ @Test
+ @SmallTest
+ public void exitEmergencyCallbackMode_NewEmergencyCallDialedAndFails() {
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phone
+ GsmCdmaPhone testPhone = (GsmCdmaPhone) setupTestPhoneForEmergencyCall(
+ /* isRoaming= */ true, /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(testPhone, E_REG_RESULT);
+ setUpAsyncResultForExitEmergencyMode(testPhone);
+ // Start emergency call then enter ECM
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ processAllMessages();
+
+ // Set call to ACTIVE
+ emergencyStateTracker.onEmergencyCallStateChanged(Call.State.ACTIVE, TEST_CALL_ID);
+ emergencyStateTracker.onEmergencyCallDomainUpdated(
+ PhoneConstants.PHONE_TYPE_IMS, TEST_CALL_ID);
+ // Set ecm as supported
+ setEcmSupportedConfig(testPhone, /* ecmSupported= */ true);
+ // End call to enter ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // 2nd call while in emergency callback mode
+ unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ TEST_CALL_ID, false);
+ emergencyStateTracker.onEmergencyTransportChanged(
+ EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
+ processAllMessages();
+ processAllFutureMessages();
+
+ // verify ecbm states are not changed.
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ // Verify ECBM timer cancel.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.TRUE));
+
+ // End call to return to ECM
+ emergencyStateTracker.endCall(TEST_CALL_ID);
+ processAllMessages();
+
+ // verify ecbm states are correct
+ assertTrue(emergencyStateTracker.isInEcm());
+ assertTrue(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify ECBM timer reset.
+ verify(testPhone).notifyEcbmTimerReset(eq(Boolean.FALSE));
+
+ // Verify exitEmergencyMode() is not called.
+ verify(testPhone, never()).exitEmergencyMode(any(Message.class));
+
+ processAllFutureMessages();
+
+ // Ensure ECBM states are all correctly false after we exit.
+ assertFalse(emergencyStateTracker.isInEcm());
+ assertFalse(emergencyStateTracker.isInImsEcm());
+ assertFalse(emergencyStateTracker.isInCdmaEcm());
+
+ // Verify exitEmergencyMode() is called.
+ verify(testPhone).exitEmergencyMode(any(Message.class));
+ }
+
private EmergencyStateTracker setupEmergencyStateTracker(
boolean isSuplDdsSwitchRequiredForEmergencyCall) {
doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java
new file mode 100644
index 0000000..56f4b67
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/SecurityAlgorithmUpdateTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.security;
+
+import static android.telephony.SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+import static android.telephony.SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.telephony.SecurityAlgorithmUpdate;
+
+import org.junit.Test;
+
+public final class SecurityAlgorithmUpdateTest {
+
+ @Test
+ public void testEqualsAndHash() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+ SecurityAlgorithmUpdate sameUpdate = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ assertThat(update).isEqualTo(sameUpdate);
+ assertThat(update.hashCode()).isEqualTo(sameUpdate.hashCode());
+ }
+
+ @Test
+ public void testNotEqualsAndHash() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+ SecurityAlgorithmUpdate sameUpdate = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, true);
+
+ assertThat(update).isNotEqualTo(sameUpdate);
+ assertThat(update.hashCode()).isNotEqualTo(sameUpdate.hashCode());
+ }
+
+ @Test
+ public void testGetters() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ assertThat(update.getConnectionEvent()).isEqualTo(CONNECTION_EVENT_VOLTE_SIP);
+ assertThat(update.getEncryption()).isEqualTo(SECURITY_ALGORITHM_EEA2);
+ assertThat(update.getIntegrity()).isEqualTo(SECURITY_ALGORITHM_HMAC_SHA1_96);
+ assertThat(update.isUnprotectedEmergency()).isFalse();
+ }
+
+ @Test
+ public void testParcel() {
+ SecurityAlgorithmUpdate update = new SecurityAlgorithmUpdate(
+ CONNECTION_EVENT_VOLTE_SIP, SECURITY_ALGORITHM_EEA2,
+ SECURITY_ALGORITHM_HMAC_SHA1_96, false);
+
+ Parcel p = Parcel.obtain();
+ update.writeToParcel(p, 0);
+ p.setDataPosition(0);
+
+ SecurityAlgorithmUpdate fromParcel = SecurityAlgorithmUpdate.CREATOR.createFromParcel(p);
+ assertThat(fromParcel).isEqualTo(update);
+ }
+}