Merge "[Settings] Move mobile data template out of framework" into rvc-dev
diff --git a/src/com/android/settings/datausage/BillingCyclePreferenceController.java b/src/com/android/settings/datausage/BillingCyclePreferenceController.java
index 88bf63c..2f144cb 100644
--- a/src/com/android/settings/datausage/BillingCyclePreferenceController.java
+++ b/src/com/android/settings/datausage/BillingCyclePreferenceController.java
@@ -26,11 +26,12 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
-import com.android.settings.core.BasePreferenceController;
-import com.android.settingslib.NetworkPolicyEditor;
-
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.datausage.lib.DataUsageLib;
+import com.android.settingslib.NetworkPolicyEditor;
+
 public class BillingCyclePreferenceController extends BasePreferenceController {
     private int mSubscriptionId;
 
@@ -58,7 +59,7 @@
         services.mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
         services.mUserManager = mContext.getSystemService(UserManager.class);
 
-        NetworkTemplate template = DataUsageUtils.getMobileTemplate(mContext, mSubscriptionId);
+        NetworkTemplate template = DataUsageLib.getMobileTemplate(mContext, mSubscriptionId);
 
         preference.setTemplate(template, mSubscriptionId, services);
     }
diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java
index 7b67a02..9d9bf9c 100644
--- a/src/com/android/settings/datausage/DataUsageSummary.java
+++ b/src/com/android/settings/datausage/DataUsageSummary.java
@@ -33,6 +33,7 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.datausage.lib.DataUsageLib;
 import com.android.settings.network.ProxySubscriptionManager;
 import com.android.settingslib.NetworkPolicyEditor;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -166,7 +167,7 @@
     private void addMobileSection(int subId, SubscriptionInfo subInfo) {
         TemplatePreferenceCategory category = (TemplatePreferenceCategory)
                 inflatePreferences(R.xml.data_usage_cellular);
-        category.setTemplate(DataUsageUtils.getMobileTemplate(getContext(), subId),
+        category.setTemplate(DataUsageLib.getMobileTemplate(getContext(), subId),
                 subId, services);
         category.pushTemplates(services);
         if (subInfo != null && !TextUtils.isEmpty(subInfo.getDisplayName())) {
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
index 4178f6c..97cf599 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java
@@ -39,6 +39,7 @@
 import com.android.internal.util.CollectionUtils;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.datausage.lib.DataUsageLib;
 import com.android.settings.network.ProxySubscriptionManager;
 import com.android.settings.network.telephony.TelephonyBasePreferenceController;
 import com.android.settings.widget.EntityHeaderController;
@@ -134,7 +135,7 @@
 
         if (subInfo != null) {
             mDataUsageTemplate = R.string.cell_data_template;
-            mDefaultTemplate = DataUsageUtils.getMobileTemplate(context, subscriptionId);
+            mDefaultTemplate = DataUsageLib.getMobileTemplate(context, subscriptionId);
         } else if (DataUsageUtils.hasWifiRadio(context)) {
             mDataUsageTemplate = R.string.wifi_data_template;
             mDefaultTemplate = NetworkTemplate.buildTemplateWifiWildcard();
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 6cdf210..da0ca63 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -33,6 +33,7 @@
 import android.text.format.Formatter.BytesResult;
 import android.util.Log;
 
+import com.android.settings.datausage.lib.DataUsageLib;
 import com.android.settings.network.ProxySubscriptionManager;
 
 import java.util.List;
@@ -183,7 +184,7 @@
      */
     public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
         if (SubscriptionManager.isValidSubscriptionId(defaultSubId) && hasMobileData(context)) {
-            return getMobileTemplate(context, defaultSubId);
+            return DataUsageLib.getMobileTemplate(context, defaultSubId);
         } else if (hasWifiRadio(context)) {
             return NetworkTemplate.buildTemplateWifiWildcard();
         } else {
diff --git a/src/com/android/settings/datausage/lib/DataUsageLib.java b/src/com/android/settings/datausage/lib/DataUsageLib.java
new file mode 100644
index 0000000..cf2ce1f
--- /dev/null
+++ b/src/com/android/settings/datausage/lib/DataUsageLib.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 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.settings.datausage.lib;
+
+import android.content.Context;
+import android.net.NetworkTemplate;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.List;
+
+/**
+ * Lib class for data usage
+ */
+public class DataUsageLib {
+    private static final String TAG = "DataUsageLib";
+
+    /**
+     * Return mobile NetworkTemplate based on {@code subId}
+     */
+    public static NetworkTemplate getMobileTemplate(Context context, int subId) {
+        final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        final int mobileDefaultSubId = telephonyManager.getSubscriptionId();
+
+        final SubscriptionManager subscriptionManager =
+                context.getSystemService(SubscriptionManager.class);
+        final List<SubscriptionInfo> subInfoList =
+                subscriptionManager.getAvailableSubscriptionInfoList();
+        if (subInfoList == null) {
+            Log.i(TAG, "Subscription is not inited: " + subId);
+            return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
+        }
+
+        for (SubscriptionInfo subInfo : subInfoList) {
+            if ((subInfo != null) && (subInfo.getSubscriptionId() == subId)) {
+                return getNormalizedMobileTemplate(telephonyManager, subId);
+            }
+        }
+        Log.i(TAG, "Subscription is not active: " + subId);
+        return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
+    }
+
+    private static NetworkTemplate getNormalizedMobileTemplate(
+            TelephonyManager telephonyManager, int subId) {
+        final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
+        final String[] mergedSubscriberIds = telephonyManager
+                .createForSubscriptionId(subId).getMergedImsisFromGroup();
+        if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
+            Log.i(TAG, "mergedSubscriberIds is null.");
+            return mobileTemplate;
+        }
+
+        return NetworkTemplate.normalize(mobileTemplate, mergedSubscriberIds);
+    }
+
+    private static NetworkTemplate getMobileTemplateForSubId(
+            TelephonyManager telephonyManager, int subId) {
+        return NetworkTemplate.buildTemplateMobileAll(telephonyManager.getSubscriberId(subId));
+    }
+}
diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
index 08524d6..40eb549 100644
--- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
@@ -29,6 +29,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.datausage.lib.DataUsageLib;
 import com.android.settingslib.net.DataUsageController;
 import com.android.settingslib.utils.ThreadUtils;
 
@@ -99,7 +100,7 @@
         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             return null;
         }
-        return DataUsageUtils.getMobileTemplate(context, subId);
+        return DataUsageLib.getMobileTemplate(context, subId);
     }
 
     private NetworkTemplate getNetworkTemplate() {
diff --git a/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
new file mode 100644
index 0000000..8d994d0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/datausage/lib/DataUsageLibTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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.settings.datausage.lib;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.NetworkTemplate;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class DataUsageLibTest {
+
+    private static final int SUB_ID = 1;
+    private static final int SUB_ID_2 = 2;
+    private static final String SUBSCRIBER_ID = "Test Subscriber";
+    private static final String SUBSCRIBER_ID_2 = "Test Subscriber 2";
+
+    @Mock
+    private TelephonyManager mTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
+    @Mock
+    private SubscriptionInfo mInfo1;
+    @Mock
+    private SubscriptionInfo mInfo2;
+    @Mock
+    private ParcelUuid mParcelUuid;
+    private Context mContext;
+    private List<SubscriptionInfo> mInfos;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = spy(RuntimeEnvironment.application);
+        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+        when(mTelephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID);
+        when(mTelephonyManager.getSubscriberId(SUB_ID_2)).thenReturn(SUBSCRIBER_ID_2);
+        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+        when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true);
+    }
+
+    @Test
+    @Ignore
+    public void getMobileTemplate_infoNull_returnMobileAll() {
+        when(mSubscriptionManager.isActiveSubscriptionId(SUB_ID)).thenReturn(false);
+
+        final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+    }
+
+    @Test
+    @Ignore
+    public void getMobileTemplate_groupUuidNull_returnMobileAll() {
+        when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
+        when(mInfo1.getGroupUuid()).thenReturn(null);
+        when(mTelephonyManager.getMergedImsisFromGroup())
+                .thenReturn(new String[] {SUBSCRIBER_ID});
+
+        final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
+    }
+
+    @Test
+    @Ignore
+    public void getMobileTemplate_groupUuidExist_returnMobileMerged() {
+        when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
+        when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid);
+        when(mTelephonyManager.getMergedImsisFromGroup())
+                .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
+
+        final NetworkTemplate networkTemplate = DataUsageLib.getMobileTemplate(mContext, SUB_ID);
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
+        assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isTrue();
+    }
+}