1 /*
2  * Copyright (C) 2014 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 package com.android.settings;
17 
18 import android.app.admin.DevicePolicyManager;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.res.Resources;
22 import android.os.Bundle;
23 import android.os.UserHandle;
24 import android.provider.Settings;
25 import android.support.v14.preference.SwitchPreference;
26 import android.support.v7.preference.Preference;
27 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
28 import android.support.v7.preference.PreferenceScreen;
29 import android.view.LayoutInflater;
30 import android.view.View;
31 import android.view.ViewGroup;
32 import android.widget.Switch;
33 
34 import com.android.internal.logging.MetricsProto.MetricsEvent;
35 import com.android.internal.widget.LockPatternUtils;
36 import com.android.settings.search.BaseSearchIndexProvider;
37 import com.android.settings.search.Indexable;
38 import com.android.settings.search.SearchIndexableRaw;
39 import com.android.settings.widget.SwitchBar;
40 
41 import java.util.ArrayList;
42 import java.util.List;
43 
44 /**
45  * Screen pinning settings.
46  */
47 public class ScreenPinningSettings extends SettingsPreferenceFragment
48         implements SwitchBar.OnSwitchChangeListener, Indexable {
49 
50     private static final CharSequence KEY_USE_SCREEN_LOCK = "use_screen_lock";
51     private static final int CHANGE_LOCK_METHOD_REQUEST = 43;
52 
53     private SwitchBar mSwitchBar;
54     private SwitchPreference mUseScreenLock;
55     private LockPatternUtils mLockPatternUtils;
56 
57     @Override
getMetricsCategory()58     protected int getMetricsCategory() {
59         return MetricsEvent.SCREEN_PINNING;
60     }
61 
62     @Override
onActivityCreated(Bundle savedInstanceState)63     public void onActivityCreated(Bundle savedInstanceState) {
64         super.onActivityCreated(savedInstanceState);
65 
66         final SettingsActivity activity = (SettingsActivity) getActivity();
67         mLockPatternUtils = new LockPatternUtils(activity);
68 
69 
70         mSwitchBar = activity.getSwitchBar();
71         mSwitchBar.addOnSwitchChangeListener(this);
72         mSwitchBar.show();
73         mSwitchBar.setChecked(isLockToAppEnabled(getActivity()));
74     }
75 
76     @Override
onViewCreated(View view, Bundle savedInstanceState)77     public void onViewCreated(View view, Bundle savedInstanceState) {
78         super.onViewCreated(view, savedInstanceState);
79         ViewGroup parent = (ViewGroup) view.findViewById(android.R.id.list_container);
80         View emptyView = LayoutInflater.from(getContext())
81                 .inflate(R.layout.screen_pinning_instructions, parent, false);
82         parent.addView(emptyView);
83         setEmptyView(emptyView);
84     }
85 
86     @Override
onDestroyView()87     public void onDestroyView() {
88         super.onDestroyView();
89 
90         mSwitchBar.removeOnSwitchChangeListener(this);
91         mSwitchBar.hide();
92     }
93 
isLockToAppEnabled(Context context)94     private static boolean isLockToAppEnabled(Context context) {
95         return Settings.System.getInt(context.getContentResolver(),
96                 Settings.System.LOCK_TO_APP_ENABLED, 0) != 0;
97     }
98 
setLockToAppEnabled(boolean isEnabled)99     private void setLockToAppEnabled(boolean isEnabled) {
100         Settings.System.putInt(getContentResolver(), Settings.System.LOCK_TO_APP_ENABLED,
101                 isEnabled ? 1 : 0);
102         if (isEnabled) {
103             // Set the value to match what we have defaulted to in the UI.
104             setScreenLockUsedSetting(isScreenLockUsed());
105         }
106     }
107 
isScreenLockUsed()108     private boolean isScreenLockUsed() {
109         int def = getCurrentSecurityTitle() != R.string.screen_pinning_unlock_none ? 1 : 0;
110         return Settings.Secure.getInt(getContentResolver(),
111                 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, def) != 0;
112     }
113 
setScreenLockUsed(boolean isEnabled)114     private boolean setScreenLockUsed(boolean isEnabled) {
115         if (isEnabled) {
116             LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
117             int passwordQuality = lockPatternUtils
118                     .getKeyguardStoredPasswordQuality(UserHandle.myUserId());
119             if (passwordQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
120                 Intent chooseLockIntent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
121                 chooseLockIntent.putExtra(
122                         ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
123                         DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
124                 startActivityForResult(chooseLockIntent, CHANGE_LOCK_METHOD_REQUEST);
125                 return false;
126             }
127         }
128         setScreenLockUsedSetting(isEnabled);
129         return true;
130     }
131 
setScreenLockUsedSetting(boolean isEnabled)132     private void setScreenLockUsedSetting(boolean isEnabled) {
133         Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCK_TO_APP_EXIT_LOCKED,
134                 isEnabled ? 1 : 0);
135     }
136 
137     @Override
onActivityResult(int requestCode, int resultCode, Intent data)138     public void onActivityResult(int requestCode, int resultCode, Intent data) {
139         super.onActivityResult(requestCode, resultCode, data);
140         if (requestCode == CHANGE_LOCK_METHOD_REQUEST) {
141             LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
142             boolean validPassQuality = lockPatternUtils.getKeyguardStoredPasswordQuality(
143                     UserHandle.myUserId())
144                     != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
145             setScreenLockUsed(validPassQuality);
146             // Make sure the screen updates.
147             mUseScreenLock.setChecked(validPassQuality);
148         }
149     }
150 
getCurrentSecurityTitle()151     private int getCurrentSecurityTitle() {
152         int quality = mLockPatternUtils.getKeyguardStoredPasswordQuality(
153                 UserHandle.myUserId());
154         switch (quality) {
155             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
156             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
157                 return R.string.screen_pinning_unlock_pin;
158             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
159             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
160             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
161             case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
162                 return R.string.screen_pinning_unlock_password;
163             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
164                 if (mLockPatternUtils.isLockPatternEnabled(UserHandle.myUserId())) {
165                     return R.string.screen_pinning_unlock_pattern;
166                 }
167         }
168         return R.string.screen_pinning_unlock_none;
169     }
170 
171     /**
172      * Listens to the state change of the lock-to-app master switch.
173      */
174     @Override
onSwitchChanged(Switch switchView, boolean isChecked)175     public void onSwitchChanged(Switch switchView, boolean isChecked) {
176         setLockToAppEnabled(isChecked);
177         updateDisplay();
178     }
179 
updateDisplay()180     public void updateDisplay() {
181         PreferenceScreen root = getPreferenceScreen();
182         if (root != null) {
183             root.removeAll();
184         }
185         if (isLockToAppEnabled(getActivity())) {
186             addPreferencesFromResource(R.xml.screen_pinning_settings);
187             root = getPreferenceScreen();
188 
189             mUseScreenLock = (SwitchPreference) root.findPreference(KEY_USE_SCREEN_LOCK);
190             mUseScreenLock.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
191                 @Override
192                 public boolean onPreferenceChange(Preference preference, Object newValue) {
193                     return setScreenLockUsed((boolean) newValue);
194                 }
195             });
196             mUseScreenLock.setChecked(isScreenLockUsed());
197             mUseScreenLock.setTitle(getCurrentSecurityTitle());
198         }
199     }
200 
201     /**
202      * For search
203      */
204     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
205         new BaseSearchIndexProvider() {
206             @Override
207             public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
208                 final List<SearchIndexableRaw> result = new ArrayList<SearchIndexableRaw>();
209 
210                 final Resources res = context.getResources();
211 
212                 // Add fragment title
213                 SearchIndexableRaw data = new SearchIndexableRaw(context);
214                 data.title = res.getString(R.string.screen_pinning_title);
215                 data.screenTitle = res.getString(R.string.screen_pinning_title);
216                 result.add(data);
217 
218                 if (isLockToAppEnabled(context)) {
219                     // Screen lock option
220                     data = new SearchIndexableRaw(context);
221                     data.title = res.getString(R.string.screen_pinning_unlock_none);
222                     data.screenTitle = res.getString(R.string.screen_pinning_title);
223                     result.add(data);
224                 } else {
225                     // Screen pinning description.
226                     data = new SearchIndexableRaw(context);
227                     data.title = res.getString(R.string.screen_pinning_description);
228                     data.screenTitle = res.getString(R.string.screen_pinning_title);
229                     result.add(data);
230                 }
231 
232                 return result;
233             }
234         };
235 }
236