Merge "Idle mode scanning for terrestrial network when P2P SMS or ESOS mode inactivity timer expired" into main
diff --git a/flags/data.aconfig b/flags/data.aconfig
index a993d51..0fd094d 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -121,3 +121,14 @@
}
}
+# OWNER=jackyu TARGET=25Q1
+flag {
+ name: "sim_disabled_graceful_tear_down"
+ namespace: "telephony"
+ description: "Gracefully tear down the networks when SIM is disabled."
+ bug: "362372940"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 2078cd9..9b1bd24 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -1024,7 +1024,10 @@
if (rat == TelephonyManager.NETWORK_TYPE_NR
|| (isLte(rat) && isNrConnected())) {
if (isNrAdvanced()) {
- transitionTo(mNrConnectedAdvancedState);
+ // Move into idle state because mPhysicalLinkStatus indicated idle,
+ // ignored any advance reason because unless mPhysicalLinkStatus changed
+ // again, shouldn't move back to advance.
+ log("Ignore NR advanced from cached PCC/RatchetedNrBands while idle");
} else if (isPhysicalLinkActive()) {
transitionWithTimerTo(mNrConnectedState);
} else {
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index f5eae91..40c0081 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -225,6 +225,8 @@
SIM_LOADED(true),
/** SIM is removed. */
SIM_REMOVAL(true),
+ /** SIM is disabled. */
+ SIM_DISABLED(true),
/** Data profiles changed. */
DATA_PROFILES_CHANGED(true),
/** When service state changes.(For now only considering data RAT and data registration). */
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 89153ab..5d31283 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -3543,15 +3543,6 @@
}
/**
- * Called when SIM is absent.
- */
- private void onSimAbsent() {
- log("onSimAbsent");
- sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
- DataEvaluationReason.SIM_REMOVAL));
- }
-
- /**
* Called when SIM state changes.
*
* @param simState SIM state. (Note this is mixed with card state and application state.)
@@ -3559,13 +3550,22 @@
private void onSimStateChanged(@SimState int simState) {
log("onSimStateChanged: state=" + TelephonyManager.simStateToString(simState));
if (mSimState != simState) {
- mSimState = simState;
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
- onSimAbsent();
+ log("onSimStateChanged: SIM absent.");
+ sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
+ DataEvaluationReason.SIM_REMOVAL));
+ } else if (simState == TelephonyManager.SIM_STATE_NOT_READY
+ && mSimState == TelephonyManager.SIM_STATE_LOADED) {
+ if (mFeatureFlags.simDisabledGracefulTearDown()) {
+ log("onSimStateChanged: SIM disabled.");
+ sendMessage(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
+ DataEvaluationReason.SIM_DISABLED));
+ }
} else if (simState == TelephonyManager.SIM_STATE_LOADED) {
sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
DataEvaluationReason.SIM_LOADED));
}
+ mSimState = simState;
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onSimStateChanged(mSimState)));
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 214b276..7599bce 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -241,7 +241,7 @@
private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40;
private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41;
private static final int EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT = 42;
- private static final int EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43;
+ private static final int CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION = 43;
private static final int CMD_UPDATE_PROVISION_SATELLITE_TOKEN = 44;
private static final int EVENT_UPDATE_PROVISION_SATELLITE_TOKEN_DONE = 45;
private static final int EVENT_NOTIFY_NTN_ELIGIBILITY_HYSTERESIS_TIMED_OUT = 46;
@@ -522,6 +522,17 @@
private final Object mIsWifiConnectedLock = new Object();
@GuardedBy("mIsWifiConnectedLock")
private boolean mIsWifiConnected = false;
+ private BroadcastReceiver
+ mDefaultSmsSubscriptionChangedBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction().equals(
+ SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED)) {
+ plogd("Default SMS subscription changed");
+ sendRequestAsync(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION, null, null);
+ }
+ }
+ };
/**
* @return The singleton instance of SatelliteController.
@@ -654,7 +665,7 @@
getDemoPointingNotAlignedDurationMillisFromResources();
mSatelliteEmergencyModeDurationMillis =
getSatelliteEmergencyModeDurationFromOverlayConfig(context);
- sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
/* delayMillis= */ TimeUnit.MINUTES.toMillis(1));
SubscriptionManager subscriptionManager = mContext.getSystemService(
@@ -664,6 +675,7 @@
subscriptionManager.addOnSubscriptionsChangedListener(
new HandlerExecutor(new Handler(looper)), mSubscriptionsChangedListener);
}
+ registerDefaultSmsSubscriptionChangedBroadcastReceiver();
}
class SatelliteSubscriptionsChangedListener
@@ -1579,7 +1591,7 @@
break;
}
- case EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION: {
+ case CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION: {
evaluateESOSProfilesPrioritization();
break;
}
@@ -4368,13 +4380,13 @@
processNewCarrierConfigData(subId);
resetCarrierRoamingSatelliteModeParams(subId);
handleStateChangedForCarrierRoamingNtnEligibility();
- sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
TimeUnit.MINUTES.toMillis(1));
}
// imsi, msisdn, default sms subId change
private void handleSubscriptionsChanged() {
- sendMessageDelayed(obtainMessage(EVENT_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+ sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
TimeUnit.MINUTES.toMillis(1));
}
@@ -5649,11 +5661,12 @@
*/
private void evaluateESOSProfilesPrioritization() {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("evaluateESOSProfilesPrioritization: Flag CarrierRoamingNbIotNtn is disabled");
return;
}
List<SubscriptionInfo> allSubInfos = mSubscriptionManagerService.getAllSubInfoList(
mContext.getOpPackageName(), mContext.getAttributionTag());
- //key : priority, low value is high, value : List<SubscriptionInfo>
+ // Key : priority - lower value has higher priority; Value : List<SubscriptionInfo>
Map<Integer, List<SubscriptionInfo>> newSubsInfoListPerPriority = new HashMap<>();
for (SubscriptionInfo info : allSubInfos) {
int subId = info.getSubscriptionId();
@@ -5671,15 +5684,18 @@
if (keyPriority != -1) {
newSubsInfoListPerPriority.computeIfAbsent(keyPriority,
k -> new ArrayList<>()).add(info);
+ } else {
+ plogw("evaluateESOSProfilesPrioritization: Got -1 keyPriority for subId="
+ + info.getSubscriptionId());
}
}
if (newSubsInfoListPerPriority.size() == 0) {
- logd("evaluateESOSProfilesPrioritization: no available");
+ logd("evaluateESOSProfilesPrioritization: no satellite subscription available");
return;
}
- // if priority is changed, send broadcast for provisioned ESOS subs ids
+ // If priority has changed, send broadcast for provisioned ESOS subs IDs
synchronized (mSatelliteTokenProvisionedLock) {
if (isPriorityChanged(mSubsInfoListPerPriority, newSubsInfoListPerPriority)) {
mSubsInfoListPerPriority = newSubsInfoListPerPriority;
@@ -6050,4 +6066,15 @@
}
}
}
+
+ private void registerDefaultSmsSubscriptionChangedBroadcastReceiver() {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("registerDefaultSmsSubscriptionChangedBroadcastReceiver: Flag "
+ + "CarrierRoamingNbIotNtn is disabled");
+ return;
+ }
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED);
+ mContext.registerReceiver(mDefaultSmsSubscriptionChangedBroadcastReceiver, intentFilter);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index e08abd9..738f765 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1507,6 +1507,52 @@
}
@Test
+ public void testTransitionToNrIdle() throws Exception {
+ doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
+ doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+ doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
+ ArrayList<PhysicalChannelConfig> physicalChannelConfigs = new ArrayList<>();
+ // use advanced band
+ 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");
+ sendCarrierConfigChanged();
+
+ assertEquals("connected_mmwave", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+
+ // empty PCC, switch to connected_rrc_idle,
+ // isNrAdvanced is still true(due to either advance band OR frequency)
+ physicalChannelConfigs.clear();
+ mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+ new AsyncResult(null, physicalChannelConfigs, null));
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+ // Received an event update, verify should stay in idle because physical link didn't change,
+ // otherwise there is a loop between advance state and idle state.
+ mNetworkTypeController.sendMessage(0 /* EVENT_UPDATE */);
+ processAllMessages();
+
+ assertEquals("connected_rrc_idle", getCurrentState().getName());
+ assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+ mNetworkTypeController.getOverrideNetworkType());
+ }
+
+ @Test
public void testSecondaryTimerAdvanceBand() throws Exception {
doReturn(true).when(mFeatureFlags).supportNrSaRrcIdle();
doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 5dce5c2..0b66459 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -888,8 +888,11 @@
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn(new SubscriptionInfoInternal.Builder().setId(1).build())
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
doReturn(true).when(mFeatureFlags).satelliteInternet();
+ doReturn(true).when(mFeatureFlags).simDisabledGracefulTearDown();
+
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
doReturn(true).when(mMockPackageManager).hasSystemFeature(anyString());
@@ -4196,7 +4199,7 @@
}
@Test
- public void testImsGracefulTearDown() throws Exception {
+ public void testImsGracefulTearDownSimRemoval() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
@@ -4242,6 +4245,52 @@
}
@Test
+ public void testImsGracefulTearDownSimDisabled() throws Exception {
+ setImsRegistered(true);
+ setRcsRegistered(true);
+
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ netCaps.maybeMarkCapabilitiesRestricted();
+ netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
+
+ NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
+ TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
+ nativeNetworkRequest, mPhone, mFeatureFlags);
+
+ mDataNetworkControllerUT.addNetworkRequest(networkRequest);
+
+ processAllMessages();
+ Mockito.clearInvocations(mPhone);
+
+ // SIM disabled
+ mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/,
+ TelephonyManager.SIM_STATE_NOT_READY, 0).sendToTarget();
+ processAllMessages();
+
+ // Make sure data network enters disconnecting state
+ ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
+ ArgumentCaptor.forClass(PreciseDataConnectionState.class);
+ verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
+ PreciseDataConnectionState pdcs = pdcsCaptor.getValue();
+ assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING);
+
+ // IMS de-registered. Now data network is safe to be torn down.
+ Mockito.clearInvocations(mPhone);
+ setImsRegistered(false);
+ setRcsRegistered(false);
+ processAllMessages();
+
+ // All data should be disconnected.
+ verifyAllDataDisconnected();
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ verify(mPhone).notifyDataConnection(pdcsCaptor.capture());
+ pdcs = pdcsCaptor.getValue();
+ assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED);
+ }
+
+ @Test
public void testNoGracefulTearDownForEmergencyDataNetwork() throws Exception {
setImsRegistered(true);