Home | History | Annotate | Download | only in security
      1 /*
      2  * Copyright (C) 2018 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.security;
     18 
     19 import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_DEVICE_REQUEST;
     20 import static com.android.settings.security.SecuritySettings.UNIFY_LOCK_CONFIRM_PROFILE_REQUEST;
     21 import static com.android.settings.security.SecuritySettings.UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST;
     22 
     23 import android.app.Activity;
     24 import android.app.admin.DevicePolicyManager;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.os.Bundle;
     28 import android.os.UserHandle;
     29 import android.os.UserManager;
     30 import android.support.v7.preference.Preference;
     31 import android.support.v7.preference.PreferenceScreen;
     32 
     33 import com.android.internal.widget.LockPatternUtils;
     34 import com.android.settings.R;
     35 import com.android.settings.Utils;
     36 import com.android.settings.core.PreferenceControllerMixin;
     37 import com.android.settings.core.SubSettingLauncher;
     38 import com.android.settings.overlay.FeatureFactory;
     39 import com.android.settings.password.ChooseLockGeneric;
     40 import com.android.settings.password.ChooseLockSettingsHelper;
     41 import com.android.settingslib.RestrictedLockUtils;
     42 import com.android.settingslib.RestrictedSwitchPreference;
     43 import com.android.settingslib.core.AbstractPreferenceController;
     44 
     45 public class LockUnificationPreferenceController extends AbstractPreferenceController
     46         implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
     47 
     48     private static final String KEY_UNIFICATION = "unification";
     49 
     50     private static final int MY_USER_ID = UserHandle.myUserId();
     51 
     52     private final UserManager mUm;
     53     private final LockPatternUtils mLockPatternUtils;
     54     private final int mProfileChallengeUserId;
     55     private final SecuritySettings mHost;
     56 
     57     private RestrictedSwitchPreference mUnifyProfile;
     58 
     59 
     60     private String mCurrentDevicePassword;
     61     private String mCurrentProfilePassword;
     62 
     63     @Override
     64     public void displayPreference(PreferenceScreen screen) {
     65         super.displayPreference(screen);
     66         mUnifyProfile = (RestrictedSwitchPreference) screen.findPreference(KEY_UNIFICATION);
     67     }
     68 
     69     public LockUnificationPreferenceController(Context context, SecuritySettings host) {
     70         super(context);
     71         mHost = host;
     72         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
     73         mLockPatternUtils = FeatureFactory.getFactory(context)
     74                 .getSecurityFeatureProvider()
     75                 .getLockPatternUtils(context);
     76         mProfileChallengeUserId = Utils.getManagedProfileId(mUm, MY_USER_ID);
     77     }
     78 
     79     @Override
     80     public boolean isAvailable() {
     81         final boolean allowSeparateProfileChallenge =
     82                 mProfileChallengeUserId != UserHandle.USER_NULL
     83                         && mLockPatternUtils.isSeparateProfileChallengeAllowed(
     84                         mProfileChallengeUserId);
     85         return allowSeparateProfileChallenge;
     86     }
     87 
     88     @Override
     89     public String getPreferenceKey() {
     90         return KEY_UNIFICATION;
     91     }
     92 
     93     @Override
     94     public boolean onPreferenceChange(Preference preference, Object value) {
     95         if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) {
     96             return false;
     97         }
     98         if ((Boolean) value) {
     99             final boolean compliantForDevice =
    100                     (mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId)
    101                             >= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
    102                             && mLockPatternUtils.isSeparateProfileChallengeAllowedToUnify(
    103                             mProfileChallengeUserId));
    104             UnificationConfirmationDialog dialog =
    105                     UnificationConfirmationDialog.newInstance(compliantForDevice);
    106             dialog.show(mHost);
    107         } else {
    108             final String title = mContext.getString(R.string.unlock_set_unlock_launch_picker_title);
    109             final ChooseLockSettingsHelper helper =
    110                     new ChooseLockSettingsHelper(mHost.getActivity(), mHost);
    111             if (!helper.launchConfirmationActivity(
    112                     UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST,
    113                     title, true /* returnCredentials */, MY_USER_ID)) {
    114                 ununifyLocks();
    115             }
    116         }
    117         return true;
    118     }
    119 
    120     @Override
    121     public void updateState(Preference preference) {
    122         if (mUnifyProfile != null) {
    123             final boolean separate =
    124                     mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId);
    125             mUnifyProfile.setChecked(!separate);
    126             if (separate) {
    127                 mUnifyProfile.setDisabledByAdmin(RestrictedLockUtils.checkIfRestrictionEnforced(
    128                         mContext, UserManager.DISALLOW_UNIFIED_PASSWORD,
    129                         mProfileChallengeUserId));
    130             }
    131         }
    132     }
    133 
    134     public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
    135         if (requestCode == UNUNIFY_LOCK_CONFIRM_DEVICE_REQUEST
    136                 && resultCode == Activity.RESULT_OK) {
    137             ununifyLocks();
    138             return true;
    139         } else if (requestCode == UNIFY_LOCK_CONFIRM_DEVICE_REQUEST
    140                 && resultCode == Activity.RESULT_OK) {
    141             mCurrentDevicePassword =
    142                     data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
    143             launchConfirmProfileLockForUnification();
    144             return true;
    145         } else if (requestCode == UNIFY_LOCK_CONFIRM_PROFILE_REQUEST
    146                 && resultCode == Activity.RESULT_OK) {
    147             mCurrentProfilePassword =
    148                     data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
    149             unifyLocks();
    150             return true;
    151         }
    152         return false;
    153     }
    154 
    155     private void ununifyLocks() {
    156         final Bundle extras = new Bundle();
    157         extras.putInt(Intent.EXTRA_USER_ID, mProfileChallengeUserId);
    158         new SubSettingLauncher(mContext)
    159                 .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName())
    160                     .setTitle(R.string.lock_settings_picker_title_profile)
    161                 .setSourceMetricsCategory(mHost.getMetricsCategory())
    162                 .setArguments(extras)
    163                 .launch();
    164     }
    165 
    166     void launchConfirmDeviceLockForUnification() {
    167         final String title = mContext.getString(
    168                 R.string.unlock_set_unlock_launch_picker_title);
    169         final ChooseLockSettingsHelper helper =
    170                 new ChooseLockSettingsHelper(mHost.getActivity(), mHost);
    171         if (!helper.launchConfirmationActivity(
    172                 UNIFY_LOCK_CONFIRM_DEVICE_REQUEST, title, true, MY_USER_ID)) {
    173             launchConfirmProfileLockForUnification();
    174         }
    175     }
    176 
    177     private void launchConfirmProfileLockForUnification() {
    178         final String title = mContext.getString(
    179                 R.string.unlock_set_unlock_launch_picker_title_profile);
    180         final ChooseLockSettingsHelper helper =
    181                 new ChooseLockSettingsHelper(mHost.getActivity(), mHost);
    182         if (!helper.launchConfirmationActivity(
    183                 UNIFY_LOCK_CONFIRM_PROFILE_REQUEST, title, true, mProfileChallengeUserId)) {
    184             unifyLocks();
    185             // TODO: update relevant prefs.
    186             // createPreferenceHierarchy();
    187         }
    188     }
    189 
    190     private void unifyLocks() {
    191         int profileQuality =
    192                 mLockPatternUtils.getKeyguardStoredPasswordQuality(mProfileChallengeUserId);
    193         if (profileQuality == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
    194             mLockPatternUtils.saveLockPattern(
    195                     LockPatternUtils.stringToPattern(mCurrentProfilePassword),
    196                     mCurrentDevicePassword, MY_USER_ID);
    197         } else {
    198             mLockPatternUtils.saveLockPassword(
    199                     mCurrentProfilePassword, mCurrentDevicePassword,
    200                     profileQuality, MY_USER_ID);
    201         }
    202         mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false,
    203                 mCurrentProfilePassword);
    204         final boolean profilePatternVisibility =
    205                 mLockPatternUtils.isVisiblePatternEnabled(mProfileChallengeUserId);
    206         mLockPatternUtils.setVisiblePatternEnabled(profilePatternVisibility, MY_USER_ID);
    207         mCurrentDevicePassword = null;
    208         mCurrentProfilePassword = null;
    209     }
    210 
    211     void unifyUncompliantLocks() {
    212         mLockPatternUtils.setSeparateProfileChallengeEnabled(mProfileChallengeUserId, false,
    213                 mCurrentProfilePassword);
    214         new SubSettingLauncher(mContext)
    215                 .setDestination(ChooseLockGeneric.ChooseLockGenericFragment.class.getName())
    216                 .setTitle(R.string.lock_settings_picker_title)
    217                 .setSourceMetricsCategory(mHost.getMetricsCategory())
    218                 .launch();
    219     }
    220 
    221 }
    222