1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.deviceinfo; 18 19 import static android.content.Context.CLIPBOARD_SERVICE; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.verify; 27 28 import android.app.Activity; 29 import android.content.ClipboardManager; 30 import android.content.Context; 31 import android.os.Process; 32 import android.os.UserManager; 33 import android.provider.Settings; 34 35 import androidx.lifecycle.LifecycleOwner; 36 import androidx.preference.Preference; 37 38 import com.android.internal.logging.nano.MetricsProto; 39 import com.android.settings.core.InstrumentedPreferenceFragment; 40 import com.android.settings.testutils.FakeFeatureFactory; 41 import com.android.settings.testutils.shadow.ShadowUtils; 42 import com.android.settingslib.core.lifecycle.Lifecycle; 43 import com.android.settingslib.development.DevelopmentSettingsEnabler; 44 45 import org.junit.After; 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.Answers; 50 import org.mockito.Mock; 51 import org.mockito.MockitoAnnotations; 52 import org.robolectric.RobolectricTestRunner; 53 import org.robolectric.RuntimeEnvironment; 54 import org.robolectric.Shadows; 55 import org.robolectric.annotation.Config; 56 import org.robolectric.shadows.ShadowUserManager; 57 58 @RunWith(RobolectricTestRunner.class) 59 @Config(shadows = ShadowUtils.class) 60 public class BuildNumberPreferenceControllerTest { 61 62 private static final String KEY_BUILD_NUMBER = "build_number"; 63 @Mock(answer = Answers.RETURNS_DEEP_STUBS) 64 private InstrumentedPreferenceFragment mFragment; 65 66 private ShadowUserManager mShadowUserManager; 67 68 private Context mContext; 69 private LifecycleOwner mLifecycleOwner; 70 private Lifecycle mLifecycle; 71 private FakeFeatureFactory mFactory; 72 private Preference mPreference; 73 private BuildNumberPreferenceController mController; 74 75 @Before setUp()76 public void setUp() { 77 MockitoAnnotations.initMocks(this); 78 mContext = RuntimeEnvironment.application; 79 mShadowUserManager = Shadows.shadowOf( 80 RuntimeEnvironment.application.getSystemService(UserManager.class)); 81 mFactory = FakeFeatureFactory.setupForTest(); 82 mLifecycleOwner = () -> mLifecycle; 83 mLifecycle = new Lifecycle(mLifecycleOwner); 84 mController = new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER); 85 mController.setHost(mFragment); 86 87 mPreference = new Preference(mContext); 88 mPreference.setKey(mController.getPreferenceKey()); 89 DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(mContext, false); 90 Settings.Global.putInt(mContext.getContentResolver(), 91 Settings.Global.DEVICE_PROVISIONED, 1); 92 } 93 94 @After tearDown()95 public void tearDown() { 96 ShadowUtils.reset(); 97 } 98 99 @Test handlePrefTreeClick_onlyHandleBuildNumberPref()100 public void handlePrefTreeClick_onlyHandleBuildNumberPref() { 101 assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse(); 102 } 103 104 @Test handlePrefTreeClick_notAdminUser_notDemoUser_doNothing()105 public void handlePrefTreeClick_notAdminUser_notDemoUser_doNothing() { 106 mShadowUserManager.setIsAdminUser(false); 107 mShadowUserManager.setIsDemoUser(false); 108 109 assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); 110 } 111 112 @Test handlePrefTreeClick_isAdminUser_notDemoUser_handleBuildNumberPref()113 public void handlePrefTreeClick_isAdminUser_notDemoUser_handleBuildNumberPref() { 114 mShadowUserManager.setIsAdminUser(true); 115 mShadowUserManager.setIsDemoUser(false); 116 117 assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue(); 118 } 119 120 @Test handlePrefTreeClick_notAdminUser_isDemoUser_handleBuildNumberPref()121 public void handlePrefTreeClick_notAdminUser_isDemoUser_handleBuildNumberPref() { 122 mShadowUserManager.setIsAdminUser(false); 123 mShadowUserManager.setIsDemoUser(true); 124 125 assertThat(mController.handlePreferenceTreeClick(mPreference)).isTrue(); 126 } 127 128 @Test handlePrefTreeClick_deviceNotProvisioned_doNothing()129 public void handlePrefTreeClick_deviceNotProvisioned_doNothing() { 130 mShadowUserManager.setIsAdminUser(true); 131 mShadowUserManager.setIsDemoUser(false); 132 133 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 134 0); 135 136 assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); 137 verify(mFactory.metricsFeatureProvider).action( 138 any(Context.class), 139 eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF)); 140 } 141 142 @Test handlePrefTreeClick_isMonkeyRun_doNothing()143 public void handlePrefTreeClick_isMonkeyRun_doNothing() { 144 ShadowUtils.setIsUserAMonkey(true); 145 assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); 146 } 147 148 @Test handlePrefTreeClick_userHasRestriction_doNothing()149 public void handlePrefTreeClick_userHasRestriction_doNothing() { 150 mShadowUserManager.setIsAdminUser(true); 151 mShadowUserManager.setIsDemoUser(false); 152 153 mShadowUserManager.setUserRestriction(Process.myUserHandle(), 154 UserManager.DISALLOW_DEBUGGING_FEATURES, true); 155 156 assertThat(mController.handlePreferenceTreeClick(mPreference)).isFalse(); 157 verify(mFactory.metricsFeatureProvider).action( 158 any(Context.class), 159 eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_BUILD_NUMBER_PREF)); 160 } 161 162 @Test onActivityResult_notConfirmPasswordRequest_doNothing()163 public void onActivityResult_notConfirmPasswordRequest_doNothing() { 164 final boolean activityResultHandled = mController.onActivityResult( 165 BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF + 1, 166 Activity.RESULT_OK, 167 null); 168 169 assertThat(activityResultHandled).isFalse(); 170 assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); 171 } 172 173 @Test onActivityResult_confirmPasswordRequestFailed_doNotEnableDevPref()174 public void onActivityResult_confirmPasswordRequestFailed_doNotEnableDevPref() { 175 final boolean activityResultHandled = mController.onActivityResult( 176 BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF, 177 Activity.RESULT_CANCELED, 178 null); 179 180 assertThat(activityResultHandled).isTrue(); 181 assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse(); 182 } 183 184 @Test onActivityResult_confirmPasswordRequestCompleted_enableDevPref()185 public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() { 186 mShadowUserManager.setIsAdminUser(true); 187 188 final boolean activityResultHandled = mController.onActivityResult( 189 BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF, 190 Activity.RESULT_OK, 191 null); 192 193 assertThat(activityResultHandled).isTrue(); 194 assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isTrue(); 195 } 196 197 @Test copy_shouldCopyBuildNumberToClipboard()198 public void copy_shouldCopyBuildNumberToClipboard() { 199 mController.copy(); 200 201 final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService( 202 CLIPBOARD_SERVICE); 203 final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText(); 204 assertThat(data.toString()).isEqualTo(mController.getSummary()); 205 } 206 } 207