Merge "Revert "Remove dynamic location settings footer"" into sc-dev am: f730edaaac

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

Change-Id: Icc34de95d3db29d33e2aaeaa6827cff2c0fdf718
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 323ce38..31d1ad3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -83,6 +83,7 @@
     <uses-permission android:name="android.permission.OEM_UNLOCK_STATE" />
     <uses-permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
+    <uses-permission android:name="android.permission.RESTART_WIFI_SUBSYSTEM" />
     <uses-permission android:name="android.permission.MANAGE_FINGERPRINT" />
     <uses-permission android:name="android.permission.USE_BIOMETRIC" />
     <uses-permission android:name="android.permission.USE_BIOMETRIC_INTERNAL" />
diff --git a/res/values-mcc234/strings.xml b/res/values-mcc234/strings.xml
new file mode 100644
index 0000000..f7d0d33
--- /dev/null
+++ b/res/values-mcc234/strings.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="cell_broadcast_settings">Emergency alerts</string>
+</resources>
\ No newline at end of file
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index c09ea02..3653baf 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.deviceinfo;
 
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +30,7 @@
 import android.text.TextUtils;
 import android.widget.Toast;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -112,7 +114,7 @@
         if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
             return false;
         }
-        if (Utils.isMonkeyRunning()) {
+        if (isUserAMonkey()) {
             return false;
         }
         // Don't enable developer options for secondary non-demo users.
@@ -245,4 +247,9 @@
                 Toast.LENGTH_LONG);
         mDevHitToast.show();
     }
+
+    @VisibleForTesting
+    protected boolean isUserAMonkey() {
+        return ActivityManager.isUserAMonkey();
+    }
 }
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index abf58d8..292196e 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -133,7 +133,7 @@
     }
 
     @VisibleForTesting
-    SubscriptionInfo getSubscriptionInfo(int simSlot) {
+    protected SubscriptionInfo getSubscriptionInfo(int simSlot) {
         final List<SubscriptionInfo> subscriptionInfoList =
                 mSubscriptionManager.getActiveSubscriptionInfoList();
         if (subscriptionInfoList != null) {
@@ -147,7 +147,7 @@
     }
 
     @VisibleForTesting
-    CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
+    protected CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
         final String phoneNumber = DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext,
                 subscriptionInfo);
         return TextUtils.isEmpty(phoneNumber) ? mContext.getString(R.string.device_info_default)
@@ -155,7 +155,7 @@
     }
 
     @VisibleForTesting
-    Preference createNewPreference(Context context) {
+    protected Preference createNewPreference(Context context) {
         return new Preference(context);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
deleted file mode 100644
index 87dcb33..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2018 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.deviceinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.when;
-
-import android.accounts.Account;
-import android.content.Context;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-public class BrandedAccountPreferenceControllerTest {
-
-    private Context mContext;
-    private FakeFeatureFactory fakeFeatureFactory;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        fakeFeatureFactory = FakeFeatureFactory.setupForTest();
-
-    }
-
-    @Test
-    public void isAvailable_configOn_noAccount_off() {
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-        assertThat(controller.isAvailable()).isFalse();
-    }
-
-    @Test
-    public void isAvailable_accountIsAvailable_on() {
-        when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
-                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
-
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-
-        assertThat(controller.isAvailable()).isTrue();
-    }
-
-    @Test
-    @Config(qualifiers = "mcc999")
-    public void isAvailable_configOff_hasAccount_off() {
-        when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
-                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
-
-        final BrandedAccountPreferenceController controller =
-                new BrandedAccountPreferenceController(mContext, "test_key");
-
-        assertThat(controller.isAvailable()).isFalse();
-    }
-}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
deleted file mode 100644
index d705b64..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.deviceinfo.hardwareinfo;
-
-import static android.content.Context.CLIPBOARD_SERVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.os.SystemProperties;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class HardwareRevisionPreferenceControllerTest {
-
-    private Context mContext;
-    private HardwareRevisionPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mController = new HardwareRevisionPreferenceController(mContext,
-                "hardware_info_device_revision");
-    }
-
-    @Test
-    public void copy_shouldCopyHardwareRevisionToClipboard() {
-        final String fakeHardwareVer = "FakeVer1.0";
-        SystemProperties.set("ro.boot.hardware.revision", fakeHardwareVer);
-
-        mController.copy();
-
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
-
-        assertThat(data.toString()).isEqualTo(fakeHardwareVer);
-    }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
deleted file mode 100644
index 2106b54..0000000
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.deviceinfo.hardwareinfo;
-
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.Context;
-import android.os.Build;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class SerialNumberPreferenceControllerTest {
-
-    private Context mContext;
-    private SerialNumberPreferenceController mController;
-
-    @Before
-    public void setUp() {
-        mContext = RuntimeEnvironment.application;
-        mController = new SerialNumberPreferenceController(mContext, "test");
-    }
-
-    @Test
-    public void copy_shouldPutSerialNumberToClipBoard() {
-        mController.copy();
-
-        final ClipboardManager clipboardManager = mContext.getSystemService(ClipboardManager.class);
-        final ClipData data = clipboardManager.getPrimaryClip();
-
-        assertThat(data.getItemAt(0).getText().toString()).contains(Build.getSerial());
-    }
-}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
new file mode 100644
index 0000000..6e78d05
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 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.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.ResourcesUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class BrandedAccountPreferenceControllerTest {
+
+    @Mock
+    private Resources mResources;
+    private Context mContext;
+    private FakeFeatureFactory mFakeFeatureFactory;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
+        mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
+
+    }
+
+    @Test
+    public void isAvailable_configOn_noAccount_off() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+        assertThat(controller.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void isAvailable_accountIsAvailable_on() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+        when(mFakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
+                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+
+        assertThat(controller.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void isAvailable_configOff_hasAccount_off() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool",
+                "config_show_branded_account_in_device_info");
+        when(mResources.getBoolean(boolId)).thenReturn(false);
+        when(mFakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class)))
+                .thenReturn(new Account[]{new Account("fake@account.foo", "fake.reallyfake")});
+
+        final BrandedAccountPreferenceController controller =
+                new BrandedAccountPreferenceController(mContext, "test_key");
+
+        assertThat(controller.isAvailable()).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
similarity index 71%
rename from tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 80a3a11..8c75449 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -22,52 +22,51 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 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.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
-import android.content.pm.UserInfo;
-import android.os.Process;
-import android.os.UserHandle;
+import android.os.Looper;
 import android.os.UserManager;
 import android.provider.Settings;
 
 import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.Preference;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.core.InstrumentedPreferenceFragment;
 import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settings.testutils.shadow.ShadowUtils;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowUserManager;
 
-@RunWith(RobolectricTestRunner.class)
-@Config(shadows = ShadowUtils.class)
+@RunWith(AndroidJUnit4.class)
 public class BuildNumberPreferenceControllerTest {
 
     private static final String KEY_BUILD_NUMBER = "build_number";
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private InstrumentedPreferenceFragment mFragment;
 
-    private ShadowUserManager mShadowUserManager;
-
     private Context mContext;
+    private UserManager mUserManager;
+    private ClipboardManager mClipboardManager;
     private LifecycleOwner mLifecycleOwner;
     private Lifecycle mLifecycle;
     private FakeFeatureFactory mFactory;
@@ -75,15 +74,23 @@
     private BuildNumberPreferenceController mController;
 
     @Before
+    @UiThreadTest
     public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
-        mShadowUserManager = Shadows.shadowOf(
-                RuntimeEnvironment.application.getSystemService(UserManager.class));
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mUserManager = (UserManager) spy(mContext.getSystemService(Context.USER_SERVICE));
+        doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+
         mFactory = FakeFeatureFactory.setupForTest();
         mLifecycleOwner = () -> mLifecycle;
         mLifecycle = new Lifecycle(mLifecycleOwner);
-        mController = new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER);
+        mController = spy(new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER));
         mController.setHost(mFragment);
 
         mPreference = new Preference(mContext);
@@ -93,11 +100,6 @@
                 Settings.Global.DEVICE_PROVISIONED, 1);
     }
 
-    @After
-    public void tearDown() {
-        ShadowUtils.reset();
-    }
-
     @Test
     public void handlePrefTreeClick_onlyHandleBuildNumberPref() {
         assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse();
@@ -105,32 +107,32 @@
 
     @Test
     public void handlePrefTreeClick_notAdminUser_notDemoUser_doNothing() {
-        mShadowUserManager.setIsAdminUser(false);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
     }
 
     @Test
     public void handlePrefTreeClick_isAdminUser_notDemoUser_handleBuildNumberPref() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
     }
 
     @Test
     public void handlePrefTreeClick_notAdminUser_isDemoUser_handleBuildNumberPref() {
-        mShadowUserManager.setIsAdminUser(false);
-        mShadowUserManager.addUser(UserHandle.myUserId(), "test", UserInfo.FLAG_DEMO);
+        when(mUserManager.isAdminUser()).thenReturn(false);
+        when(mUserManager.isDemoUser()).thenReturn(true);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue();
     }
 
     @Test
     public void handlePrefTreeClick_deviceNotProvisioned_doNothing() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
 
         Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
                 0);
@@ -143,17 +145,16 @@
 
     @Test
     public void handlePrefTreeClick_isMonkeyRun_doNothing() {
-        ShadowUtils.setIsUserAMonkey(true);
+        when(mController.isUserAMonkey()).thenReturn(true);
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
     }
 
     @Test
     public void handlePrefTreeClick_userHasRestriction_doNothing() {
-        mShadowUserManager.setIsAdminUser(true);
-        mShadowUserManager.setIsDemoUser(false);
-
-        mShadowUserManager.setUserRestriction(Process.myUserHandle(),
-                UserManager.DISALLOW_DEBUGGING_FEATURES, true);
+        when(mUserManager.isAdminUser()).thenReturn(true);
+        when(mUserManager.isDemoUser()).thenReturn(false);
+        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES))
+                .thenReturn(true);
 
         assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse();
         verify(mFactory.metricsFeatureProvider).action(
@@ -184,8 +185,9 @@
     }
 
     @Test
+    @UiThreadTest
     public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
-        mShadowUserManager.setIsAdminUser(true);
+        when(mUserManager.isAdminUser()).thenReturn(true);
 
         final boolean activityResultHandled = mController.onActivityResult(
                 BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
@@ -197,12 +199,14 @@
     }
 
     @Test
+    @UiThreadTest
     public void copy_shouldCopyBuildNumberToClipboard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
         mController.copy();
 
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
-        assertThat(data.toString()).isEqualTo(mController.getSummary());
+        final ClipData data = captor.getValue();
+        assertThat(data.getItemAt(0).getText().toString()).isEqualTo(mController.getSummary());
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
similarity index 71%
rename from tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
index 9bb2d3f..2a06ce9 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
@@ -21,38 +21,43 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
+import android.os.Looper;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
-import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 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.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
 import java.util.List;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class PhoneNumberPreferenceControllerTest {
 
-    @Mock
     private Preference mPreference;
     @Mock
     private Preference mSecondPreference;
@@ -62,25 +67,34 @@
     private SubscriptionInfo mSubscriptionInfo;
     @Mock
     private SubscriptionManager mSubscriptionManager;
-    @Mock
     private PreferenceScreen mScreen;
 
     private Context mContext;
     private PhoneNumberPreferenceController mController;
+    private ClipboardManager mClipboardManager;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
         when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
         mController = spy(new PhoneNumberPreferenceController(mContext, "phone_number"));
-        final String prefKey = mController.getPreferenceKey();
-        when(mScreen.findPreference(prefKey)).thenReturn(mPreference);
-        when(mScreen.getContext()).thenReturn(mContext);
+
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        mScreen = preferenceManager.createPreferenceScreen(mContext);
+        mPreference = spy(new Preference(mContext));
+        mPreference.setKey(mController.getPreferenceKey());
+        mPreference.setVisible(true);
+        mScreen.addPreference(mPreference);
+
         doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
         doReturn(mSecondPreference).when(mController).createNewPreference(mContext);
-        when(mPreference.isVisible()).thenReturn(true);
     }
 
     @Test
@@ -105,7 +119,7 @@
 
         mController.displayPreference(mScreen);
 
-        verify(mScreen).addPreference(mSecondPreference);
+        assertThat(mScreen.getPreferenceCount()).isEqualTo(2);
     }
 
     @Test
@@ -117,7 +131,7 @@
 
         mController.updateState(mPreference);
 
-        verify(mPreference).setTitle(mContext.getString(R.string.status_number));
+        verify(mPreference).setTitle(ResourcesUtils.getResourcesString(mContext, "status_number"));
         verify(mPreference).setSummary(phoneNumber);
     }
 
@@ -130,11 +144,11 @@
 
         mController.updateState(mPreference);
 
-        verify(mPreference).setTitle(
-                mContext.getString(R.string.status_number_sim_slot, 1 /* sim slot */));
+        verify(mPreference).setTitle(ResourcesUtils.getResourcesString(
+                mContext, "status_number_sim_slot", 1 /* sim slot */));
         verify(mPreference).setSummary(phoneNumber);
-        verify(mSecondPreference).setTitle(
-                mContext.getString(R.string.status_number_sim_slot, 2 /* sim slot */));
+        verify(mSecondPreference).setTitle(ResourcesUtils.getResourcesString(
+                mContext, "status_number_sim_slot", 2 /* sim slot */));
         verify(mSecondPreference).setSummary(phoneNumber);
     }
 
@@ -145,7 +159,8 @@
         CharSequence primaryNumber = mController.getSummary();
 
         assertThat(primaryNumber).isNotNull();
-        assertThat(primaryNumber).isEqualTo(mContext.getString(R.string.device_info_default));
+        assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
+                mContext, "device_info_default"));
     }
 
     @Test
@@ -155,22 +170,24 @@
 
         CharSequence primaryNumber = mController.getSummary();
 
-        assertThat(primaryNumber).isEqualTo(mContext.getString(R.string.device_info_default));
+        assertThat(primaryNumber).isEqualTo(ResourcesUtils.getResourcesString(
+                mContext, "device_info_default"));
     }
 
     @Test
+    @UiThreadTest
     public void copy_shouldCopyPhoneNumberToClipboard() {
         final List<SubscriptionInfo> list = new ArrayList<>();
         list.add(mSubscriptionInfo);
         when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(list);
         final String phoneNumber = "1111111111";
         doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
 
         mController.copy();
 
-        final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
-                CLIPBOARD_SERVICE);
-        final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+        final CharSequence data = captor.getValue().getItemAt(0).getText();
         assertThat(phoneNumber.contentEquals(data)).isTrue();
     }
 }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java b/tests/unit/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
similarity index 90%
rename from tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
index bb65fa2..ca124fd 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/StorageProfileFragmentTest.java
@@ -11,7 +11,7 @@
  * 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
+ * limitations under the License.
  */
 package com.android.settings.deviceinfo;
 
@@ -21,8 +21,12 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
+import android.os.Looper;
 import android.util.SparseArray;
 
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
 import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
 import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
 import com.android.settingslib.applications.StorageStatsSource;
@@ -32,16 +36,19 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class StorageProfileFragmentTest {
 
     @Captor
     private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
 
     @Test
+    @UiThreadTest
     public void verifyAppSizesAreNotZeroedOut() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
         StorageProfileFragment fragment = new StorageProfileFragment();
         StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
similarity index 66%
rename from tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
index 65e29b4..847919a 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceControllerTest.java
@@ -18,41 +18,57 @@
 
 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.content.res.Resources;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class DeviceModelPreferenceControllerTest {
 
     private Context mContext;
     private DeviceModelPreferenceController mController;
 
+    @Mock
+    private Resources mResources;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
         mController = new DeviceModelPreferenceController(mContext, "test_key");
     }
 
     @Test
     public void getAvailabilityStatus_configAllowed_available() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+        when(mResources.getBoolean(boolId)).thenReturn(true);
+
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.AVAILABLE);
     }
 
     @Test
-    @Config(qualifiers = "mcc999")
     public void getAvailabilityStatus_configDisallowed_unavailable() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+        when(mResources.getBoolean(boolId)).thenReturn(false);
+
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.UNSUPPORTED_ON_DEVICE);
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
similarity index 70%
rename from tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
index c7c7669..7262615 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoPreferenceControllerTest.java
@@ -17,41 +17,53 @@
 
 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.content.res.Resources;
 import android.os.Build;
+import android.os.Looper;
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceManager;
 import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.deviceinfo.HardwareInfoPreferenceController;
+import com.android.settings.testutils.ResourcesUtils;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
 
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
 public class HardwareInfoPreferenceControllerTest {
 
-    private final String KEY = "device_model";
+    private static final String KEY = "device_model";
 
     private Preference mPreference;
     private PreferenceScreen mPreferenceScreen;
     private Context mContext;
+    @Mock
+    private Resources mResources;
     private HardwareInfoPreferenceController mController;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        when(mContext.getResources()).thenReturn(mResources);
         mController = new HardwareInfoPreferenceController(mContext, KEY);
         mPreference = new Preference(mContext);
         mPreference.setKey(KEY);
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
         final PreferenceManager preferenceManager = new PreferenceManager(mContext);
         mPreferenceScreen = preferenceManager.createPreferenceScreen(mContext);
         mPreferenceScreen.addPreference(mPreference);
@@ -59,13 +71,20 @@
 
     @Test
     public void isAvailable_returnTrueIfVisible() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+
+        when(mResources.getBoolean(boolId)).thenReturn(true);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.AVAILABLE);
     }
 
     @Test
-    @Config(qualifiers = "mcc999")
     public void isAvailable_returnFalseIfNotVisible() {
+        final int boolId = ResourcesUtils.getResourcesId(
+                ApplicationProvider.getApplicationContext(), "bool", "config_show_device_model");
+
+        when(mResources.getBoolean(boolId)).thenReturn(false);
         assertThat(mController.getAvailabilityStatus()).isEqualTo(
                 BasePreferenceController.UNSUPPORTED_ON_DEVICE);
     }
diff --git a/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
new file mode 100644
index 0000000..fc1407f
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/HardwareRevisionPreferenceControllerTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.deviceinfo.hardwareinfo;
+
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Looper;
+import android.os.SystemProperties;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(AndroidJUnit4.class)
+public class HardwareRevisionPreferenceControllerTest {
+
+    private Context mContext;
+    private HardwareRevisionPreferenceController mController;
+    private ClipboardManager mClipboardManager;
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+        mController = new HardwareRevisionPreferenceController(mContext,
+                "hardware_info_device_revision");
+    }
+
+    @Test
+    @UiThreadTest
+    public void copy_shouldCopyHardwareRevisionToClipboard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
+        mController.copy();
+
+        final ClipData data = captor.getValue();
+        final String hardwareVer = SystemProperties.get("ro.boot.hardware.revision");
+        assertThat(data.getItemAt(0).getText().toString()).isEqualTo(hardwareVer);
+    }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
new file mode 100644
index 0000000..eaf97d4
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/hardwareinfo/SerialNumberPreferenceControllerTest.java
@@ -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.deviceinfo.hardwareinfo;
+
+import static android.content.Context.CLIPBOARD_SERVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.os.Build;
+import android.os.Looper;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@RunWith(AndroidJUnit4.class)
+public class SerialNumberPreferenceControllerTest {
+
+    private Context mContext;
+    private SerialNumberPreferenceController mController;
+    private ClipboardManager mClipboardManager;
+
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mClipboardManager = (ClipboardManager) spy(mContext.getSystemService(CLIPBOARD_SERVICE));
+        doReturn(mClipboardManager).when(mContext).getSystemService(CLIPBOARD_SERVICE);
+        mController = new SerialNumberPreferenceController(mContext, "test");
+    }
+
+    @Test
+    @UiThreadTest
+    public void copy_shouldPutSerialNumberToClipBoard() {
+        ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class);
+        doNothing().when(mClipboardManager).setPrimaryClip(captor.capture());
+
+        mController.copy();
+
+        final ClipData data = captor.getValue();
+        assertThat(data.getItemAt(0).getText().toString()).contains(Build.getSerial());
+    }
+}