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 DevelopmentSettingsDashboardFragment mFragment; 56 private final ChooseLockSettingsHelper mChooseLockSettingsHelper; 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 mFragment = fragment; 73 if (activity != null || mFragment != null) { 74 mChooseLockSettingsHelper = new ChooseLockSettingsHelper(activity, mFragment); 75 } else { 76 mChooseLockSettingsHelper = null; 77 } 78 } 79 80 @Override isAvailable()81 public boolean isAvailable() { 82 return mOemLockManager != null; 83 } 84 85 @Override getPreferenceKey()86 public String getPreferenceKey() { 87 return PREFERENCE_KEY; 88 } 89 90 @Override displayPreference(PreferenceScreen screen)91 public void displayPreference(PreferenceScreen screen) { 92 super.displayPreference(screen); 93 94 mPreference = screen.findPreference(getPreferenceKey()); 95 } 96 97 @Override onPreferenceChange(Preference preference, Object newValue)98 public boolean onPreferenceChange(Preference preference, Object newValue) { 99 boolean isUnlocked = (Boolean) newValue; 100 if (isUnlocked) { 101 if (!showKeyguardConfirmation(mContext.getResources(), 102 REQUEST_CODE_ENABLE_OEM_UNLOCK)) { 103 confirmEnableOemUnlock(); 104 } 105 } else { 106 mOemLockManager.setOemUnlockAllowedByUser(false); 107 OemLockInfoDialog.show(mFragment); 108 } 109 return true; 110 } 111 112 @Override updateState(Preference preference)113 public void updateState(Preference preference) { 114 super.updateState(preference); 115 mPreference.setChecked(isOemUnlockedAllowed()); 116 updateOemUnlockSettingDescription(); 117 // Showing mEnableOemUnlock preference as device has persistent data block. 118 mPreference.setDisabledByAdmin(null); 119 mPreference.setEnabled(enableOemUnlockPreference()); 120 if (mPreference.isEnabled()) { 121 // Check restriction, disable mEnableOemUnlock and apply policy transparency. 122 mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); 123 } 124 } 125 126 @Override onActivityResult(int requestCode, int resultCode, Intent data)127 public boolean onActivityResult(int requestCode, int resultCode, Intent data) { 128 if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) { 129 if (resultCode == Activity.RESULT_OK) { 130 if (mPreference.isChecked()) { 131 confirmEnableOemUnlock(); 132 } else { 133 mOemLockManager.setOemUnlockAllowedByUser(false); 134 } 135 } 136 return true; 137 } 138 return false; 139 } 140 141 @Override onDeveloperOptionsSwitchEnabled()142 protected void onDeveloperOptionsSwitchEnabled() { 143 handleDeveloperOptionsToggled(); 144 } 145 onOemUnlockConfirmed()146 public void onOemUnlockConfirmed() { 147 mOemLockManager.setOemUnlockAllowedByUser(true); 148 } 149 onOemUnlockDismissed()150 public void onOemUnlockDismissed() { 151 if (mPreference == null) { 152 return; 153 } 154 updateState(mPreference); 155 } 156 handleDeveloperOptionsToggled()157 private void handleDeveloperOptionsToggled() { 158 mPreference.setEnabled(enableOemUnlockPreference()); 159 if (mPreference.isEnabled()) { 160 // Check restriction, disable mEnableOemUnlock and apply policy transparency. 161 mPreference.checkRestrictionAndSetDisabled(UserManager.DISALLOW_FACTORY_RESET); 162 } 163 } 164 updateOemUnlockSettingDescription()165 private void updateOemUnlockSettingDescription() { 166 int oemUnlockSummary = R.string.oem_unlock_enable_summary; 167 if (isBootloaderUnlocked()) { 168 oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_bootloader_unlocked; 169 } else if (isSimLockedDevice()) { 170 oemUnlockSummary = R.string.oem_unlock_enable_disabled_summary_sim_locked_device; 171 } else if (!isOemUnlockAllowedByUserAndCarrier()) { 172 // If the device isn't SIM-locked but OEM unlock is disallowed by some party, this 173 // means either some other carrier restriction is in place or the device hasn't been 174 // able to confirm which restrictions (SIM-lock or otherwise) apply. 175 oemUnlockSummary = 176 R.string.oem_unlock_enable_disabled_summary_connectivity_or_locked; 177 } 178 mPreference.setSummary(mContext.getResources().getString(oemUnlockSummary)); 179 } 180 181 /** Returns {@code true} if the device is SIM-locked. Otherwise, returns {@code false}. */ isSimLockedDevice()182 private boolean isSimLockedDevice() { 183 int phoneCount = mTelephonyManager.getPhoneCount(); 184 for (int i = 0; i < phoneCount; i++) { 185 if (mTelephonyManager.getAllowedCarriers(i).size() > 0) { 186 return true; 187 } 188 } 189 return false; 190 } 191 192 /** 193 * Returns {@code true} if the bootloader has been unlocked. Otherwise, returns {code false}. 194 */ 195 @VisibleForTesting isBootloaderUnlocked()196 boolean isBootloaderUnlocked() { 197 return mOemLockManager.isDeviceOemUnlocked(); 198 } 199 enableOemUnlockPreference()200 private boolean enableOemUnlockPreference() { 201 return !isBootloaderUnlocked() && isOemUnlockAllowedByUserAndCarrier(); 202 } 203 204 205 @VisibleForTesting showKeyguardConfirmation(Resources resources, int requestCode)206 boolean showKeyguardConfirmation(Resources resources, int requestCode) { 207 return mChooseLockSettingsHelper.launchConfirmationActivity( 208 requestCode, resources.getString(R.string.oem_unlock_enable)); 209 } 210 211 @VisibleForTesting confirmEnableOemUnlock()212 void confirmEnableOemUnlock() { 213 EnableOemUnlockSettingWarningDialog.show(mFragment); 214 } 215 216 /** 217 * Returns whether OEM unlock is allowed by the user and carrier. 218 * 219 * This does not take into account any restrictions imposed by the device policy. 220 */ 221 @VisibleForTesting isOemUnlockAllowedByUserAndCarrier()222 boolean isOemUnlockAllowedByUserAndCarrier() { 223 final UserHandle userHandle = UserHandle.of(UserHandle.myUserId()); 224 return mOemLockManager.isOemUnlockAllowedByCarrier() 225 && !mUserManager.hasBaseUserRestriction(UserManager.DISALLOW_FACTORY_RESET, 226 userHandle); 227 } 228 229 @VisibleForTesting isOemUnlockedAllowed()230 boolean isOemUnlockedAllowed() { 231 return mOemLockManager.isOemUnlockAllowed(); 232 } 233 234 } 235