Merge "Add a config to hide "Enable wireless display" menu" into main am: 6a04355cb3 am: 919149ceee

Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/2647051

Change-Id: Ibadb5404e51cf60c5f0e6336772e6ccafc29e996
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java
index 9bf626c..4c65488 100644
--- a/src/com/android/settings/DefaultRingtonePreference.java
+++ b/src/com/android/settings/DefaultRingtonePreference.java
@@ -51,16 +51,9 @@
             return;
         }
 
-        String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
-        if (mimeType == null) {
+        if (!isValidRingtoneUri(ringtoneUri)) {
             Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
-                    + " ignored: failure to find mimeType (no access from this context?)");
-            return;
-        }
-
-        if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
-            Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
-                    + " ignored: associated mimeType:" + mimeType + " is not an audio type");
+                    + " ignored: invalid ringtone Uri");
             return;
         }
 
diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java
index 8f9c618..de5b7c3 100644
--- a/src/com/android/settings/RingtonePreference.java
+++ b/src/com/android/settings/RingtonePreference.java
@@ -16,6 +16,8 @@
 
 package com.android.settings;
 
+import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
@@ -23,9 +25,11 @@
 import android.media.RingtoneManager;
 import android.net.Uri;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings.System;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.Log;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
@@ -239,4 +243,83 @@
         return true;
     }
 
+    public boolean isDefaultRingtone(Uri ringtoneUri) {
+        // null URIs are valid (None/silence)
+        return ringtoneUri == null || RingtoneManager.isDefault(ringtoneUri);
+    }
+
+    protected boolean isValidRingtoneUri(Uri ringtoneUri) {
+        if (isDefaultRingtone(ringtoneUri)) {
+            return true;
+        }
+
+        // Return early for android resource URIs
+        if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(ringtoneUri.getScheme())) {
+            return true;
+        }
+
+        String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
+        if (mimeType == null) {
+            Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+                    + " failed: failure to find mimeType (no access from this context?)");
+            return false;
+        }
+
+        if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+                || mimeType.equals("application/x-flac"))) {
+            Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+                    + " failed: associated mimeType:" + mimeType + " is not an audio type");
+            return false;
+        }
+
+        // Validate userId from URIs: content://{userId}@...
+        final int userIdFromUri = ContentProvider.getUserIdFromUri(ringtoneUri, mUserId);
+        if (userIdFromUri != mUserId) {
+            final UserManager userManager = mUserContext.getSystemService(UserManager.class);
+
+            if (!userManager.isSameProfileGroup(mUserId, userIdFromUri)) {
+                Log.e(TAG,
+                    "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + userIdFromUri
+                        + " and user " + mUserId + " are not in the same profile group");
+                return false;
+            }
+
+            final int parentUserId;
+            final int profileUserId;
+            if (userManager.isProfile()) {
+                profileUserId = mUserId;
+                parentUserId = userIdFromUri;
+            } else {
+                parentUserId = mUserId;
+                profileUserId = userIdFromUri;
+            }
+
+            final UserHandle parent = userManager.getProfileParent(UserHandle.of(profileUserId));
+            if (parent == null || parent.getIdentifier() != parentUserId) {
+                Log.e(TAG,
+                    "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + profileUserId
+                        + " is not a profile of user " + parentUserId);
+                return false;
+            }
+
+            // Allow parent <-> managed profile sharing, unless restricted
+            if (userManager.hasUserRestrictionForUser(
+                UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, UserHandle.of(parentUserId))) {
+                Log.e(TAG,
+                    "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + parentUserId
+                        + " has restriction: " + UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE);
+                return false;
+            }
+
+            if (!(userManager.isManagedProfile(profileUserId) || userManager.getUserProperties(
+                    UserHandle.of(profileUserId)).isMediaSharedWithParent())) {
+                Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+                    + " failed: user " + profileUserId + " is not a cloned or managed profile");
+                return false;
+            }
+        }
+
+        return true;
+    }
+
 }
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
index 70fdbf0..0bfb87d 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
@@ -76,6 +76,8 @@
 
     private int mCenterTouchCount = 0;
 
+    private int mPace = 1;
+
     @Nullable
     UdfpsEnrollHelper.Listener mListener;
 
@@ -157,6 +159,9 @@
             }
         }
 
+        if (mRemainingSteps > remaining) {
+            mPace = mRemainingSteps - remaining;
+        }
         mRemainingSteps = remaining;
 
         if (mListener != null && mTotalSteps != -1) {
@@ -258,7 +263,7 @@
             return false;
         }
 
-        return mRemainingSteps <= 2 && mRemainingSteps >= 0;
+        return mRemainingSteps <= mPace && mRemainingSteps >= 0;
     }
 
     private int getStageThresholdSteps(int totalSteps, int stageIndex) {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
index 5014634..453941d 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
@@ -16,12 +16,16 @@
 
 package com.android.settings.network.telephony;
 
+import static android.telephony.TelephonyManager.CALL_STATE_IDLE;
+
 import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
 
 import android.content.Context;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
 
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
@@ -40,26 +44,40 @@
     private int mSubId;
     private SubscriptionsChangeListener mChangeListener;
     private SubscriptionManager mSubscriptionManager;
+    private TelephonyManager mTelephonyManager;
+    private CallStateTelephonyCallback mCallStateCallback;
 
     public MobileNetworkSwitchController(Context context, String preferenceKey) {
         super(context, preferenceKey);
         mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
         mChangeListener = new SubscriptionsChangeListener(context, this);
     }
 
     void init(int subId) {
         mSubId = subId;
+        mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
     }
 
     @OnLifecycleEvent(ON_RESUME)
     public void onResume() {
         mChangeListener.start();
+
+        if (mCallStateCallback == null) {
+            mCallStateCallback = new CallStateTelephonyCallback();
+            mTelephonyManager.registerTelephonyCallback(
+                    mContext.getMainExecutor(), mCallStateCallback);
+        }
         update();
     }
 
     @OnLifecycleEvent(ON_PAUSE)
     public void onPause() {
+        if (mCallStateCallback != null) {
+            mTelephonyManager.unregisterTelephonyCallback(mCallStateCallback);
+            mCallStateCallback = null;
+        }
         mChangeListener.stop();
     }
 
@@ -118,4 +136,12 @@
     public void onSubscriptionsChanged() {
         update();
     }
+
+    private class CallStateTelephonyCallback extends TelephonyCallback implements
+            TelephonyCallback.CallStateListener {
+        @Override
+        public void onCallStateChanged(int state) {
+            mSwitchBar.setSwitchBarEnabled(state == CALL_STATE_IDLE);
+        }
+    }
 }
diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
index a6b565a..9ea8c58 100644
--- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
+++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
@@ -17,6 +17,7 @@
 
 package com.android.settings.notification;
 
+import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS;
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
 
 import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME;
@@ -26,6 +27,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -35,10 +37,12 @@
 import android.content.pm.ServiceInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Slog;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
+import android.widget.Toast;
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
@@ -55,12 +59,28 @@
     private ComponentName mComponentName;
     private NotificationManager mNm;
 
+    private DevicePolicyManager mDpm;
+    private UserManager mUm;
+
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
 
+        mUm = getSystemService(UserManager.class);
+        mDpm = getSystemService(DevicePolicyManager.class);
+
+        if (mUm.isManagedProfile()) {
+            Slog.w(LOG_TAG, "Apps in the work profile do not support notification listeners");
+            Toast.makeText(this,
+                    mDpm.getResources().getString(WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS,
+                            () -> getString(R.string.notification_settings_work_profile)),
+                    Toast.LENGTH_SHORT).show();
+            finish();
+            return;
+        }
+
         mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
         mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME);
diff --git a/src/com/android/settings/notification/app/NotificationSoundPreference.java b/src/com/android/settings/notification/app/NotificationSoundPreference.java
index 136b21f..b55f9bd 100644
--- a/src/com/android/settings/notification/app/NotificationSoundPreference.java
+++ b/src/com/android/settings/notification/app/NotificationSoundPreference.java
@@ -25,10 +25,13 @@
 import android.os.AsyncTask;
 import android.util.AttributeSet;
 
+import android.util.Log;
 import com.android.settings.R;
 import com.android.settings.RingtonePreference;
 
 public class NotificationSoundPreference extends RingtonePreference {
+    private static final String TAG = "NotificationSoundPreference";
+
     private Uri mRingtone;
 
     public NotificationSoundPreference(Context context, AttributeSet attrs) {
@@ -50,8 +53,13 @@
     public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
         if (data != null) {
             Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
-            setRingtone(uri);
-            callChangeListener(uri);
+            if (isValidRingtoneUri(uri)) {
+                setRingtone(uri);
+                callChangeListener(uri);
+            } else {
+                Log.e(TAG, "onActivityResult for URI:" + uri
+                    + " ignored: invalid ringtone Uri");
+            }
         }
 
         return true;
diff --git a/src/com/android/settings/password/SetNewPasswordActivity.java b/src/com/android/settings/password/SetNewPasswordActivity.java
index e54ae7a..fc664ec 100644
--- a/src/com/android/settings/password/SetNewPasswordActivity.java
+++ b/src/com/android/settings/password/SetNewPasswordActivity.java
@@ -121,7 +121,9 @@
 
     @Override
     public void launchChooseLock(Bundle chooseLockFingerprintExtras) {
-        Intent intent = new Intent(this, SetupChooseLockGeneric.class);
+        final boolean isInSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
+        Intent intent = isInSetupWizard ? new Intent(this, SetupChooseLockGeneric.class)
+                : new Intent(this, ChooseLockGeneric.class);
         intent.setAction(mNewPasswordAction);
         intent.putExtras(chooseLockFingerprintExtras);
         if (mCallerAppName != null) {
diff --git a/src/com/android/settings/password/SetupChooseLockGeneric.java b/src/com/android/settings/password/SetupChooseLockGeneric.java
index a3bef83..bc6c512 100644
--- a/src/com/android/settings/password/SetupChooseLockGeneric.java
+++ b/src/com/android/settings/password/SetupChooseLockGeneric.java
@@ -256,12 +256,6 @@
             return InternalSetupChooseLockGenericFragment.class;
         }
 
-        @Override
-        protected boolean isToolbarEnabled() {
-            // Hide the action bar from this page.
-            return false;
-        }
-
         public static class InternalSetupChooseLockGenericFragment
                 extends ChooseLockGenericFragment {
             @Override
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
index f4489c6..e123389 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
@@ -40,6 +40,7 @@
 import com.android.settingslib.spaprivileged.framework.common.crossProfileApps
 import org.junit.After
 import org.junit.Before
+import org.junit.Ignore
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -116,6 +117,7 @@
         composeTestRule.waitUntilExists(hasText(SUMMARY))
     }
 
+    @Ignore
     @Test
     fun whenClick_startActivity() {
         mockCanConfig(true)
diff --git a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
index 7877684..c580fc5 100644
--- a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
+++ b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
@@ -16,16 +16,20 @@
 
 package com.android.settings;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ContentInterface;
 import android.content.ContentResolver;
 import android.content.Context;
-import android.media.RingtoneManager;
+import android.content.pm.UserProperties;
 import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -34,17 +38,22 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 /** Unittest for DefaultRingtonePreference. */
 @RunWith(AndroidJUnit4.class)
 public class DefaultRingtonePreferenceTest {
 
+    private static final int OWNER_USER_ID = 1;
+    private static final int OTHER_USER_ID = 10;
+    private static final int INVALID_RINGTONE_TYPE = 0;
     private DefaultRingtonePreference mDefaultRingtonePreference;
 
     @Mock
     private ContentResolver mContentResolver;
     @Mock
+    private UserManager mUserManager;
     private Uri mRingtoneUri;
 
     @Before
@@ -52,14 +61,29 @@
         MockitoAnnotations.initMocks(this);
 
         Context context = spy(ApplicationProvider.getApplicationContext());
-        doReturn(mContentResolver).when(context).getContentResolver();
+        mContentResolver = ContentResolver.wrap(Mockito.mock(ContentInterface.class));
+        when(context.getContentResolver()).thenReturn(mContentResolver);
 
         mDefaultRingtonePreference = spy(new DefaultRingtonePreference(context, null /* attrs */));
         doReturn(context).when(mDefaultRingtonePreference).getContext();
+
+        // Use INVALID_RINGTONE_TYPE to return early in RingtoneManager.setActualDefaultRingtoneUri
         when(mDefaultRingtonePreference.getRingtoneType())
-                .thenReturn(RingtoneManager.TYPE_RINGTONE);
-        mDefaultRingtonePreference.setUserId(1);
+                .thenReturn(INVALID_RINGTONE_TYPE);
+
+        mDefaultRingtonePreference.setUserId(OWNER_USER_ID);
         mDefaultRingtonePreference.mUserContext = context;
+        when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(false);
+
+        when(context.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+        when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+
+        UserProperties userProperties = new UserProperties.Builder().setMediaSharedWithParent(false)
+                .build();
+        when(mUserManager.getUserProperties(UserHandle.of(OTHER_USER_ID))).thenReturn(
+                userProperties);
+
+        mRingtoneUri = Uri.parse("content://none");
     }
 
     @Test
@@ -79,4 +103,53 @@
 
         verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
     }
+
+    @Test
+    public void onSaveRingtone_notManagedProfile_shouldNotSetRingtone() {
+        mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+        when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+        when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
+        when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
+                UserHandle.of(OWNER_USER_ID));
+        when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(false);
+
+        mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+        verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
+    }
+
+    @Test
+    public void onSaveRingtone_notSameUser_shouldNotSetRingtone() {
+        mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+        when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+        when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(false);
+
+        mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+        verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
+    }
+
+    @Test
+    public void onSaveRingtone_isManagedProfile_shouldSetRingtone() {
+        mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+        when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+        when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
+        when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
+                UserHandle.of(OWNER_USER_ID));
+        when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(true);
+
+        mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+        verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
+    }
+
+    @Test
+    public void onSaveRingtone_defaultUri_shouldSetRingtone() {
+        mRingtoneUri = Uri.parse("default_ringtone");
+        when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(true);
+
+        mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+        verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
+    }
 }
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
index e460d67..3cdd23a 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
@@ -35,6 +35,8 @@
 import android.os.Looper;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -44,28 +46,32 @@
 import androidx.preference.PreferenceViewHolder;
 import androidx.test.annotation.UiThreadTest;
 import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.widget.SettingsMainSwitchPreference;
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
+import org.junit.Rule;
 import org.junit.Test;
-import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 import java.util.Arrays;
+import java.util.concurrent.Executor;
 
-@RunWith(AndroidJUnit4.class)
 public class MobileNetworkSwitchControllerTest {
+    @Rule
+    public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
     @Mock
     private SubscriptionManager mSubscriptionManager;
     @Mock
     private SubscriptionInfo mSubscription;
+    @Mock
+    private TelephonyManager mTelephonyManager;
 
     private PreferenceScreen mScreen;
     private PreferenceManager mPreferenceManager;
@@ -76,7 +82,9 @@
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         mContext = spy(ApplicationProvider.getApplicationContext());
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
         when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
@@ -89,18 +97,19 @@
         when(sub2.getSubscriptionId()).thenReturn(456);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription, sub2));
 
+        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+        when(mTelephonyManager.createForSubscriptionId(mSubId))
+                .thenReturn(mTelephonyManager);
+
         final String key = "prefKey";
         mController = new MobileNetworkSwitchController(mContext, key);
         mController.init(mSubscription.getSubscriptionId());
 
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-
         mPreferenceManager = new PreferenceManager(mContext);
         mScreen = mPreferenceManager.createPreferenceScreen(mContext);
         mSwitchBar = new SettingsMainSwitchPreference(mContext);
         mSwitchBar.setKey(key);
+        mSwitchBar.setTitle("123");
         mScreen.addPreference(mSwitchBar);
 
         final LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -117,7 +126,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void isAvailable_pSIM_isNotAvailable() {
         when(mSubscription.isEmbedded()).thenReturn(false);
         mController.displayPreference(mScreen);
@@ -130,7 +138,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void displayPreference_oneEnabledSubscription_switchBarNotHidden() {
         doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
@@ -140,7 +147,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void displayPreference_oneDisabledSubscription_switchBarNotHidden() {
         doReturn(false).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
         SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
@@ -152,7 +158,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void displayPreference_subscriptionEnabled_switchIsOn() {
         when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
         mController.displayPreference(mScreen);
@@ -162,7 +167,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void displayPreference_subscriptionDisabled_switchIsOff() {
         when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
 
@@ -174,7 +178,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledCalledCorrectly() {
         when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
         mController.displayPreference(mScreen);
@@ -183,18 +186,24 @@
 
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         doNothing().when(mContext).startActivity(intentCaptor.capture());
+
+        // set switch off then should start a Activity.
         mSwitchBar.setChecked(false);
+
+        when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
+        // Simulate action of back from previous activity.
+        mController.displayPreference(mScreen);
         Bundle extra = intentCaptor.getValue().getExtras();
 
         verify(mContext, times(1)).startActivity(any());
         assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
         assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable))
                 .isEqualTo(false);
+        assertThat(mSwitchBar.isChecked()).isFalse();
     }
 
     @Test
     @UiThreadTest
-    @Ignore
     public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledFailed() {
         when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
                 .thenReturn(false);
@@ -205,7 +214,12 @@
 
         final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
         doNothing().when(mContext).startActivity(intentCaptor.capture());
+
+        // set switch off then should start a Activity.
         mSwitchBar.setChecked(false);
+
+        // Simulate action of back from previous activity.
+        mController.displayPreference(mScreen);
         Bundle extra = intentCaptor.getValue().getExtras();
 
         verify(mContext, times(1)).startActivity(any());
@@ -217,7 +231,6 @@
 
     @Test
     @UiThreadTest
-    @Ignore
     public void switchChangeListener_fromDisabledToEnabled_setSubscriptionEnabledCalledCorrectly() {
         when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
         mController.displayPreference(mScreen);
@@ -233,4 +246,24 @@
         assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
         assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable)).isEqualTo(true);
     }
+    @Test
+    @UiThreadTest
+    public void onResumeAndonPause_registerAndUnregisterTelephonyCallback() {
+        mController.onResume();
+
+        verify(mTelephonyManager)
+                .registerTelephonyCallback(any(Executor.class), any(TelephonyCallback.class));
+
+        mController.onPause();
+        verify(mTelephonyManager)
+                .unregisterTelephonyCallback(any(TelephonyCallback.class));
+    }
+
+    @Test
+    @UiThreadTest
+    public void onPause_doNotRegisterAndUnregisterTelephonyCallback() {
+        mController.onPause();
+        verify(mTelephonyManager, times(0))
+                .unregisterTelephonyCallback(any(TelephonyCallback.class));
+    }
 }