1 /* 2 * Copyright (C) 2017 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.development; 18 19 import static com.android.settings.development.DevelopmentOptionsActivityRequestCodes.REQUEST_CODE_ENABLE_OEM_UNLOCK; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.res.Resources; 25 import android.os.Build; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 import android.service.oemlock.OemLockManager; 29 import android.telephony.TelephonyManager; 30 31 import androidx.annotation.VisibleForTesting; 32 import androidx.preference.Preference; 33 import androidx.preference.PreferenceScreen; 34 35 import com.android.settings.R; 36 import com.android.settings.core.PreferenceControllerMixin; 37 import com.android.settings.password.ChooseLockSettingsHelper; 38 import com.android.settingslib.RestrictedSwitchPreference; 39 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 40 41 public class OemUnlockPreferenceController extends DeveloperOptionsPreferenceController implements 42 Preference.OnPreferenceChangeListener, PreferenceControllerMixin, OnActivityResultListener { 43 44 private static final String PREFERENCE_KEY = "oem_unlock_enable"; 45 private static final String TAG = "OemUnlockPreferenceController"; 46 47 private final OemLockManager mOemLockManager; 48 private final UserManager mUserManager; 49 private final TelephonyManager mTelephonyManager; 50 private final DevelopmentSettingsDashboardFragment mFragment; 51 private final ChooseLockSettingsHelper mChooseLockSettingsHelper; 52 private RestrictedSwitchPreference mPreference; 53 OemUnlockPreferenceController(Context context, Activity activity, DevelopmentSettingsDashboardFragment fragment)54 public OemUnlockPreferenceController(Context context, Activity activity, 55 DevelopmentSettingsDashboardFragment fragment) { 56 super(context); 57 58 if (Build.IS_EMULATOR && Build.IS_ENG) { 59 mOemLockManager = null; 60 } else { 61 mOemLockManager = (OemLockManager) context.getSystemService(Context.OEM_LOCK_SERVICE); 62 } 63 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 64 mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 65 mFragment = fragment; 66 if (activity != null || mFragment != null) { 67 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(activity, mFragment); 68 } else { 69 mChooseLockSettingsHelper = null; 70 } 71 } 72 73 @Override isAvailable()74 public boolean isAvailable() { 75 return mOemLockManager != null; 76 } 77 78 @Override getPreferenceKey()79 public String getPreferenceKey() { 80 return PREFERENCE_KEY; 81 } 82 83 @Override displayPreference(PreferenceScreen screen)84 public void displayPreference(PreferenceScreen screen) { 85 super.displayPreference(screen); 86 87 mPreference = screen.findPreference(getPreferenceKey()); 88 } 89 90 @Override onPreferenceChange(Preference preference, Object newValue)91 public boolean onPreferenceChange(Preference preference, Object newValue) { 92 boolean isUnlocked = (Boolean) newValue; 93 if (isUnlocked) { 94 if (!showKeyguardConfirmation(mContext.getResources(), 95 REQUEST_CODE_ENABLE_OEM_UNLOCK)) { 96 confirmEnableOemUnlock(); 97 } 98 } else { 99 mOemLockManager.setOemUnlockAllowedByUser(false); 100 OemLockInfoDialog.show(mFragment); 101 } 102 return true; 103 } 104 105 @Override updateState(Preference preference)106 public void updateState(Preference preference) { 107 super.updateState(preference); 108 mPreference.setChecked(isOemUnlockedAllowed()); 109 updateOemUnlockSettingDescription(); 110 // Showing mEnableOemUnlock preference as device has persistent data block. 111 mPreference.setDisabledByAdmin(null); 112 mPreference.setEnabled(enableOemUnlockPreference()); 113 if (mPreference.isEnabled()) { 114 // Check restriction, disable mEnableOemUnlock and apply policy transparency. 115 mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); 116 } 117 } 118 119 @Override onActivityResult(int requestCode, int resultCode, Intent data)120 public boolean onActivityResult(int requestCode, int resultCode, Intent data) { 121 if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) { 122 if (resultCode == Activity.RESULT_OK) { 123 if (mPreference.isChecked()) { 124 confirmEnableOemUnlock(); 125 } else { 126 mOemLockManager.setOemUnlockAllowedByUser(false); 127 } 128 } 129 return true; 130 } 131 return false; 132 } 133 134 @Override onDeveloperOptionsSwitchEnabled()135 protected void onDeveloperOptionsSwitchEnabled() { 136 handleDeveloperOptionsToggled(); 137 } 138 onOemUnlockConfirmed()139 public void onOemUnlockConfirmed() { 140 mOemLockManager.setOemUnlockAllowedByUser(true); 141 } 142 onOemUnlockDismissed()143 public void onOemUnlockDismissed() { 144 if (mPreference == null) { 145 return; 146 } 147 updateState(mPreference); 148 } 149 handleDeveloperOptionsToggled()150 private void handleDeveloperOptionsToggled() { 151 mPreference.setEnabled(enableOemUnlockPreference()); 152 if (mPreference.isEnabled()) { 153 // Check restriction, disable mEnableOemUnlock and apply policy transparency. 154 mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); 155 } 156 } 157 updateOemUnlockSettingDescription()158 private void updateOemUnlockSettingDescription() { 159 int oemUnlockSummary = R.string.oem_unlock_enable_summary; 160 if (isBootloaderUnlocked()) { 161 oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked; 162 } else if (isSimLockedDevice()) { 163 oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device; 164 } else if (!isOemUnlockAllowedByUserAndCarrier()) { 165 // If the device isn't SIM-locked but OEM unlock is disallowed by some party, this 166 // means either some other carrier restriction is in place or the device hasn't been 167 // able to confirm which restrictions (SIM-lock or otherwise) apply. 168 oemUnlockSummary = 169 R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked; 170 } 171 mPreference.setSummary(mContext.getResources().getString(oemUnlockSummary)); 172 } 173 174 /** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */ isSimLockedDevice()175 private boolean isSimLockedDevice() { 176 int phoneCount = mTelephonyManager.getPhoneCount(); 177 for (int i = 0; i < phoneCount; i++) { 178 if (mTelephonyManager.getAllowedCarriers(i).size() > 0) { 179 return true; 180 } 181 } 182 return false; 183 } 184 185 /** 186 * Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}. 187 */ 188 @VisibleForTesting isBootloaderUnlocked()189 boolean isBootloaderUnlocked() { 190 return mOemLockManager.isDeviceOemUnlocked(); 191 } 192 enableOemUnlockPreference()193 private boolean enableOemUnlockPreference() { 194 return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier(); 195 } 196 197 198 @VisibleForTesting showKeyguardConfirmation(Resources resources, int requestCode)199 boolean showKeyguardConfirmation(Resources resources, int requestCode) { 200 return mChooseLockSettingsHelper.launchConfirmationActivity( 201 requestCode, resources.getString(R.string.oem_unlock_enable)); 202 } 203 204 @VisibleForTesting confirmEnableOemUnlock()205 void confirmEnableOemUnlock() { 206 EnableOemUnlockSettingWarningDialog.show(mFragment); 207 } 208 209 /** 210 * Returns whether OEM unlock is allowed by the user and carrier. 211 * 212 * This does not take into account any restrictions imposed by the device policy. 213 */ 214 @VisibleForTesting isOemUnlockAllowedByUserAndCarrier()215 boolean isOemUnlockAllowedByUserAndCarrier() { 216 final UserHandle userHandle = UserHandle.of(UserHandle.myUserId()); 217 return mOemLockManager.isOemUnlockAllowedByCarrier() 218 && !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, 219 userHandle); 220 } 221 222 @VisibleForTesting isOemUnlockedAllowed()223 boolean isOemUnlockedAllowed() { 224 return mOemLockManager.isOemUnlockAllowed(); 225 } 226 227 } 228