diff --git a/res/xml/mobile_network_settings_v2.xml b/res/xml/mobile_network_settings_v2.xml new file mode 100644 index 00000000000..7a19c325334 --- /dev/null +++ b/res/xml/mobile_network_settings_v2.xml @@ -0,0 +1,155 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java index 8bf54a7ed82..36614103184 100644 --- a/src/com/android/settings/datausage/DataUsageSummary.java +++ b/src/com/android/settings/datausage/DataUsageSummary.java @@ -141,7 +141,8 @@ public class DataUsageSummary extends DataUsageBaseFragment implements DataUsage final Activity activity = getActivity(); final ArrayList controllers = new ArrayList<>(); mSummaryController = - new DataUsageSummaryPreferenceController(activity, getSettingsLifecycle(), this); + new DataUsageSummaryPreferenceController(activity, getSettingsLifecycle(), this, + DataUsageUtils.getDefaultSubscriptionId(activity)); controllers.add(mSummaryController); getSettingsLifecycle().addObserver(mSummaryController); return controllers; diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java index d5707c4ac6f..353c5ee27bb 100644 --- a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java +++ b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.java @@ -31,6 +31,7 @@ import android.util.RecurrenceRule; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; +import androidx.preference.PreferenceFragmentCompat; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.util.CollectionUtils; @@ -47,9 +48,9 @@ import com.android.settingslib.net.DataUsageController; import java.util.List; /** - * This is the controller for the top of the data usage screen that retrieves carrier data from the - * new subscriptions framework API if available. The controller reads subscription information from - * the framework and falls back to legacy usage data if none are available. + * This is the controller for a data usage header that retrieves carrier data from the new + * subscriptions framework API if available. The controller reads subscription information from the + * framework and falls back to legacy usage data if none are available. */ public class DataUsageSummaryPreferenceController extends BasePreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnStart { @@ -63,7 +64,7 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll private final Activity mActivity; private final EntityHeaderController mEntityHeaderController; private final Lifecycle mLifecycle; - private final DataUsageSummary mDataUsageSummary; + private final PreferenceFragmentCompat mFragment; private final DataUsageController mDataUsageController; private final DataUsageInfoController mDataInfoController; private final NetworkTemplate mDefaultTemplate; @@ -94,28 +95,31 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll private long mCycleStart; /** The ending time of the billing cycle in ms since the epoch */ private long mCycleEnd; + /** The subscription that we should show usage for. */ + private int mSubscriptionId; private Intent mManageSubscriptionIntent; public DataUsageSummaryPreferenceController(Activity activity, - Lifecycle lifecycle, DataUsageSummary dataUsageSummary) { + Lifecycle lifecycle, PreferenceFragmentCompat fragment, int subscriptionId) { super(activity, KEY); mActivity = activity; mEntityHeaderController = EntityHeaderController.newInstance(activity, - dataUsageSummary, null); + fragment, null); mLifecycle = lifecycle; - mDataUsageSummary = dataUsageSummary; + mFragment = fragment; + mSubscriptionId = subscriptionId; - final int defaultSubId = DataUsageUtils.getDefaultSubscriptionId(activity); - mDefaultTemplate = DataUsageUtils.getDefaultTemplate(activity, defaultSubId); - NetworkPolicyManager policyManager = NetworkPolicyManager.from(activity); + mDefaultTemplate = DataUsageUtils.getDefaultTemplate(activity, mSubscriptionId); + NetworkPolicyManager policyManager = activity.getSystemService(NetworkPolicyManager.class); mPolicyEditor = new NetworkPolicyEditor(policyManager); mHasMobileData = DataUsageUtils.hasMobileData(activity) - && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID; + && mSubscriptionId != SubscriptionManager.INVALID_SUBSCRIPTION_ID; mDataUsageController = new DataUsageController(activity); + mDataUsageController.setSubscriptionId(mSubscriptionId); mDataInfoController = new DataUsageInfoController(); if (mHasMobileData) { @@ -142,7 +146,8 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll Activity activity, Lifecycle lifecycle, EntityHeaderController entityHeaderController, - DataUsageSummary dataUsageSummary) { + PreferenceFragmentCompat fragment, + int subscriptionId) { super(activity, KEY); mDataUsageController = dataUsageController; mDataInfoController = dataInfoController; @@ -154,12 +159,13 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll mActivity = activity; mLifecycle = lifecycle; mEntityHeaderController = entityHeaderController; - mDataUsageSummary = dataUsageSummary; + mFragment = fragment; + mSubscriptionId = subscriptionId; } @Override public void onStart() { - RecyclerView view = mDataUsageSummary.getListView(); + RecyclerView view = mFragment.getListView(); mEntityHeaderController.setRecyclerView(view, mLifecycle); mEntityHeaderController.styleActionBar(mActivity); } @@ -260,12 +266,18 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll mCycleEnd = info.cycleEnd; mSnapshotTime = -1L; - final int defaultSubId = SubscriptionManager.getDefaultSubscriptionId(); - final SubscriptionInfo subInfo = mSubscriptionManager.getDefaultDataSubscriptionInfo(); + SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(mSubscriptionId); + if (subInfo == null) { + subInfo = mSubscriptionManager.getAllSubscriptionInfoList().stream().filter( + i -> i.getSubscriptionId() == mSubscriptionId).findFirst().orElse(null); + } if (subInfo != null && mHasMobileData) { mCarrierName = subInfo.getCarrierName(); - List plans = mSubscriptionManager.getSubscriptionPlans(defaultSubId); - final SubscriptionPlan primaryPlan = getPrimaryPlan(mSubscriptionManager, defaultSubId); + List plans = mSubscriptionManager.getSubscriptionPlans( + mSubscriptionId); + final SubscriptionPlan primaryPlan = getPrimaryPlan(mSubscriptionManager, + mSubscriptionId); + if (primaryPlan != null) { mDataplanCount = plans.size(); mDataplanSize = primaryPlan.getDataLimitBytes(); @@ -284,8 +296,8 @@ public class DataUsageSummaryPreferenceController extends BasePreferenceControll } } mManageSubscriptionIntent = - mSubscriptionManager.createManageSubscriptionIntent(defaultSubId); - Log.i(TAG, "Have " + mDataplanCount + " plans, dflt sub-id " + defaultSubId + mSubscriptionManager.createManageSubscriptionIntent(mSubscriptionId); + Log.i(TAG, "Have " + mDataplanCount + " plans, dflt sub-id " + mSubscriptionId + ", intent " + mManageSubscriptionIntent); } diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index 6e5dece5a01..9665c093da5 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -34,7 +34,10 @@ import androidx.preference.Preference; import com.android.internal.telephony.TelephonyIntents; import com.android.settings.R; +import com.android.settings.core.FeatureFlags; import com.android.settings.dashboard.RestrictedDashboardFragment; +import com.android.settings.datausage.DataUsageSummaryPreferenceController; +import com.android.settings.development.featureflags.FeatureFlagPersistent; import com.android.settings.network.telephony.cdma.CdmaSubscriptionPreferenceController; import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController; import com.android.settings.network.telephony.gsm.AutoSelectPreferenceController; @@ -42,6 +45,7 @@ import com.android.settings.network.telephony.gsm.OpenNetworkSelectPagePreferenc import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.widget.PreferenceCategoryController; +import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; @@ -105,12 +109,23 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment { } @Override - public void onAttach(Context context) { - super.onAttach(context); - + protected List createPreferenceControllers(Context context) { mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2) && + mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return Arrays.asList( + new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(), + this, mSubId)); + } + return Arrays.asList(); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId); use(ApnPreferenceController.class).init(mSubId); @@ -163,7 +178,11 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment { @Override protected int getPreferenceScreenResId() { - return R.xml.mobile_network_settings; + if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2)) { + return R.xml.mobile_network_settings_v2; + } else { + return R.xml.mobile_network_settings; + } } @Override diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java index d1cb63ed177..43476371423 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.java @@ -34,11 +34,11 @@ import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkTemplate; -import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import androidx.fragment.app.FragmentActivity; +import androidx.preference.PreferenceFragmentCompat; import androidx.recyclerview.widget.RecyclerView; import com.android.internal.logging.nano.MetricsProto; @@ -92,7 +92,7 @@ public class DataUsageSummaryPreferenceControllerTest { @Mock(answer = Answers.RETURNS_DEEP_STUBS) private EntityHeaderController mHeaderController; @Mock - private DataUsageSummary mDataUsageSummary; + private PreferenceFragmentCompat mPreferenceFragment; @Mock private TelephonyManager mTelephonyManager; @Mock @@ -104,6 +104,7 @@ public class DataUsageSummaryPreferenceControllerTest { private FragmentActivity mActivity; private Context mContext; private DataUsageSummaryPreferenceController mController; + private int mDefaultSubscriptionId; @Before public void setUp() { @@ -125,6 +126,7 @@ public class DataUsageSummaryPreferenceControllerTest { .thenReturn(mConnectivityManager); when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_READY); when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(false); + mDefaultSubscriptionId = 1234; mController = new DataUsageSummaryPreferenceController( mDataUsageController, mDataInfoController, @@ -133,7 +135,7 @@ public class DataUsageSummaryPreferenceControllerTest { R.string.cell_data_template, true, null, - mActivity, null, null, null); + mActivity, null, null, null, mDefaultSubscriptionId); } @After @@ -355,11 +357,7 @@ public class DataUsageSummaryPreferenceControllerTest { R.string.cell_data_template, true, mSubscriptionManager, - mActivity, null, null, null); - - final SubscriptionInfo subInfo = new SubscriptionInfo(0, "123456", 0, "name", "carrier", - 0, 0, "number", 0, null, "123", "456", "ZX", false, null, null); - when(mSubscriptionManager.getDefaultDataSubscriptionInfo()).thenReturn(subInfo); + mActivity, null, null, null, mDefaultSubscriptionId); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); } @@ -373,7 +371,7 @@ public class DataUsageSummaryPreferenceControllerTest { R.string.cell_data_template, true, mSubscriptionManager, - mActivity, null, null, null); + mActivity, null, null, null, mDefaultSubscriptionId); when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT); when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(false); @@ -390,7 +388,7 @@ public class DataUsageSummaryPreferenceControllerTest { R.string.cell_data_template, true, mSubscriptionManager, - mActivity, null, null, null); + mActivity, null, null, null, mDefaultSubscriptionId); when(mTelephonyManager.getSimState()).thenReturn(TelephonyManager.SIM_STATE_ABSENT); when(mConnectivityManager.isNetworkSupported(TYPE_WIFI)).thenReturn(true); @@ -409,9 +407,10 @@ public class DataUsageSummaryPreferenceControllerTest { R.string.cell_data_template, true, mSubscriptionManager, - mActivity, mLifecycle, mHeaderController, mDataUsageSummary); + mActivity, mLifecycle, mHeaderController, mPreferenceFragment, + mDefaultSubscriptionId); - when(mDataUsageSummary.getListView()).thenReturn(recyclerView); + when(mPreferenceFragment.getListView()).thenReturn(recyclerView); mController.onStart(); diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java new file mode 100644 index 00000000000..0240bd834f8 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2019 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.network.telephony; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.app.usage.NetworkStatsManager; +import android.content.Context; +import android.net.NetworkPolicyManager; +import android.os.Bundle; +import android.provider.Settings; +import android.telephony.TelephonyManager; + +import com.android.settings.core.FeatureFlags; +import com.android.settings.datausage.DataUsageSummaryPreferenceController; +import com.android.settings.development.featureflags.FeatureFlagPersistent; +import com.android.settings.testutils.shadow.ShadowEntityHeaderController; +import com.android.settings.widget.EntityHeaderController; +import com.android.settingslib.core.AbstractPreferenceController; + +import org.junit.Before; +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 org.robolectric.annotation.Config; + +import java.util.List; + +import androidx.fragment.app.FragmentActivity; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowEntityHeaderController.class) +public class MobileNetworkSettingsTest { + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private NetworkStatsManager mNetworkStatsManager; + @Mock + private NetworkPolicyManager mNetworkPolicyManager; + @Mock + private FragmentActivity mActivity; + + private Context mContext; + private MobileNetworkSettings mFragment; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); + when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager); + ShadowEntityHeaderController.setUseMock(mock(EntityHeaderController.class)); + + mFragment = spy(new MobileNetworkSettings()); + final Bundle args = new Bundle(); + final int subscriptionId = 1234; + args.putInt(Settings.EXTRA_SUB_ID, subscriptionId); + mFragment.setArguments(args); + when(mFragment.getActivity()).thenReturn(mActivity); + when(mActivity.getSystemService(NetworkPolicyManager.class)).thenReturn( + mNetworkPolicyManager); + } + + @Test + public void onAttach_noCrash() { + mFragment.onAttach(mContext); + } + + @Test + public void createPreferenceControllers_noV2Flag_noDataUsageSummaryController() { + final List controllers = + mFragment.createPreferenceControllers(mContext); + assertThat(controllers.stream().filter( + c -> c.getClass().equals(DataUsageSummaryPreferenceController.class)) + .count()) + .isEqualTo(0); + } + + @Test + public void createPreferenceControllers_v2Flag_createsDataUsageSummaryController() { + FeatureFlagPersistent.setEnabled(mContext, FeatureFlags.NETWORK_INTERNET_V2, true); + + final List controllers = + mFragment.createPreferenceControllers(mContext); + assertThat(controllers.stream().filter( + c -> c.getClass().equals(DataUsageSummaryPreferenceController.class)) + .count()) + .isEqualTo(1); + } +}