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 
20 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
21 
22 import android.content.Context;
23 import android.os.UserHandle;
24 import android.os.UserManager;
25 import android.util.Log;
26 
27 import androidx.preference.Preference;
28 import androidx.preference.PreferenceScreen;
29 
30 import com.android.internal.widget.LockPatternUtils;
31 import com.android.settings.R;
32 import com.android.settings.Utils;
33 import com.android.settings.core.TogglePreferenceController;
34 import com.android.settings.overlay.FeatureFactory;
35 import com.android.settingslib.core.lifecycle.Lifecycle;
36 import com.android.settingslib.core.lifecycle.LifecycleObserver;
37 import com.android.settingslib.core.lifecycle.events.OnResume;
38 
39 import java.util.concurrent.ExecutionException;
40 import java.util.concurrent.FutureTask;
41 
42 public class VisiblePatternProfilePreferenceController extends TogglePreferenceController
43         implements LifecycleObserver, OnResume {
44 
45     private static final String KEY_VISIBLE_PATTERN_PROFILE = "visiblepattern_profile";
46     private static final String TAG = "VisPtnProfPrefCtrl";
47 
48     private final LockPatternUtils mLockPatternUtils;
49     private final UserManager mUm;
50     private final int mUserId = UserHandle.myUserId();
51     private final int mProfileChallengeUserId;
52 
53     private Preference mPreference;
54 
VisiblePatternProfilePreferenceController(Context context)55     public VisiblePatternProfilePreferenceController(Context context) {
56         this(context, null /* lifecycle */);
57     }
58 
VisiblePatternProfilePreferenceController(Context context, Lifecycle lifecycle)59     public VisiblePatternProfilePreferenceController(Context context, Lifecycle lifecycle) {
60         this(context, lifecycle, KEY_VISIBLE_PATTERN_PROFILE);
61     }
62 
63 
64     // TODO (b/73074893) Replace this constructor without Lifecycle using setter method instead.
VisiblePatternProfilePreferenceController( Context context, Lifecycle lifecycle, String key)65     public VisiblePatternProfilePreferenceController(
66             Context context, Lifecycle lifecycle, String key) {
67         super(context, key);
68         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
69         mLockPatternUtils = FeatureFactory.getFactory(context)
70                 .getSecurityFeatureProvider()
71                 .getLockPatternUtils(context);
72         mProfileChallengeUserId = Utils.getManagedProfileId(mUm, mUserId);
73         if (lifecycle != null) {
74             lifecycle.addObserver(this);
75         }
76     }
77 
78     @Override
getAvailabilityStatus()79     public int getAvailabilityStatus() {
80         final FutureTask<Integer> futureTask = new FutureTask<>(
81                 // Put the API call in a future to avoid StrictMode violation.
82                 () -> {
83                     final boolean isSecure = mLockPatternUtils.isSecure(mProfileChallengeUserId);
84                     final boolean hasPassword = mLockPatternUtils
85                             .getKeyguardStoredPasswordQuality(mProfileChallengeUserId)
86                             == PASSWORD_QUALITY_SOMETHING;
87                     if (isSecure && hasPassword) {
88                         return AVAILABLE;
89                     }
90                     return DISABLED_FOR_USER;
91                 });
92         try {
93             futureTask.run();
94             return futureTask.get();
95         } catch (InterruptedException | ExecutionException e) {
96             Log.w(TAG, "Error getting lock pattern state.");
97             return DISABLED_FOR_USER;
98         }
99     }
100 
101     @Override
isChecked()102     public boolean isChecked() {
103         return mLockPatternUtils.isVisiblePatternEnabled(
104                 mProfileChallengeUserId);
105     }
106 
107     @Override
setChecked(boolean isChecked)108     public boolean setChecked(boolean isChecked) {
109         if (Utils.startQuietModeDialogIfNecessary(mContext, mUm, mProfileChallengeUserId)) {
110             return false;
111         }
112         mLockPatternUtils.setVisiblePatternEnabled(isChecked, mProfileChallengeUserId);
113         return true;
114     }
115 
116     @Override
displayPreference(PreferenceScreen screen)117     public void displayPreference(PreferenceScreen screen) {
118         super.displayPreference(screen);
119         mPreference = screen.findPreference(getPreferenceKey());
120     }
121 
122     @Override
getSliceHighlightMenuRes()123     public int getSliceHighlightMenuRes() {
124         return R.string.menu_key_security;
125     }
126 
127     @Override
onResume()128     public void onResume() {
129         mPreference.setVisible(isAvailable());
130     }
131 }
132