diff --git a/res/values/strings.xml b/res/values/strings.xml index 2636e6e6573..5f47c8ce66a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2832,6 +2832,10 @@ On / Screen won\u2019t turn off if you\u2019re looking at it Off + + Camera access needed + + Tap to manage permissions for Device Personalization Services Prevents your screen from turning off if you\u2019re looking at it @@ -3078,8 +3082,8 @@ Kernel version Build number - - Mainline module versions + + Google Play system update Not available diff --git a/res/xml/mobile_network_settings_v2.xml b/res/xml/mobile_network_settings_v2.xml index 20ed1c75a22..506b354ba42 100644 --- a/res/xml/mobile_network_settings_v2.xml +++ b/res/xml/mobile_network_settings_v2.xml @@ -203,4 +203,14 @@ android:title="@string/mobile_network_erase_sim" settings:controller="com.android.settings.network.telephony.DeleteSimProfilePreferenceController" /> + + + + diff --git a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java index 5ce7be5b43e..ab7465cfd3f 100644 --- a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java @@ -21,8 +21,11 @@ import android.content.Context; import androidx.preference.Preference; public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController { + private final Context mContext; + public AdaptiveSleepDetailPreferenceController(Context context, String key) { super(context, key); + mContext = context; } @Override @@ -42,6 +45,7 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer @Override public void updateState(Preference preference) { super.updateState(preference); - preference.setEnabled(super.hasSufficientPermissions); + preference.setEnabled(AdaptiveSleepPreferenceController.hasSufficientPermission( + mContext.getPackageManager())); } -} +} \ No newline at end of file diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java index e83410d3d7a..f9828d77fcd 100644 --- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java @@ -29,7 +29,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle private static final String SYSTEM_KEY = ADAPTIVE_SLEEP; private static final int DEFAULT_VALUE = 0; - final boolean hasSufficientPermissions; + private final boolean hasSufficientPermissions; public AdaptiveSleepPreferenceController(Context context, String key) { super(context, key); @@ -71,7 +71,7 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle : UNSUPPORTED_ON_DEVICE; } - private static boolean hasSufficientPermission(PackageManager packageManager) { + static boolean hasSufficientPermission(PackageManager packageManager) { final String attentionPackage = packageManager.getAttentionServicePackageName(); return attentionPackage != null && packageManager.checkPermission( Manifest.permission.CAMERA, attentionPackage) == PackageManager.PERMISSION_GRANTED; diff --git a/src/com/android/settings/display/AdaptiveSleepSettings.java b/src/com/android/settings/display/AdaptiveSleepSettings.java index d0f2c9aa0b1..94abe1aba0d 100644 --- a/src/com/android/settings/display/AdaptiveSleepSettings.java +++ b/src/com/android/settings/display/AdaptiveSleepSettings.java @@ -16,16 +16,21 @@ package com.android.settings.display; +import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED; import android.app.settings.SettingsEnums; import android.content.Context; -import android.content.SharedPreferences; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; import android.provider.SearchIndexableResource; -import android.util.Log; +import androidx.preference.Preference; + +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -39,23 +44,45 @@ import java.util.List; public class AdaptiveSleepSettings extends DashboardFragment { private static final String TAG = "AdaptiveSleepSettings"; + private Context mContext; + private String mPackageName; + private PackageManager mPackageManager; + + @VisibleForTesting + Preference mPermissionRequiredPreference; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); final FooterPreference footerPreference = mFooterPreferenceMixin.createFooterPreference(); - final Context context = getContext(); + mContext = getContext(); + mPermissionRequiredPreference = createPermissionMissionPreference(); footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp); footerPreference.setTitle(R.string.adaptive_sleep_privacy); - context.getSharedPreferences(PREF, Context.MODE_PRIVATE) + getPreferenceScreen().addPreference(mPermissionRequiredPreference); + mPermissionRequiredPreference.setVisible(false); + mPackageManager = mContext.getPackageManager(); + mPackageName = mPackageManager.getAttentionServicePackageName(); + mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE) .edit() .putBoolean(PREF_KEY_INTERACTED, true) .apply(); } + @Override + public void onResume() { + super.onResume(); + if (!hasSufficientPermission(mPackageManager)) { + mPermissionRequiredPreference.setVisible(true); + } + else { + mPermissionRequiredPreference.setVisible(false); + } + } + @Override protected int getPreferenceScreenResId() { return R.xml.adaptive_sleep_detail; @@ -86,4 +113,29 @@ public class AdaptiveSleepSettings extends DashboardFragment { return Arrays.asList(sir); } }; + + private Preference createPermissionMissionPreference() { + Preference preference = new Preference(mContext, null); + preference.setIcon(R.drawable.ic_info_outline_24); + // Makes sure it's above the toggle. + preference.setOrder(1); + preference.setPersistent(true); + preference.setTitle(R.string.adaptive_sleep_title_no_permission); + preference.setSummary(R.string.adaptive_sleep_summary_no_permission); + preference.setOnPreferenceClickListener(p -> { + final Intent intent = new Intent( + android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.setData(Uri.parse("package:" + mPackageName)); + mContext.startActivity(intent); + return true; + }); + return preference; + } + + @VisibleForTesting + void setupForTesting(PackageManager packageManager, Context context) { + mContext = context; + mPackageManager = packageManager; + mPermissionRequiredPreference = createPermissionMissionPreference(); + } } diff --git a/src/com/android/settings/network/MobileNetworkListController.java b/src/com/android/settings/network/MobileNetworkListController.java index d0e14ce2168..ab41fad6236 100644 --- a/src/com/android/settings/network/MobileNetworkListController.java +++ b/src/com/android/settings/network/MobileNetworkListController.java @@ -118,14 +118,19 @@ public class MobileNetworkListController extends AbstractPreferenceController im if (mSubscriptionManager.isActiveSubscriptionId(subId)) { pref.setSummary(R.string.mobile_network_active_sim); } else { - pref.setSummary(R.string.mobile_network_inactive_sim); + pref.setSummary(mContext.getString(R.string.mobile_network_tap_to_activate, + SubscriptionUtil.getDisplayName(info))); } } pref.setOnPreferenceClickListener(clickedPref -> { - final Intent intent = new Intent(mContext, MobileNetworkActivity.class); - intent.putExtra(Settings.EXTRA_SUB_ID, info.getSubscriptionId()); - mContext.startActivity(intent); + if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)) { + mSubscriptionManager.setSubscriptionEnabled(subId, true); + } else { + 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); diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java index 9498c4e61e0..0f76f24de56 100644 --- a/src/com/android/settings/network/MobileNetworkSummaryController.java +++ b/src/com/android/settings/network/MobileNetworkSummaryController.java @@ -108,7 +108,14 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController } return null; } else if (subs.size() == 1) { - return subs.get(0).getDisplayName(); + final SubscriptionInfo info = subs.get(0); + final int subId = info.getSubscriptionId(); + if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)) { + return mContext.getString(R.string.mobile_network_tap_to_activate, + SubscriptionUtil.getDisplayName(info)); + } else { + return subs.get(0).getDisplayName(); + } } else { final int count = subs.size(); return mContext.getResources().getQuantityString(R.plurals.mobile_network_summary_count, @@ -154,9 +161,15 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController if (subs.size() == 1) { mPreference.setOnPreferenceClickListener((Preference pref) -> { - final Intent intent = new Intent(mContext, MobileNetworkActivity.class); - intent.putExtra(Settings.EXTRA_SUB_ID, subs.get(0).getSubscriptionId()); - mContext.startActivity(intent); + final SubscriptionInfo info = subs.get(0); + final int subId = info.getSubscriptionId(); + if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)) { + mSubscriptionManager.setSubscriptionEnabled(subId, true); + } else { + final Intent intent = new Intent(mContext, MobileNetworkActivity.class); + intent.putExtra(Settings.EXTRA_SUB_ID, subs.get(0).getSubscriptionId()); + mContext.startActivity(intent); + } return true; }); } else { diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java index ebac51f3f67..f7235754f6c 100644 --- a/src/com/android/settings/network/SubscriptionUtil.java +++ b/src/com/android/settings/network/SubscriptionUtil.java @@ -25,12 +25,10 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.UiccSlotInfo; -import android.text.TextUtils; import androidx.annotation.VisibleForTesting; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public class SubscriptionUtil { @@ -107,4 +105,12 @@ public class SubscriptionUtil { } return subscriptions; } + + public static String getDisplayName(SubscriptionInfo info) { + final CharSequence name = info.getDisplayName(); + if (name != null) { + return name.toString(); + } + return ""; + } } diff --git a/src/com/android/settings/network/telephony/DisableSimFooterPreferenceController.java b/src/com/android/settings/network/telephony/DisableSimFooterPreferenceController.java new file mode 100644 index 00000000000..ab01b9d5a86 --- /dev/null +++ b/src/com/android/settings/network/telephony/DisableSimFooterPreferenceController.java @@ -0,0 +1,54 @@ +/* + * 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 android.content.Context; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.network.SubscriptionUtil; + +public class DisableSimFooterPreferenceController extends BasePreferenceController { + private int mSubId; + + public DisableSimFooterPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + } + + public void init(int subId) { + mSubId = subId; + } + + @Override + public int getAvailabilityStatus() { + if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + return CONDITIONALLY_UNAVAILABLE; + } + for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) { + if (info.getSubscriptionId() == mSubId) { + if (info.isEmbedded()) { + return CONDITIONALLY_UNAVAILABLE; + } + break; + } + } + return AVAILABLE; + } +} diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index aa63b747ad9..c8e2247db15 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -142,6 +142,7 @@ public class MobileNetworkSettings extends RestrictedDashboardFragment { use(DisabledSubscriptionController.class).init(getLifecycle(), mSubId); use(DeleteSimProfilePreferenceController.class).init(mSubId, this, REQUEST_CODE_DELETE_SUBSCRIPTION); + use(DisableSimFooterPreferenceController.class).init(mSubId); } use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId); diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java index 2037adce4b5..e6422f00d60 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java @@ -93,23 +93,23 @@ public class MobileNetworkSwitchController extends BasePreferenceController impl if (mSwitchBar == null) { return; } - final List subs = SubscriptionUtil.getAvailableSubscriptions( - mContext); - if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID || - mSubscriptionManager.isSubscriptionEnabled(mSubId) && subs.size() < 2) { - mSwitchBar.hide(); - return; - } - for (SubscriptionInfo info : subs) { + SubscriptionInfo subInfo = null; + for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mContext)) { if (info.getSubscriptionId() == mSubId) { - mSwitchBar.show(); - mSwitchBar.setChecked(mSubscriptionManager.isSubscriptionEnabled(mSubId)); - return; + subInfo = info; + break; } } - // This subscription was not found in the available list. - mSwitchBar.hide(); + + // For eSIM, we always want the toggle. The telephony stack doesn't currently support + // disabling a pSIM directly (b/133379187), so we for now we don't include this on pSIM. + if (subInfo == null || !subInfo.isEmbedded()) { + mSwitchBar.hide(); + } else { + mSwitchBar.show(); + mSwitchBar.setChecked(mSubscriptionManager.isSubscriptionEnabled(mSubId)); + } } @Override diff --git a/src/com/android/settings/notification/HeaderPreferenceController.java b/src/com/android/settings/notification/HeaderPreferenceController.java index d94211384d7..be5f45eacca 100644 --- a/src/com/android/settings/notification/HeaderPreferenceController.java +++ b/src/com/android/settings/notification/HeaderPreferenceController.java @@ -25,13 +25,14 @@ import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.view.View; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; import androidx.preference.Preference; -import androidx.preference.PreferenceFragmentCompat; import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.widget.EntityHeaderController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.widget.LayoutPreference; @@ -39,11 +40,11 @@ import com.android.settingslib.widget.LayoutPreference; public class HeaderPreferenceController extends NotificationPreferenceController implements PreferenceControllerMixin, LifecycleObserver { - private final PreferenceFragmentCompat mFragment; + private final DashboardFragment mFragment; private EntityHeaderController mHeaderController; private boolean mStarted = false; - public HeaderPreferenceController(Context context, PreferenceFragmentCompat fragment) { + public HeaderPreferenceController(Context context, DashboardFragment fragment) { super(context, null); mFragment = fragment; } @@ -83,18 +84,12 @@ public class HeaderPreferenceController extends NotificationPreferenceController .setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE, EntityHeaderController.ActionType.ACTION_NONE) .setHasAppInfoLink(true) + .setRecyclerView(mFragment.getListView(), mFragment.getSettingsLifecycle()) .done(activity, mContext); pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE); } } - CharSequence getLabel() { - return (mChannel != null && !isDefaultChannel()) ? mChannel.getName() - : mChannelGroup != null - ? mChannelGroup.getName() - : mAppRow.label; - } - @Override public CharSequence getSummary() { if (mChannel != null && !isDefaultChannel()) { @@ -124,4 +119,12 @@ public class HeaderPreferenceController extends NotificationPreferenceController mHeaderController.styleActionBar(mFragment.getActivity()); } } + + @VisibleForTesting + CharSequence getLabel() { + return (mChannel != null && !isDefaultChannel()) ? mChannel.getName() + : mChannelGroup != null + ? mChannelGroup.getName() + : mAppRow.label; + } } diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java new file mode 100644 index 00000000000..971ebc52d67 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java @@ -0,0 +1,80 @@ +/* + * 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.display; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; + +import androidx.preference.PreferenceScreen; + +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; + +@RunWith(RobolectricTestRunner.class) +public class AdaptiveSleepSettingsTest { + private AdaptiveSleepSettings mSettings; + private static final String PACKAGE_NAME = "package_name"; + @Mock + private PackageManager mPackageManager; + @Mock + private PreferenceScreen mScreen; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + Context context = RuntimeEnvironment.application; + mSettings = spy(new AdaptiveSleepSettings()); + + doReturn(PACKAGE_NAME).when(mPackageManager).getAttentionServicePackageName(); + doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + doReturn(mScreen).when(mSettings).getPreferenceScreen(); + + mSettings.setupForTesting(mPackageManager, context); + mSettings.onAttach(context); + + } + + @Test + public void onResume_hasPermission_preferenceInvisible() { + mSettings.onResume(); + + assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isFalse(); + } + + @Test + public void onResume_noPermission_preferenceVisible() { + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + Manifest.permission.CAMERA, PACKAGE_NAME); + + mSettings.onResume(); + + assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java index 342fed50f15..4a98753e2b0 100644 --- a/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/MobileNetworkListControllerTest.java @@ -21,6 +21,8 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -32,6 +34,7 @@ import android.content.Context; import android.content.Intent; import android.provider.Settings; import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.euicc.EuiccManager; @@ -54,9 +57,11 @@ import androidx.preference.PreferenceScreen; @RunWith(RobolectricTestRunner.class) public class MobileNetworkListControllerTest { @Mock - TelephonyManager mTelephonyManager; + private TelephonyManager mTelephonyManager; @Mock - EuiccManager mEuiccManager; + private EuiccManager mEuiccManager; + @Mock + private SubscriptionManager mSubscriptionManager; @Mock private Lifecycle mLifecycle; @@ -74,6 +79,7 @@ public class MobileNetworkListControllerTest { mContext = spy(Robolectric.setupActivity(Activity.class)); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.EUICC_PROVISIONED, 1); when(mPreferenceScreen.getContext()).thenReturn(mContext); mAddMorePreference = new Preference(mContext); @@ -114,6 +120,8 @@ public class MobileNetworkListControllerTest { public void displayPreference_twoSubscriptions_correctlySetup() { final SubscriptionInfo sub1 = createMockSubscription(1, "sub1"); final SubscriptionInfo sub2 = createMockSubscription(2, "sub2"); + doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(eq(1)); + doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(eq(2)); SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2)); mController.displayPreference(mPreferenceScreen); mController.onResume(); @@ -138,6 +146,33 @@ public class MobileNetworkListControllerTest { assertThat(intent2.getIntExtra(EXTRA_SUB_ID, INVALID_SUBSCRIPTION_ID)).isEqualTo(2); } + @Test + public void displayPreference_oneActiveESimOneInactivePSim_correctlySetup() { + final SubscriptionInfo sub1 = createMockSubscription(1, "sub1"); + final SubscriptionInfo sub2 = createMockSubscription(2, "sub2"); + when(sub1.isEmbedded()).thenReturn(true); + doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(eq(1)); + doReturn(false).when(mSubscriptionManager).isActiveSubscriptionId(eq(2)); + + when(sub2.isEmbedded()).thenReturn(false); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2)); + + mController.displayPreference(mPreferenceScreen); + mController.onResume(); + + // Check that the preferences get created with the correct summaries. + final ArgumentCaptor 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.getSummary()).isEqualTo("Active / Downloaded SIM"); + assertThat(pref2.getSummary()).isEqualTo("Tap to activate sub2"); + + pref2.getOnPreferenceClickListener().onPreferenceClick(pref2); + verify(mSubscriptionManager).setSubscriptionEnabled(eq(2), eq(true)); + } + @Test public void onSubscriptionsChanged_twoSubscriptionsOneChangesName_preferenceUpdated() { final SubscriptionInfo sub1 = createMockSubscription(1, "sub1"); diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java index a6238505756..99c9134c77d 100644 --- a/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/MobileNetworkSummaryControllerTest.java @@ -18,6 +18,7 @@ package com.android.settings.network; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.atLeastOnce; @@ -64,6 +65,8 @@ public class MobileNetworkSummaryControllerTest { @Mock private TelephonyManager mTelephonyManager; @Mock + private SubscriptionManager mSubscriptionManager; + @Mock private EuiccManager mEuiccManager; @Mock private PreferenceScreen mPreferenceScreen; @@ -79,9 +82,11 @@ public class MobileNetworkSummaryControllerTest { MockitoAnnotations.initMocks(this); mContext = spy(Robolectric.setupActivity(Activity.class)); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); + when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); when(mContext.getSystemService(EuiccManager.class)).thenReturn(mEuiccManager); when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager); when(mTelephonyManager.getNetworkCountryIso()).thenReturn(""); + when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true); when(mEuiccManager.isEnabled()).thenReturn(true); Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.EUICC_PROVISIONED, 1); @@ -159,6 +164,24 @@ public class MobileNetworkSummaryControllerTest { SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(sub1.getSubscriptionId()); } + @Test + public void getSummary_oneInactivePSim_correctSummaryAndClickHandler() { + final SubscriptionInfo sub1 = mock(SubscriptionInfo.class); + when(sub1.getSubscriptionId()).thenReturn(1); + when(sub1.getDisplayName()).thenReturn("sub1"); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1)); + when(mSubscriptionManager.isActiveSubscriptionId(eq(1))).thenReturn(false); + + mController.displayPreference(mPreferenceScreen); + mController.onResume(); + + assertThat(mController.getSummary()).isEqualTo("Tap to activate sub1"); + + assertThat(mPreference.getFragment()).isNull(); + mPreference.getOnPreferenceClickListener().onPreferenceClick(mPreference); + verify(mSubscriptionManager).setSubscriptionEnabled(eq(sub1.getSubscriptionId()), eq(true)); + } + @Test public void getSummary_twoSubscriptions_correctSummaryAndFragment() { final SubscriptionInfo sub1 = mock(SubscriptionInfo.class); diff --git a/tests/robotests/src/com/android/settings/network/telephony/DisableSimFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DisableSimFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..a0a4f009832 --- /dev/null +++ b/tests/robotests/src/com/android/settings/network/telephony/DisableSimFooterPreferenceControllerTest.java @@ -0,0 +1,77 @@ +/* + * 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.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.telephony.SubscriptionInfo; + +import com.android.settings.network.SubscriptionUtil; + +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 java.util.Arrays; + +@RunWith(RobolectricTestRunner.class) +public class DisableSimFooterPreferenceControllerTest { + private static final String PREF_KEY = "pref_key"; + private static final int SUB_ID = 111; + + @Mock + private SubscriptionInfo mInfo; + + private Context mContext; + private DisableSimFooterPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + when(mInfo.getSubscriptionId()).thenReturn(SUB_ID); + SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mInfo)); + mController = new DisableSimFooterPreferenceController(mContext, PREF_KEY); + } + + @Test + public void isAvailable_noInit_notAvailable() { + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_eSIM_notAvailable() { + when(mInfo.isEmbedded()).thenReturn(true); + mController.init(SUB_ID); + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_pSIM_available() { + when(mInfo.isEmbedded()).thenReturn(false); + mController.init(SUB_ID); + assertThat(mController.isAvailable()).isTrue(); + } +} diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java index a10227f5924..86c380e006b 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java @@ -79,13 +79,14 @@ public class MobileNetworkSwitchControllerTest { mLifecycleOwner = () -> mLifecycle; mLifecycle = new Lifecycle(mLifecycleOwner); + when(mSubscription.isEmbedded()).thenReturn(true); when(mSubscription.getSubscriptionId()).thenReturn(mSubId); // Most tests want to have 2 available subscriptions so that the switch bar will show. - SubscriptionInfo sub2 = mock(SubscriptionInfo.class); + final SubscriptionInfo sub2 = mock(SubscriptionInfo.class); when(sub2.getSubscriptionId()).thenReturn(456); SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription, sub2)); - String key = "prefKey"; + final String key = "prefKey"; mController = new MobileNetworkSwitchController(mContext, key); mController.init(mLifecycle, mSubscription.getSubscriptionId()); @@ -100,11 +101,18 @@ public class MobileNetworkSwitchControllerTest { } @Test - public void displayPreference_oneEnabledSubscription_switchBarHidden() { + public void isAvailable_pSIM_isNotAvailable() { + when(mSubscription.isEmbedded()).thenReturn(false); + mController.displayPreference(mScreen); + assertThat(mSwitchBar.isShowing()).isFalse(); + } + + @Test + public void displayPreference_oneEnabledSubscription_switchBarNotHidden() { doReturn(true).when(mSubscriptionManager).isSubscriptionEnabled(mSubId); SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription)); mController.displayPreference(mScreen); - assertThat(mSwitchBar.isShowing()).isFalse(); + assertThat(mSwitchBar.isShowing()).isTrue(); } @Test diff --git a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java index de84f0755c3..7f6ecaefc67 100644 --- a/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/HeaderPreferenceControllerTest.java @@ -21,7 +21,6 @@ import static android.app.NotificationManager.IMPORTANCE_NONE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; - import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -35,8 +34,8 @@ import android.os.UserManager; import android.view.View; import androidx.fragment.app.FragmentActivity; -import androidx.preference.PreferenceFragmentCompat; +import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; @@ -70,7 +69,7 @@ public class HeaderPreferenceControllerTest { shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm); shadowApplication.setSystemService(Context.USER_SERVICE, mUm); mContext = RuntimeEnvironment.application; - PreferenceFragmentCompat fragment = mock(PreferenceFragmentCompat.class); + DashboardFragment fragment = mock(DashboardFragment.class); when(fragment.getContext()).thenReturn(mContext); FragmentActivity activity = mock(FragmentActivity.class); when(activity.getApplicationContext()).thenReturn(mContext);