• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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