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.MetricsProto.MetricsEvent;
35import com.android.internal.widget.LockPatternUtils;
36import com.android.settings.search.BaseSearchIndexProvider;
37import com.android.settings.search.Indexable;
38import com.android.settings.search.SearchIndexableRaw;
39import com.android.settings.widget.SwitchBar;
40
41import java.util.ArrayList;
42import java.util.List;
43
44/**
45 * Screen pinning settings.
46 */
47public 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
58    protected int getMetricsCategory() {
59        return MetricsEvent.SCREEN_PINNING;
60    }
61
62    @Override
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
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
87    public void onDestroyView() {
88        super.onDestroyView();
89
90        mSwitchBar.removeOnSwitchChangeListener(this);
91        mSwitchBar.hide();
92    }
93
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
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
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
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
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
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
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
175    public void onSwitchChanged(Switch switchView, boolean isChecked) {
176        setLockToAppEnabled(isChecked);
177        updateDisplay();
178    }
179
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