Merge "The Settings ANR when allowed network type never was loaded" into sc-dev
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index 0c6cc92..429f7f9 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -457,10 +457,10 @@
             // 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);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index 8d60477..2156e66 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.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 @@
     /**
      * 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 @@
 
         boolean isAnyDataCallDormant = false;
         boolean isAnyDataCallActive = false;
+        boolean isInternetDataCallActive = false;
 
         for (DataCallResponse newState : dcsList) {
 
@@ -249,6 +251,11 @@
                     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 @@
 
         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 @@
 
     /**
      * 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/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index a05fa03..bfc5915 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 @@
     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;
 
@@ -5597,13 +5600,21 @@
                         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/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index c92d4f9..1161792 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 @@
                 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/dataconnection/DcControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
index 3c8e7ab..003f74e 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_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.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.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 @@
 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 @@
     private List<ApnContext> mApnContexts;
     @Mock
     private DataServiceManager mDataServiceManager;
+    @Mock
+    private Handler mTestHandler;
 
     UpdateLinkPropertyResult mResult;
 
@@ -142,4 +152,131 @@
 
         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