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