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