From 223484ea3cf8dead9abcda6a07d0224192be7820 Mon Sep 17 00:00:00 2001 From: jeffreyhuang Date: Fri, 15 Sep 2017 16:01:34 -0700 Subject: [PATCH] Introduce OemUnlockPreferenceController - Create new OemUnlockPreferenceController - Add new onActivityResult method in DeveloperOptionsController - Create controller inside the DashboardFragment - Port logic from DevelopmentSettings into the controller Bug: 34203528 Test: make RunSettingsRoboTests -j40 Change-Id: I0b1387b9547e7c9f2a1a0963421d0ebea55d9ff4 --- .../DeveloperOptionsPreferenceController.java | 19 +- ...evelopmentOptionsActivityRequestCodes.java | 24 ++ .../DevelopmentSettingsDashboardFragment.java | 47 +++- .../EnableOemUnlockSettingWarningDialog.java | 82 +++++++ .../development/OemUnlockDialogHost.java | 33 +++ .../OemUnlockPreferenceController.java | 220 ++++++++++++++++++ ...elopmentSettingsDashboardFragmentTest.java | 22 ++ .../OemUnlockPreferenceControllerTest.java | 201 ++++++++++++++++ 8 files changed, 642 insertions(+), 6 deletions(-) create mode 100644 src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java create mode 100644 src/com/android/settings/development/EnableOemUnlockSettingWarningDialog.java create mode 100644 src/com/android/settings/development/OemUnlockDialogHost.java create mode 100644 src/com/android/settings/development/OemUnlockPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/development/OemUnlockPreferenceControllerTest.java diff --git a/src/com/android/settings/development/DeveloperOptionsPreferenceController.java b/src/com/android/settings/development/DeveloperOptionsPreferenceController.java index a7d45ebba8e..7715c254fcb 100644 --- a/src/com/android/settings/development/DeveloperOptionsPreferenceController.java +++ b/src/com/android/settings/development/DeveloperOptionsPreferenceController.java @@ -17,6 +17,7 @@ package com.android.settings.development; import android.content.Context; +import android.content.Intent; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.AbstractPreferenceController; @@ -34,13 +35,29 @@ public abstract class DeveloperOptionsPreferenceController extends super(context); } + /** + * Called when an activity returns to the DeveloperSettingsDashboardFragment. + * + * @param requestCode The integer request code originally supplied to + * startActivityForResult(), allowing you to identify who this + * result came from. + * @param resultCode The integer result code returned by the child activity + * through its setResult(). + * @param data An Intent, which can return result data to the caller + * (various data can be attached to Intent "extras"). + * @return true if the controller handled the activity result + */ + public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + return false; + } + /** * Called when developer options is enabled */ public abstract void onDeveloperOptionsEnabled(); /** - *Called when developer options is disabled + * Called when developer options is disabled */ public abstract void onDeveloperOptionsDisabled(); } diff --git a/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java new file mode 100644 index 00000000000..54d1fa39d23 --- /dev/null +++ b/src/com/android/settings/development/DevelopmentOptionsActivityRequestCodes.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 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.development; + +/** + * Interface for storing Activity request codes in development options + */ +public interface DevelopmentOptionsActivityRequestCodes { + int REQUEST_CODE_ENABLE_OEM_UNLOCK = 0; +} diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 8df25c227c3..89723a8eddd 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -16,10 +16,13 @@ package com.android.settings.development; +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.os.UserManager; import android.provider.SearchIndexableResource; +import android.support.annotation.VisibleForTesting; import android.util.Log; import android.widget.Switch; @@ -40,7 +43,7 @@ import java.util.Arrays; import java.util.List; public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment - implements SwitchBar.OnSwitchChangeListener { + implements SwitchBar.OnSwitchChangeListener, OemUnlockDialogHost { private static final String TAG = "DevSettingsDashboard"; @@ -103,6 +106,33 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra } } + @Override + public void onOemUnlockDialogConfirmed() { + final OemUnlockPreferenceController controller = getDevelopmentOptionsController( + OemUnlockPreferenceController.class); + controller.onOemUnlockConfirmed(); + } + + @Override + public void onOemUnlockDialogDismissed() { + final OemUnlockPreferenceController controller = getDevelopmentOptionsController( + OemUnlockPreferenceController.class); + controller.onOemUnlockDismissed(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + for (AbstractPreferenceController controller : mPreferenceControllers) { + if (controller instanceof DeveloperOptionsPreferenceController) { + if (((DeveloperOptionsPreferenceController) controller).onActivityResult( + requestCode, resultCode, data)) { + return; + } + } + } + super.onActivityResult(requestCode, resultCode, data); + } + @Override protected String getLogTag() { return TAG; @@ -121,7 +151,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra @Override protected List getPreferenceControllers(Context context) { - mPreferenceControllers = buildPreferenceControllers(context, getLifecycle()); + mPreferenceControllers = buildPreferenceControllers(context, getActivity(), getLifecycle(), + this /* devOptionsDashboardFragment */); return mPreferenceControllers; } @@ -140,14 +171,19 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra } private static List buildPreferenceControllers(Context context, - Lifecycle lifecycle) { + Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment) { final List controllers = new ArrayList<>(); controllers.add(new StayAwakePreferenceController(context, lifecycle)); controllers.add(new BluetoothSnoopLogPreferenceController(context)); - + controllers.add(new OemUnlockPreferenceController(context, activity, fragment)); return controllers; } + @VisibleForTesting + T getDevelopmentOptionsController(Class clazz) { + return getPreferenceController(clazz); + } + /** * For Search. */ @@ -171,7 +207,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra @Override public List getPreferenceControllers(Context context) { - return buildPreferenceControllers(context, null /* lifecycle */); + return buildPreferenceControllers(context, null /* activity */, + null /* lifecycle */, null /* devOptionsDashboardFragment */); } }; } diff --git a/src/com/android/settings/development/EnableOemUnlockSettingWarningDialog.java b/src/com/android/settings/development/EnableOemUnlockSettingWarningDialog.java new file mode 100644 index 00000000000..2486ef53589 --- /dev/null +++ b/src/com/android/settings/development/EnableOemUnlockSettingWarningDialog.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 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.development; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.Fragment; +import android.app.FragmentManager; +import android.content.DialogInterface; +import android.os.Bundle; + +import com.android.internal.logging.nano.MetricsProto; +import com.android.settings.R; +import com.android.settings.core.instrumentation.InstrumentedDialogFragment; + +public class EnableOemUnlockSettingWarningDialog extends InstrumentedDialogFragment implements + DialogInterface.OnClickListener, DialogInterface.OnDismissListener { + + public static final String TAG = "EnableOemUnlockDlg"; + + public static void show(Fragment host) { + final FragmentManager manager = host.getActivity().getFragmentManager(); + if (manager.findFragmentByTag(TAG) == null) { + final EnableOemUnlockSettingWarningDialog dialog = + new EnableOemUnlockSettingWarningDialog(); + dialog.setTargetFragment(host, 0 /* requestCode */); + dialog.show(manager, TAG); + } + } + + @Override + public int getMetricsCategory() { + return MetricsProto.MetricsEvent.DIALOG_ENABLE_OEM_UNLOCKING; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setTitle(R.string.confirm_enable_oem_unlock_title) + .setMessage(R.string.confirm_enable_oem_unlock_text) + .setPositiveButton(R.string.enable_text, this /* onClickListener */) + .setNegativeButton(android.R.string.cancel, this /* onClickListener */) + .create(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + final OemUnlockDialogHost host = (OemUnlockDialogHost) getTargetFragment(); + if (host == null) { + return; + } + if (which == DialogInterface.BUTTON_POSITIVE) { + host.onOemUnlockDialogConfirmed(); + } else { + host.onOemUnlockDialogDismissed(); + } + } + + @Override + public void onDismiss(DialogInterface dialog) { + super.onDismiss(dialog); + final OemUnlockDialogHost host = (OemUnlockDialogHost) getTargetFragment(); + if (host == null) { + return; + } + host.onOemUnlockDialogDismissed(); + } +} diff --git a/src/com/android/settings/development/OemUnlockDialogHost.java b/src/com/android/settings/development/OemUnlockDialogHost.java new file mode 100644 index 00000000000..c134e9c2ea2 --- /dev/null +++ b/src/com/android/settings/development/OemUnlockDialogHost.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2017 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.development; + +/** + * Interface for OemUnlockDialogFragment callbacks. + */ +public interface OemUnlockDialogHost { + + /** + * Called when the user presses enable on the warning dialog. + */ + void onOemUnlockDialogConfirmed(); + + /** + * Called when the user dismisses or cancels the warning dialog. + */ + void onOemUnlockDialogDismissed(); +} diff --git a/src/com/android/settings/development/OemUnlockPreferenceController.java b/src/com/android/settings/development/OemUnlockPreferenceController.java new file mode 100644 index 00000000000..7d85d2e20f5 --- /dev/null +++ b/src/com/android/settings/development/OemUnlockPreferenceController.java @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2017 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.development; + +import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes + .REQUEST_CODE_ENABLE_OEM_UNLOCK; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.os.UserHandle; +import android.os.UserManager; +import android.service.oemlock.OemLockManager; +import android.support.annotation.VisibleForTesting; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.telephony.TelephonyManager; + +import com.android.settings.R; +import com.android.settings.password.ChooseLockSettingsHelper; +import com.android.settingslib.RestrictedSwitchPreference; + +public class OemUnlockPreferenceController extends DeveloperOptionsPreferenceController implements + Preference.OnPreferenceChangeListener { + + private static final String PREFERENCE_KEY = "oem_unlock_enable"; + + private final OemLockManager mOemLockManager; + private final UserManager mUserManager; + private final TelephonyManager mTelephonyManager; + private final DevelopmentSettingsDashboardFragment mFragment; + private final ChooseLockSettingsHelper mChooseLockSettingsHelper; + private RestrictedSwitchPreference mPreference; + + public OemUnlockPreferenceController(Context context, Activity activity, + DevelopmentSettingsDashboardFragment fragment) { + super(context); + mOemLockManager = (OemLockManager) context.getSystemService(Context.OEM_LOCK_SERVICE); + mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mFragment = fragment; + if (activity != null || mFragment != null) { + mChooseLockSettingsHelper = new ChooseLockSettingsHelper(activity, mFragment); + } else { + mChooseLockSettingsHelper = null; + } + } + + @Override + public boolean isAvailable() { + return mOemLockManager != null; + } + + @Override + public String getPreferenceKey() { + return PREFERENCE_KEY; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mPreference = (RestrictedSwitchPreference) screen.findPreference(getPreferenceKey()); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean isUnlocked = (Boolean) newValue; + if (isUnlocked) { + if (!showKeyguardConfirmation(mContext.getResources(), + REQUEST_CODE_ENABLE_OEM_UNLOCK)) { + confirmEnableOemUnlock(); + } + } else { + mOemLockManager.setOemUnlockAllowedByUser(false); + } + return true; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + mPreference.setChecked(mOemLockManager.isOemUnlockAllowed()); + updateOemUnlockSettingDescription(); + // Showing mEnableOemUnlock preference as device has persistent data block. + mPreference.setDisabledByAdmin(null); + mPreference.setEnabled(enableOemUnlockPreference()); + if (mPreference.isEnabled()) { + // Check restriction, disable mEnableOemUnlock and apply policy transparency. + mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); + } + } + + @Override + public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) { + if (resultCode == Activity.RESULT_OK) { + if (mPreference.isChecked()) { + confirmEnableOemUnlock(); + } else { + mOemLockManager.setOemUnlockAllowedByUser(false); + } + } + return true; + } + return false; + } + + @Override + public void onDeveloperOptionsEnabled() { + handleDeveloperOptionsToggled(); + } + + @Override + public void onDeveloperOptionsDisabled() { + handleDeveloperOptionsToggled(); + } + + public void onOemUnlockConfirmed() { + mOemLockManager.setOemUnlockAllowedByUser(true); + } + + public void onOemUnlockDismissed() { + if (mPreference == null) { + return; + } + updateState(mPreference); + } + + private void handleDeveloperOptionsToggled() { + if (mPreference == null) { + return; + } + + mPreference.setEnabled(enableOemUnlockPreference()); + if (mPreference.isEnabled()) { + // Check restriction, disable mEnableOemUnlock and apply policy transparency. + mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); + } + } + + private void updateOemUnlockSettingDescription() { + int oemUnlockSummary = R.string.oem_unlock_enable_summary; + if (isBootloaderUnlocked()) { + oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked; + } else if (isSimLockedDevice()) { + oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device; + } else if (!isOemUnlockAllowedByUserAndCarrier()) { + // If the device isn't SIM-locked but OEM unlock is disallowed by some party, this + // means either some other carrier restriction is in place or the device hasn't been + // able to confirm which restrictions (SIM-lock or otherwise) apply. + oemUnlockSummary = + R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked; + } + mPreference.setSummary(mContext.getResources().getString(oemUnlockSummary)); + } + + /** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */ + private boolean isSimLockedDevice() { + int phoneCount = mTelephonyManager.getPhoneCount(); + for (int i = 0; i < phoneCount; i++) { + if (mTelephonyManager.getAllowedCarriers(i).size() > 0) { + return true; + } + } + return false; + } + + /** + * Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}. + */ + private boolean isBootloaderUnlocked() { + return mOemLockManager.isDeviceOemUnlocked(); + } + + private boolean enableOemUnlockPreference() { + return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier(); + } + + + @VisibleForTesting + boolean showKeyguardConfirmation(Resources resources, int requestCode) { + return mChooseLockSettingsHelper.launchConfirmationActivity( + requestCode, resources.getString(R.string.oem_unlock_enable)); + } + + @VisibleForTesting + void confirmEnableOemUnlock() { + EnableOemUnlockSettingWarningDialog.show(mFragment); + } + + /** + * Returns whether OEM unlock is allowed by the user and carrier. + * + * This does not take into account any restrictions imposed by the device policy. + */ + @VisibleForTesting + boolean isOemUnlockAllowedByUserAndCarrier() { + final UserHandle userHandle = UserHandle.of(UserHandle.myUserId()); + return mOemLockManager.isOemUnlockAllowedByCarrier() + && !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, + userHandle); + } + +} diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java index a001aafcdb1..c8748deeac3 100644 --- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java @@ -17,7 +17,11 @@ package com.android.settings.development; import static com.google.common.truth.Truth.assertThat; + +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.content.Context; @@ -161,6 +165,24 @@ public class DevelopmentSettingsDashboardFragmentTest { .isFalse(); } + @Test + public void onOemUnlockDialogConfirmed_shouldCallControllerOemConfirmed() { + final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class); + doReturn(controller).when(mDashboard).getDevelopmentOptionsController( + OemUnlockPreferenceController.class); + mDashboard.onOemUnlockDialogConfirmed(); + verify(controller).onOemUnlockConfirmed(); + } + + @Test + public void onOemUnlockDialogConfirmed_shouldCallControllerOemDismissed() { + final OemUnlockPreferenceController controller = mock(OemUnlockPreferenceController.class); + doReturn(controller).when(mDashboard).getDevelopmentOptionsController( + OemUnlockPreferenceController.class); + mDashboard.onOemUnlockDialogDismissed(); + verify(controller).onOemUnlockDismissed(); + } + @Implements(EnableDevelopmentSettingWarningDialog.class) public static class ShadowEnableDevelopmentSettingWarningDialog { diff --git a/tests/robotests/src/com/android/settings/development/OemUnlockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/OemUnlockPreferenceControllerTest.java new file mode 100644 index 00000000000..13678703bd8 --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/OemUnlockPreferenceControllerTest.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2017 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.development; + +import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes + .REQUEST_CODE_ENABLE_OEM_UNLOCK; + +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 static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.Resources; +import android.os.UserManager; +import android.service.oemlock.OemLockManager; +import android.support.v7.preference.PreferenceScreen; +import android.telephony.TelephonyManager; + +import com.android.settings.TestConfig; +import com.android.settings.testutils.SettingsRobolectricTestRunner; +import com.android.settingslib.RestrictedSwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class OemUnlockPreferenceControllerTest { + + @Mock + private Context mContext; + @Mock + private Activity mActivity; + @Mock + private DevelopmentSettingsDashboardFragment mFragment; + @Mock + private RestrictedSwitchPreference mPreference; + @Mock + private PreferenceScreen mPreferenceScreen; + @Mock + private OemLockManager mOemLockManager; + @Mock + private UserManager mUserManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private Resources mResources; + private OemUnlockPreferenceController mController; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.OEM_LOCK_SERVICE)).thenReturn(mOemLockManager); + when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); + when(mContext.getResources()).thenReturn(mResources); + mController = new OemUnlockPreferenceController(mContext, mActivity, mFragment); + when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn( + mPreference); + mController.displayPreference(mPreferenceScreen); + } + + @Test + public void isAvailable_shouldReturnTrueWhenOemLockManagerIsNotNull() { + boolean returnValue = mController.isAvailable(); + + assertThat(returnValue).isTrue(); + } + + @Test + public void isAvailable_shouldReturnFalseWhenOemLockManagerIsNull() { + when(mContext.getSystemService(Context.OEM_LOCK_SERVICE)).thenReturn(null); + mController = new OemUnlockPreferenceController(mContext, mActivity, mFragment); + boolean returnValue = mController.isAvailable(); + + assertThat(returnValue).isFalse(); + } + + @Test + public void onPreferenceChanged_turnOnUnlock() { + mController = spy(mController); + doReturn(false).when(mController).showKeyguardConfirmation(mResources, + REQUEST_CODE_ENABLE_OEM_UNLOCK); + doNothing().when(mController).confirmEnableOemUnlock(); + mController.onPreferenceChange(null, true); + + verify(mController).confirmEnableOemUnlock(); + } + + @Test + public void onPreferenceChanged_turnOffUnlock() { + mController.onPreferenceChange(null, false); + + verify(mOemLockManager).setOemUnlockAllowedByUser(false); + } + + @Test + public void updateState_preferenceShouldBeCheckedAndShouldBeDisabled() { + mController = spy(mController); + when(mOemLockManager.isOemUnlockAllowed()).thenReturn(true); + doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier(); + when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(true); + mController.updateState(mPreference); + + verify(mPreference).setChecked(true); + verify(mPreference).setEnabled(false); + } + + @Test + public void updateState_preferenceShouldBeUncheckedAndShouldBeDisabled() { + mController = spy(mController); + when(mOemLockManager.isOemUnlockAllowed()).thenReturn(false); + doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier(); + when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(true); + mController.updateState(mPreference); + + verify(mPreference).setChecked(false); + verify(mPreference).setEnabled(false); + } + + @Test + public void updateState_preferenceShouldBeCheckedAndShouldBeEnabled() { + mController = spy(mController); + when(mOemLockManager.isOemUnlockAllowed()).thenReturn(true); + doReturn(true).when(mController).isOemUnlockAllowedByUserAndCarrier(); + when(mOemLockManager.isDeviceOemUnlocked()).thenReturn(false); + mController.updateState(mPreference); + + verify(mPreference).setChecked(true); + verify(mPreference).setEnabled(true); + } + + @Test + public void onActivityResult_shouldReturnTrue() { + final boolean result = mController.onActivityResult(REQUEST_CODE_ENABLE_OEM_UNLOCK, + Activity.RESULT_OK, null); + + assertThat(result).isTrue(); + } + + @Test + public void onActivityResult_shouldReturnFalse() { + final boolean result = mController.onActivityResult(123454, + 1434, null); + + assertThat(result).isFalse(); + } + + @Test + public void onDeveloperOptionsEnabled_preferenceShouldCheckRestriction() { + mController = spy(mController); + doReturn(false).when(mController).isOemUnlockAllowedByUserAndCarrier(); + when(mPreference.isEnabled()).thenReturn(true); + mController.onDeveloperOptionsEnabled(); + + verify(mPreference).checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); + + } + + @Test + public void onDeveloperOptionsDisabled_preferenceShouldCheckRestriction() { + mController = spy(mController); + doReturn(false).when(mController).isOemUnlockAllowedByUserAndCarrier(); + when(mPreference.isEnabled()).thenReturn(true); + mController.onDeveloperOptionsDisabled(); + + verify(mPreference).checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); + + } + + @Test + public void onOemUnlockConfirmed_oemManagerShouldSetUnlockAllowedByUser() { + mController.onOemUnlockConfirmed(); + + verify(mOemLockManager).setOemUnlockAllowedByUser(true); + } +}