Merge "Add new fields for counting sms sms message for Satellite" into main
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 3cefb5e..f05e002 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -213,8 +213,8 @@
     @NonNull private final Set<Integer> mAdditionalNrAdvancedBands = new HashSet<>();
     @NonNull private String mPrimaryTimerState;
     @NonNull private String mSecondaryTimerState;
-    // TODO(b/316425811 remove the workaround)
     private int mNrAdvancedBandsSecondaryTimer;
+    private int mNrAdvancedPciChangeSecondaryTimer;
     @NonNull private String mPreviousState;
     @LinkStatus private int mPhysicalLinkStatus;
     private boolean mIsPhysicalChannelConfig16Supported;
@@ -224,6 +224,7 @@
     private boolean mEnableNrAdvancedWhileRoaming = true;
     private boolean mIsDeviceIdleMode = false;
     private boolean mPrimaryCellChangedWhileIdle = false;
+    private boolean mPciChangedDuringPrimaryTimer = false;
 
     // Cached copies below to prevent race conditions
     @NonNull private ServiceState mServiceState;
@@ -485,6 +486,8 @@
                 CarrierConfigManager.KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL);
         mNrAdvancedBandsSecondaryTimer = config.getInt(
                 CarrierConfigManager.KEY_NR_ADVANCED_BANDS_SECONDARY_TIMER_SECONDS_INT);
+        mNrAdvancedPciChangeSecondaryTimer = config.getInt(
+                CarrierConfigManager.KEY_NR_ADVANCED_PCI_CHANGE_SECONDARY_TIMER_SECONDS_INT);
         String nrIconConfiguration = config.getString(
                 CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
         String overrideTimerRule = config.getString(
@@ -1427,6 +1430,7 @@
         mLastAnchorNrCellId = anchorNrCellId;
         mPhysicalChannelConfigs = physicalChannelConfigs;
         mDoesPccListIndicateIdle = false;
+        mPciChangedDuringPrimaryTimer = mIsPrimaryTimerActive;
         if (DBG) {
             log("Physical channel configs updated: anchorNrCell=" + mLastAnchorNrCellId
                     + ", nrBandwidths=" + mRatchetedNrBandwidths + ", nrBands=" +  mRatchetedNrBands
@@ -1484,6 +1488,7 @@
     private void transitionWithSecondaryTimerTo(IState destState) {
         String currentName = getCurrentState().getName();
         OverrideTimerRule rule = mOverrideTimerRules.get(mPrimaryTimerState);
+        int duration = -1;
         if (DBG) {
             log("Transition with secondary timer from " + currentName + " to "
                     + destState.getName());
@@ -1492,12 +1497,19 @@
             log("Skip secondary timer from " + currentName + " to "
                     + destState.getName() + " due to in call");
         } else if (!mIsDeviceIdleMode && rule != null && rule.getSecondaryTimer(currentName) > 0) {
-            int duration = rule.getSecondaryTimer(currentName);
+            duration = rule.getSecondaryTimer(currentName);
             if (mLastShownNrDueToAdvancedBand && mNrAdvancedBandsSecondaryTimer > 0) {
                 duration = mNrAdvancedBandsSecondaryTimer;
                 if (DBG) log("timer adjusted by nr_advanced_bands_secondary_timer_seconds_int");
             }
             if (DBG) log(duration + "s secondary timer started for state: " + currentName);
+        } else if (mNrAdvancedPciChangeSecondaryTimer > 0
+                && mPciChangedDuringPrimaryTimer) {
+            duration = mNrAdvancedPciChangeSecondaryTimer;
+            if (DBG) log(duration + "s secondary timer started for PCI changed");
+        }
+
+        if (duration > 0) {
             mSecondaryTimerState = currentName;
             mPreviousState = currentName;
             mIsSecondaryTimerActive = true;
@@ -1505,7 +1517,9 @@
             mSecondaryTimerExpireTimestamp = SystemClock.uptimeMillis() + durationMillis;
             sendMessageDelayed(EVENT_SECONDARY_TIMER_EXPIRED, destState, durationMillis);
         }
+
         mIsPrimaryTimerActive = false;
+        mPciChangedDuringPrimaryTimer = false;
         transitionTo(getCurrentState());
     }
 
@@ -1555,6 +1569,7 @@
             }
             removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
             mIsPrimaryTimerActive = false;
+            mPciChangedDuringPrimaryTimer = false;
             mPrimaryTimerState = "";
             transitionToCurrentState();
             return;
@@ -1598,6 +1613,7 @@
         removeMessages(EVENT_PRIMARY_TIMER_EXPIRED);
         removeMessages(EVENT_SECONDARY_TIMER_EXPIRED);
         mIsPrimaryTimerActive = false;
+        mPciChangedDuringPrimaryTimer = false;
         mIsSecondaryTimerActive = false;
         mSecondaryTimerExpireTimestamp = 0;
         mPrimaryTimerState = "";
@@ -1821,10 +1837,11 @@
         pw.flush();
         pw.increaseIndent();
         pw.println("mSubId=" + mPhone.getSubId());
-        pw.println("mOverrideTimerRules=" + mOverrideTimerRules.toString());
+        pw.println("mOverrideTimerRules=" + mOverrideTimerRules);
         pw.println("mLteEnhancedPattern=" + mLteEnhancedPattern);
         pw.println("mIsPhysicalChannelConfigOn=" + mIsPhysicalChannelConfigOn);
         pw.println("mIsPrimaryTimerActive=" + mIsPrimaryTimerActive);
+        pw.println("mPciChangedDuringPrimaryTimer=" + mPciChangedDuringPrimaryTimer);
         pw.println("mIsSecondaryTimerActive=" + mIsSecondaryTimerActive);
         pw.println("mIsTimerResetEnabledForLegacyStateRrcIdle="
                 + mIsTimerResetEnabledForLegacyStateRrcIdle);
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index b15ddf8..a90adda 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -1060,16 +1060,17 @@
     }
 
     /**
-     * Notify the phone that an SMS has been sent. This will be used determine if the SMS was sent
-     * to an emergency address.
+     * Notify the phone that an SMS has been sent. This will be used to determine if the SMS was
+     * sent to an emergency address.
+     *
      * @param destinationAddress the address that the SMS was sent to.
      */
     public void notifySmsSent(String destinationAddress) {
-        TelephonyManager m = (TelephonyManager) getContext().getSystemService(
-                Context.TELEPHONY_SERVICE);
+        TelephonyManager m =
+                (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
         if (mContext.getPackageManager() != null
-                && mContext.getPackageManager().hasSystemFeature(
-                        PackageManager.FEATURE_TELEPHONY_CALLING)) {
+                && mContext.getPackageManager()
+                                .hasSystemFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)) {
             if (m != null && m.isEmergencyNumber(destinationAddress)) {
                 mLocalLog.log("Emergency SMS detected, recording time.");
                 mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 86cfbba..00612f7 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -3391,6 +3391,7 @@
         mPendingImsDeregDataNetworks.remove(dataNetwork);
         mDataRetryManager.cancelPendingHandoverRetry(dataNetwork);
         if (dataNetwork.isInternetSupported()) updateOverallInternetDataState();
+        onPcoDataChanged(dataNetwork);
 
         if (dataNetwork.getNetworkCapabilities().hasCapability(
                 NetworkCapabilities.NET_CAPABILITY_IMS)) {
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index c586d19..026bfff 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -4158,8 +4158,7 @@
         }
 
         UserHandle myUserHandle = UserHandle.of(UserHandle.getCallingUserId());
-        return mFeatureFlags.subscriptionUserAssociationQuery()
-            && isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle);
+        return isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle);
     }
 
     /**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 0b6aff9..3f77744 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -640,16 +640,16 @@
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(emergencyNumber);
 
         // Feature flag enabled
-        // Device does not have FEATURE_TELEPHONY_CALLING
+        // Device does not have FEATURE_TELEPHONY_MESSAGING
         doReturn(false).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+                eq(PackageManager.FEATURE_TELEPHONY_MESSAGING));
         mPhoneUT.notifySmsSent(emergencyNumber);
         processAllMessages();
         assertFalse(mPhoneUT.isInEmergencySmsMode());
 
-        // Device has FEATURE_TELEPHONY_CALLING
+        // Device has FEATURE_TELEPHONY_MESSAGING
         doReturn(true).when(mPackageManager).hasSystemFeature(
-                eq(PackageManager.FEATURE_TELEPHONY_CALLING));
+                eq(PackageManager.FEATURE_TELEPHONY_MESSAGING));
         mPhoneUT.notifySmsSent(emergencyNumber);
         processAllMessages();
         assertTrue(mPhoneUT.isInEmergencySmsMode());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index ba9bc74..4db6f56 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1373,6 +1373,60 @@
     }
 
     @Test
+    public void testSecondaryPciTimerExpire() throws Exception {
+        testTransitionToCurrentStateNrConnectedMmwave();
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+
+        mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
+                "connected_mmwave,any,10;connected,any,10;not_restricted_rrc_con,any,10");
+        mBundle.putInt(CarrierConfigManager.KEY_NR_ADVANCED_PCI_CHANGE_SECONDARY_TIMER_SECONDS_INT,
+                30);
+        sendCarrierConfigChanged();
+
+        // should trigger 10 second primary timer
+        doReturn(NetworkRegistrationInfo.NR_STATE_NONE).when(mServiceState).getNrState();
+        mNetworkTypeController.sendMessage(3 /* EVENT_SERVICE_STATE_CHANGED */);
+        processAllMessages();
+
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+        // Before primary timer expires, PCI changed, indicating 5G UW might soon recover
+        moveTimeForward(5 * 1000);
+        mNetworkTypeController.sendMessage(11 /* EVENT_PHYSICAL_CHANNEL_CONFIGS_CHANGED */,
+                new AsyncResult(null,
+                        List.of(new PhysicalChannelConfig.Builder()
+                                .setPhysicalCellId(2)
+                                .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+                                .setCellConnectionStatus(CellInfo.CONNECTION_PRIMARY_SERVING)
+                        .build()),
+                        null));
+        processAllMessages();
+
+        // primary timer expires
+        moveTimeForward(5 * 1000);
+        processAllMessages();
+
+        // should trigger 30 second secondary timer
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertTrue(mNetworkTypeController.areAnyTimersActive());
+
+        // secondary timer expires
+        moveTimeForward(30 * 1000);
+        processAllMessages();
+
+        assertEquals("legacy", getCurrentState().getName());
+        assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
+                mNetworkTypeController.getOverrideNetworkType());
+        assertFalse(mNetworkTypeController.areAnyTimersActive());
+    }
+
+    @Test
     public void testSecondaryTimerReset() throws Exception {
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         mBundle.putString(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_STRING,
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 7fb743c..0ac0b0e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -3915,6 +3915,13 @@
         processAllMessages();
 
         verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true));
+
+        // Deactivate the data, verify notify PCO gone.
+        mDataNetworkControllerUT.tearDownAllDataNetworks(
+                DataNetwork.TEAR_DOWN_REASON_AIRPLANE_MODE_ON);
+        processAllFutureMessages();
+
+        verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(false));
     }
 
     @Test