Merge changes I9cae479a,Ie642d780

* changes:
  Remove the multi-SIM bottom nav in network and internet v2 mode
  Add page listing multiple mobile networks
This commit is contained in:
TreeHugger Robot
2019-01-16 09:11:17 +00:00
committed by Android (Google) Code Review
11 changed files with 813 additions and 10 deletions

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Toolbar
android:id="@+id/mobile_action_bar"
style="?android:attr/actionBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:navigationContentDescription="@*android:string/action_bar_up_description"
android:theme="?android:attr/actionBarTheme"/>
<FrameLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>

View File

@@ -10344,6 +10344,34 @@
<!-- Mobile network settings screen, title of Mobile data switch preference [CHAR LIMIT=NONE] --> <!-- Mobile network settings screen, title of Mobile data switch preference [CHAR LIMIT=NONE] -->
<string name="mobile_data_settings_summary">Access data using mobile network</string> <string name="mobile_data_settings_summary">Access data using mobile network</string>
<!-- Summary of the 'Mobile network' item on the Network & internet page when there is no mobile
service setup yet (eg no SIM card inserted and no eSIM configured). Tapping it leads to a
UI where the user can setup service. [CHAR LIMIT=50] -->
<string name="mobile_network_summary_add_a_network">Add a network</string>
<!-- Summary of the 'Mobile network' item on the Network & internet page when there is more than
one mobile service configured (aka "dual SIM") - it shows a count of SIM/eSIM and tapping
it leads to a page showing a list of the mobile service subscriptions. [CHAR LIMIT=40] -->
<plurals name="mobile_network_summary_count">
<item quantity="one"><xliff:g id="count" example="1">%1$d</xliff:g> SIM</item>
<item quantity="other"><xliff:g id="count" example="2">%1$d</xliff:g> SIMs</item>
</plurals>
<!-- Title of item shown at the bottom of the page listing multiple mobile service
subscriptions; tapping it leads to a UI to add more [CHAR LIMIT=40] -->
<string name="mobile_network_list_add_more">Add more</string>
<!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
that service is active and is tied to a physical SIM card [CHAR LIMIT=40] -->
<string name="mobile_network_active_sim">Active SIM</string>
<!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
that service is inactive and is tied to a physical SIM card [CHAR LIMIT=40] -->
<string name="mobile_network_inactive_sim">Inactive SIM</string>
<!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
that service is active and is tied to an eSIM profile [CHAR LIMIT=40] -->
<string name="mobile_network_active_esim">Active eSIM</string>
<!-- Summary for an item in the page listing multiple mobile service subscriptions, indicating
that service is inactive and is tied to an eSIM profile [CHAR LIMIT=40] -->
<string name="mobile_network_inactive_esim">Inactive eSIM</string>
<!-- Title for preferred network type [CHAR LIMIT=NONE] --> <!-- Title for preferred network type [CHAR LIMIT=NONE] -->
<string name="preferred_network_mode_title">Preferred network type</string> <string name="preferred_network_mode_title">Preferred network type</string>
<!-- Summary for preferred network type [CHAR LIMIT=NONE] --> <!-- Summary for preferred network type [CHAR LIMIT=NONE] -->

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="mobile_network_list_screen"
android:title="@string/network_settings_title">
<Preference
android:key="add_more"
android:title="@string/mobile_network_list_add_more"
android:icon="@drawable/ic_menu_add"
android:order="100" />
</PreferenceScreen>

View File

@@ -40,15 +40,14 @@
</com.android.settings.widget.MasterSwitchPreference> </com.android.settings.widget.MasterSwitchPreference>
<com.android.settingslib.RestrictedPreference <com.android.settingslib.RestrictedPreference
android:key="mobile_network_settings" android:key="mobile_network_list"
android:title="@string/network_settings_title" android:title="@string/network_settings_title"
android:summary="@string/summary_placeholder" android:summary="@string/summary_placeholder"
android:icon="@drawable/ic_network_cell" android:icon="@drawable/ic_network_cell"
android:order="-15" android:order="-15"
settings:keywords="@string/keywords_more_mobile_networks" settings:keywords="@string/keywords_more_mobile_networks"
settings:userRestriction="no_config_mobile_networks" settings:userRestriction="no_config_mobile_networks"
settings:useAdminDisabledSummary="true"> settings:useAdminDisabledSummary="true" />
</com.android.settingslib.RestrictedPreference>
<com.android.settingslib.RestrictedSwitchPreference <com.android.settingslib.RestrictedSwitchPreference
android:key="toggle_airplane" android:key="toggle_airplane"

View File

@@ -0,0 +1,149 @@
/*
* 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;
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.ArrayMap;
import com.android.settings.R;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
import java.util.Map;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
/**
* This populates the entries on a page which lists all available mobile subscriptions. Each entry
* has the name of the subscription with some subtext giving additional detail, and clicking on the
* entry brings you to a details page for that network.
*/
public class MobileNetworkListController extends AbstractPreferenceController implements
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String TAG = "MobileNetworkListCtlr";
private SubscriptionManager mSubscriptionManager;
private SubscriptionsChangeListener mChangeListener;
private PreferenceScreen mPreferenceScreen;
private Map<Integer, Preference> mPreferences;
public MobileNetworkListController(Context context, Lifecycle lifecycle) {
super(context);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mChangeListener = new SubscriptionsChangeListener(context, this);
mPreferences = new ArrayMap<>();
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mChangeListener.start();
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
mChangeListener.stop();
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceScreen = screen;
update();
}
private void update() {
if (mPreferenceScreen == null) {
return;
}
// Since we may already have created some preferences previously, we first grab the list of
// those, then go through the current available subscriptions making sure they are all
// present in the screen, and finally remove any now-outdated ones.
final Map<Integer, Preference> existingPreferences = mPreferences;
mPreferences = new ArrayMap<>();
final List<SubscriptionInfo> subscriptions = SubscriptionUtil.getAvailableSubscriptions(
mSubscriptionManager);
for (SubscriptionInfo info : subscriptions) {
int subId = info.getSubscriptionId();
Preference pref = existingPreferences.remove(subId);
if (pref == null) {
pref = new Preference(mPreferenceScreen.getContext());
mPreferenceScreen.addPreference(pref);
}
pref.setTitle(info.getDisplayName());
if (info.isEmbedded()) {
if (mSubscriptionManager.isActiveSubscriptionId(subId)) {
pref.setSummary(R.string.mobile_network_active_esim);
} else {
pref.setSummary(R.string.mobile_network_inactive_esim);
}
} else {
if (mSubscriptionManager.isActiveSubscriptionId(subId)) {
pref.setSummary(R.string.mobile_network_active_sim);
} else {
pref.setSummary(R.string.mobile_network_inactive_sim);
}
}
pref.setOnPreferenceClickListener(clickedPref -> {
final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
intent.putExtra(Settings.EXTRA_SUB_ID, info.getSubscriptionId());
mContext.startActivity(intent);
return true;
});
mPreferences.put(subId, pref);
}
for (Preference pref : existingPreferences.values()) {
mPreferenceScreen.removePreference(pref);
}
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return null;
}
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
}
@Override
public void onSubscriptionsChanged() {
update();
}
}

View File

@@ -0,0 +1,71 @@
/*
* 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;
import android.content.Context;
import android.provider.SearchIndexableResource;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class MobileNetworkListFragment extends DashboardFragment {
private static final String LOG_TAG = "NetworkListFragment";
@Override
protected int getPreferenceScreenResId() {
return R.xml.mobile_network_list;
}
@Override
protected String getLogTag() {
return LOG_TAG;
}
@Override
public int getMetricsCategory() {
// TODO(asargent) - return SettingsEnums.MOBILE_NETWORK_LIST once the CL defining it has
// landed.
return 0;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new MobileNetworkListController(getContext(), getLifecycle()));
return controllers;
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.mobile_network_list;
result.add(sir);
return result;
}
};
}

View File

@@ -0,0 +1,147 @@
/*
* 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;
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settings.R;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
public class MobileNetworkSummaryController extends AbstractPreferenceController implements
SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver {
private static final String TAG = "MobileNetSummaryCtlr";
private static final String KEY = "mobile_network_list";
private SubscriptionManager mSubscriptionManager;
private SubscriptionsChangeListener mChangeListener;
private PreferenceScreen mScreen;
/**
* This controls the summary text and click behavior of the "Mobile network" item on the
* Network & internet page. There are 3 separate cases depending on the number of mobile network
* subscriptions:
* <ul>
* <li>No subscription: click action begins a UI flow to add a network subscription, and
* the summary text indicates this</li>
*
* <li>One subscription: click action takes you to details for that one network, and
* the summary text is the network name</li>
*
* <li>More than one subscription: click action takes you to a page listing the subscriptions,
* and the summary text gives the count of SIMs</li>
* </ul>
*/
public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
super(context);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mChangeListener = new SubscriptionsChangeListener(context, this);
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mChangeListener.start();
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
mChangeListener.stop();
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
}
@Override
public CharSequence getSummary() {
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
mSubscriptionManager);
if (subs.isEmpty()) {
return mContext.getResources().getString(R.string.mobile_network_summary_add_a_network);
} else if (subs.size() == 1) {
return subs.get(0).getDisplayName();
} else {
final int count = subs.size();
return mContext.getResources().getQuantityString(R.plurals.mobile_network_summary_count,
count, count);
}
}
private void update() {
if (mScreen != null) {
final Preference preference = mScreen.findPreference(getPreferenceKey());
refreshSummary(preference);
final List<SubscriptionInfo> subs = SubscriptionUtil.getAvailableSubscriptions(
mSubscriptionManager);
preference.setOnPreferenceClickListener(null);
preference.setFragment(null);
if (subs.size() == 0) {
preference.setOnPreferenceClickListener((Preference pref) -> {
// TODO(asargent) - need to get correct intent to fire here
return true;
});
} else if (subs.size() == 1) {
preference.setOnPreferenceClickListener((Preference pref) -> {
final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
mContext.startActivity(intent);
return true;
});
} else {
preference.setFragment(MobileNetworkListFragment.class.getCanonicalName());
}
}
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
}
@Override
public void onSubscriptionsChanged() {
update();
}
}

View File

@@ -96,8 +96,11 @@ public class NetworkDashboardFragment extends DashboardFragment implements
new MobilePlanPreferenceController(context, mobilePlanHost); new MobilePlanPreferenceController(context, mobilePlanHost);
final WifiMasterSwitchPreferenceController wifiPreferenceController = final WifiMasterSwitchPreferenceController wifiPreferenceController =
new WifiMasterSwitchPreferenceController(context, metricsFeatureProvider); new WifiMasterSwitchPreferenceController(context, metricsFeatureProvider);
final MobileNetworkPreferenceController mobileNetworkPreferenceController = MobileNetworkPreferenceController mobileNetworkPreferenceController = null;
new MobileNetworkPreferenceController(context); if (!FeatureFlagPersistent.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
mobileNetworkPreferenceController = new MobileNetworkPreferenceController(context);
}
final VpnPreferenceController vpnPreferenceController = final VpnPreferenceController vpnPreferenceController =
new VpnPreferenceController(context); new VpnPreferenceController(context);
final PrivateDnsPreferenceController privateDnsPreferenceController = final PrivateDnsPreferenceController privateDnsPreferenceController =
@@ -106,13 +109,21 @@ public class NetworkDashboardFragment extends DashboardFragment implements
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(mobilePlanPreferenceController); lifecycle.addObserver(mobilePlanPreferenceController);
lifecycle.addObserver(wifiPreferenceController); lifecycle.addObserver(wifiPreferenceController);
if (mobileNetworkPreferenceController != null) {
lifecycle.addObserver(mobileNetworkPreferenceController); lifecycle.addObserver(mobileNetworkPreferenceController);
}
lifecycle.addObserver(vpnPreferenceController); lifecycle.addObserver(vpnPreferenceController);
lifecycle.addObserver(privateDnsPreferenceController); lifecycle.addObserver(privateDnsPreferenceController);
} }
final List<AbstractPreferenceController> controllers = new ArrayList<>(); final List<AbstractPreferenceController> controllers = new ArrayList<>();
if (FeatureFlagPersistent.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
controllers.add(new MobileNetworkSummaryController(context, lifecycle));
}
if (mobileNetworkPreferenceController != null) {
controllers.add(mobileNetworkPreferenceController); controllers.add(mobileNetworkPreferenceController);
}
controllers.add(new TetherPreferenceController(context, lifecycle)); controllers.add(new TetherPreferenceController(context, lifecycle));
controllers.add(vpnPreferenceController); controllers.add(vpnPreferenceController);
controllers.add(new ProxyPreferenceController(context)); controllers.add(new ProxyPreferenceController(context));

View File

@@ -37,7 +37,9 @@ import androidx.fragment.app.FragmentTransaction;
import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.CollectionUtils; import com.android.internal.util.CollectionUtils;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SettingsBaseActivity; import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.development.featureflags.FeatureFlagPersistent;
import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -77,7 +79,11 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (FeatureFlagPersistent.isEnabled(this, FeatureFlags.NETWORK_INTERNET_V2)) {
setContentView(R.layout.mobile_network_settings_container_v2);
} else {
setContentView(R.layout.mobile_network_settings_container); setContentView(R.layout.mobile_network_settings_container);
}
setActionBar(findViewById(R.id.mobile_action_bar)); setActionBar(findViewById(R.id.mobile_action_bar));
mPhoneChangeReceiver = new PhoneChangeReceiver(); mPhoneChangeReceiver = new PhoneChangeReceiver();
mSubscriptionManager = getSystemService(SubscriptionManager.class); mSubscriptionManager = getSystemService(SubscriptionManager.class);
@@ -132,7 +138,9 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
void updateSubscriptions(Bundle savedInstanceState) { void updateSubscriptions(Bundle savedInstanceState) {
mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList(); mSubscriptionInfos = mSubscriptionManager.getActiveSubscriptionInfoList();
if (!FeatureFlagPersistent.isEnabled(this, FeatureFlags.NETWORK_INTERNET_V2)) {
updateBottomNavigationView(); updateBottomNavigationView();
}
if (savedInstanceState == null) { if (savedInstanceState == null) {
switchFragment(new MobileNetworkSettings(), getSubscriptionId()); switchFragment(new MobileNetworkSettings(), getSubscriptionId());

View File

@@ -0,0 +1,152 @@
/*
* 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;
import static android.provider.Settings.EXTRA_SUB_ID;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import androidx.lifecycle.Lifecycle;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
public class MobileNetworkListControllerTest {
@Mock
private Lifecycle mLifecycle;
@Mock
private PreferenceScreen mPreferenceScreen;
private Context mContext;
private MobileNetworkListController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
when(mPreferenceScreen.getContext()).thenReturn(mContext);
mController = new MobileNetworkListController(mContext, mLifecycle);
}
@After
public void tearDown() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
}
@Test
public void displayPreference_noSubscriptions_noCrash() {
mController.displayPreference(mPreferenceScreen);
mController.onResume();
}
@Test
public void displayPreference_twoSubscriptions_correctlySetup() {
final SubscriptionInfo sub1 = createMockSubscription(1, "sub1");
final SubscriptionInfo sub2 = createMockSubscription(2, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
// Check that the preferences get created with the correct titles.
final ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(
Preference.class);
verify(mPreferenceScreen, times(2)).addPreference(preferenceCaptor.capture());
final Preference pref1 = preferenceCaptor.getAllValues().get(0);
final Preference pref2 = preferenceCaptor.getAllValues().get(1);
assertThat(pref1.getTitle()).isEqualTo("sub1");
assertThat(pref2.getTitle()).isEqualTo("sub2");
// Check that the onclick listeners are setup to fire with the right subscription id.
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
pref1.getOnPreferenceClickListener().onPreferenceClick(pref1);
pref2.getOnPreferenceClickListener().onPreferenceClick(pref2);
verify(mContext, times(2)).startActivity(intentCaptor.capture());
final Intent intent1 = intentCaptor.getAllValues().get(0);
final Intent intent2 = intentCaptor.getAllValues().get(1);
assertThat(intent1.getIntExtra(EXTRA_SUB_ID, INVALID_SUBSCRIPTION_ID)).isEqualTo(1);
assertThat(intent2.getIntExtra(EXTRA_SUB_ID, INVALID_SUBSCRIPTION_ID)).isEqualTo(2);
}
@Test
public void onSubscriptionsChanged_twoSubscriptionsOneChangesName_preferenceUpdated() {
final SubscriptionInfo sub1 = createMockSubscription(1, "sub1");
final SubscriptionInfo sub2 = createMockSubscription(2, "sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
final ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(
Preference.class);
verify(mPreferenceScreen, times(2)).addPreference(preferenceCaptor.capture());
when(sub2.getDisplayName()).thenReturn("new name");
mController.onSubscriptionsChanged();
assertThat(preferenceCaptor.getAllValues().get(1).getTitle()).isEqualTo("new name");
}
@Test
public void onSubscriptionsChanged_startWithThreeSubsAndRemoveOne_correctPreferenceRemoved() {
final SubscriptionInfo sub1 = createMockSubscription(1, "sub1");
final SubscriptionInfo sub2 = createMockSubscription(2, "sub2");
final SubscriptionInfo sub3 = createMockSubscription(3, "sub3");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2, sub3));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
final ArgumentCaptor<Preference> preferenceCaptor = ArgumentCaptor.forClass(
Preference.class);
verify(mPreferenceScreen, times(3)).addPreference(preferenceCaptor.capture());
// remove sub2, and check that the second pref was removed from the screen
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub3));
mController.onSubscriptionsChanged();
final ArgumentCaptor<Preference> removedPrefCaptor = ArgumentCaptor.forClass(
Preference.class);
verify(mPreferenceScreen).removePreference(removedPrefCaptor.capture());
assertThat(removedPrefCaptor.getValue().getTitle()).isEqualTo("sub2");
}
private SubscriptionInfo createMockSubscription(int id, String displayName) {
final SubscriptionInfo sub = mock(SubscriptionInfo.class);
when(sub.getSubscriptionId()).thenReturn(id);
when(sub.getDisplayName()).thenReturn(displayName);
return sub;
}
}

View File

@@ -0,0 +1,171 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.telephony.SubscriptionInfo;
import com.android.settings.network.telephony.MobileNetworkActivity;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import androidx.lifecycle.Lifecycle;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
public class MobileNetworkSummaryControllerTest {
@Mock
private Lifecycle mLifecycle;
@Mock
PreferenceScreen mPreferenceScreen;
Preference mPreference;
private Context mContext;
private MobileNetworkSummaryController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
mController = new MobileNetworkSummaryController(mContext, mLifecycle);
mPreference = new Preference(mContext);
mPreference.setKey(mController.getPreferenceKey());
when(mPreferenceScreen.findPreference(eq(mController.getPreferenceKey()))).thenReturn(
mPreference);
}
@After
public void tearDown() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
}
@Test
public void getSummary_noSubscriptions_correctSummary() {
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("Add a network");
}
@Test
public void getSummary_oneSubscription_correctSummaryAndClickHandler() {
SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub1.getDisplayName()).thenReturn("sub1");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
}
@Test
public void getSummary_twoSubscriptions_correctSummaryAndFragment() {
SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("2 SIMs");
assertThat(mPreference.getFragment()).isEqualTo(MobileNetworkListFragment.class.getName());
}
@Test
public void getSummaryAfterUpdate_twoSubscriptionsBecomesOne_correctSummaryAndFragment() {
SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
when(sub1.getDisplayName()).thenReturn("sub1");
when(sub2.getDisplayName()).thenReturn("sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("2 SIMs");
assertThat(mPreference.getFragment()).isEqualTo(MobileNetworkListFragment.class.getName());
// Simulate sub2 having disappeared - the end result should change to be the same as
// if there were just one subscription.
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
mController.onSubscriptionsChanged();
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
}
@Test
public void getSummaryAfterUpdate_oneSubscriptionBecomesTwo_correctSummaryAndFragment() {
SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
when(sub1.getDisplayName()).thenReturn("sub1");
when(sub2.getDisplayName()).thenReturn("sub2");
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("sub1");
assertThat(mPreference.getFragment()).isNull();
mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
assertThat(intentCaptor.getValue().getComponent().getClassName()).isEqualTo(
MobileNetworkActivity.class.getName());
// Simulate sub2 appearing in the list of subscriptions and check the results.
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.displayPreference(mPreferenceScreen);
mController.onResume();
assertThat(mController.getSummary()).isEqualTo("2 SIMs");
assertThat(mPreference.getFragment()).isEqualTo(MobileNetworkListFragment.class.getName());
}
}