1/*
2 * Copyright (C) 2007 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
17package com.android.settings;
18
19import android.app.Activity;
20import android.app.admin.DevicePolicyManager;
21import android.content.Context;
22import android.content.Intent;
23import android.os.Bundle;
24import android.os.UserHandle;
25import android.os.UserManager;
26import android.provider.SearchIndexableResource;
27import android.security.KeyStore;
28import android.support.v7.preference.PreferenceGroup;
29import android.support.v7.preference.PreferenceScreen;
30
31import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
32import com.android.internal.widget.LockPatternUtils;
33import com.android.settings.dashboard.DashboardFragment;
34import com.android.settings.search.BaseSearchIndexProvider;
35import com.android.settings.search.Indexable;
36import com.android.settingslib.RestrictedLockUtils;
37import com.android.settingslib.RestrictedPreference;
38
39import java.util.ArrayList;
40import java.util.List;
41
42/**
43 * Encryption and Credential settings.
44 * TODO: Extends this from {@link DashboardFragment} instead
45 */
46public class EncryptionAndCredential extends SettingsPreferenceFragment implements Indexable {
47
48    private static final String TAG = "EncryptionAndCredential";
49
50    // Misc Settings
51    private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
52    private static final String KEY_USER_CREDENTIALS = "user_credentials";
53    private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
54    private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
55    private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
56
57    private static final int MY_USER_ID = UserHandle.myUserId();
58
59    private UserManager mUm;
60
61    private KeyStore mKeyStore;
62    private RestrictedPreference mResetCredentials;
63
64    private boolean mIsAdmin;
65
66    @Override
67    public int getMetricsCategory() {
68        return MetricsEvent.ENCRYPTION_AND_CREDENTIAL;
69    }
70
71    @Override
72    public void onCreate(Bundle savedInstanceState) {
73        super.onCreate(savedInstanceState);
74
75        final Activity activity = getActivity();
76
77        mUm = UserManager.get(activity);
78    }
79
80    /**
81     * Important!
82     *
83     * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
84     * logic or adding/removing preferences here.
85     */
86    private PreferenceScreen createPreferenceHierarchy() {
87        PreferenceScreen root = getPreferenceScreen();
88        if (root != null) {
89            root.removeAll();
90        }
91        addPreferencesFromResource(R.xml.encryption_and_credential);
92        root = getPreferenceScreen();
93
94        // Add options for device encryption
95        mIsAdmin = mUm.isAdminUser();
96
97        if (mIsAdmin) {
98            if (LockPatternUtils.isDeviceEncryptionEnabled()) {
99                // The device is currently encrypted.
100                addPreferencesFromResource(R.xml.security_settings_encrypted);
101            } else {
102                // This device supports encryption but isn't encrypted.
103                addPreferencesFromResource(R.xml.security_settings_unencrypted);
104            }
105        }
106
107        // Credential storage
108        mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume()
109
110        if (!RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
111                UserManager.DISALLOW_CONFIG_CREDENTIALS, MY_USER_ID)) {
112            RestrictedPreference userCredentials = (RestrictedPreference) root.findPreference(
113                    KEY_USER_CREDENTIALS);
114            userCredentials.checkRestrictionAndSetDisabled(
115                    UserManager.DISALLOW_CONFIG_CREDENTIALS);
116            RestrictedPreference credentialStorageType = (RestrictedPreference) root.findPreference(
117                    KEY_CREDENTIAL_STORAGE_TYPE);
118            credentialStorageType.checkRestrictionAndSetDisabled(
119                    UserManager.DISALLOW_CONFIG_CREDENTIALS);
120            RestrictedPreference installCredentials = (RestrictedPreference) root.findPreference(
121                    KEY_CREDENTIALS_INSTALL);
122            installCredentials.checkRestrictionAndSetDisabled(
123                    UserManager.DISALLOW_CONFIG_CREDENTIALS);
124            mResetCredentials = (RestrictedPreference) root.findPreference(KEY_RESET_CREDENTIALS);
125            mResetCredentials.checkRestrictionAndSetDisabled(
126                    UserManager.DISALLOW_CONFIG_CREDENTIALS);
127
128            final int storageSummaryRes =
129                    mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware
130                            : R.string.credential_storage_type_software;
131            credentialStorageType.setSummary(storageSummaryRes);
132        } else {
133            PreferenceGroup credentialsManager = (PreferenceGroup)
134                    root.findPreference(KEY_CREDENTIALS_MANAGER);
135            credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS));
136            credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL));
137            credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE));
138            credentialsManager.removePreference(root.findPreference(KEY_USER_CREDENTIALS));
139        }
140
141        return root;
142    }
143
144    @Override
145    public void onResume() {
146        super.onResume();
147
148        // Make sure we reload the preference hierarchy since some of these settings
149        // depend on others...
150        createPreferenceHierarchy();
151
152        if (mResetCredentials != null && !mResetCredentials.isDisabledByAdmin()) {
153            mResetCredentials.setEnabled(!mKeyStore.isEmpty());
154        }
155    }
156
157    /**
158     * see confirmPatternThenDisableAndClear
159     */
160    @Override
161    public void onActivityResult(int requestCode, int resultCode, Intent data) {
162        super.onActivityResult(requestCode, resultCode, data);
163        createPreferenceHierarchy();
164    }
165
166    @Override
167    protected int getHelpResource() {
168        return R.string.help_url_encryption;
169    }
170
171    /**
172     * For Search. Please keep it in sync when updating "createPreferenceHierarchy()"
173     */
174    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
175            new SecuritySearchIndexProvider();
176
177    private static class SecuritySearchIndexProvider extends BaseSearchIndexProvider {
178
179        @Override
180        public List<SearchIndexableResource> getXmlResourcesToIndex(
181                Context context, boolean enabled) {
182            final List<SearchIndexableResource> index = new ArrayList<>();
183
184            // Add everything. We will suppress some of them in getNonIndexableKeys()
185            index.add(getSearchResource(context, R.xml.encryption_and_credential));
186            index.add(getSearchResource(context, R.xml.security_settings_encrypted));
187            index.add(getSearchResource(context, R.xml.security_settings_unencrypted));
188
189            return index;
190        }
191
192        @Override
193        protected boolean isPageSearchEnabled(Context context) {
194            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
195            return um.isAdminUser();
196        }
197
198        private SearchIndexableResource getSearchResource(Context context, int xmlResId) {
199            final SearchIndexableResource sir = new SearchIndexableResource(context);
200            sir.xmlResId = xmlResId;
201            return sir;
202        }
203
204        @Override
205        public List<String> getNonIndexableKeys(Context context) {
206            final List<String> keys = super.getNonIndexableKeys(context);
207            if (!isPageSearchEnabled(context)) {
208                return keys;
209            }
210            final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
211
212            if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
213                keys.add(KEY_CREDENTIALS_MANAGER);
214                keys.add(KEY_RESET_CREDENTIALS);
215                keys.add(KEY_CREDENTIALS_INSTALL);
216                keys.add(KEY_CREDENTIAL_STORAGE_TYPE);
217                keys.add(KEY_USER_CREDENTIALS);
218            }
219
220            final DevicePolicyManager dpm = (DevicePolicyManager)
221                    context.getSystemService(Context.DEVICE_POLICY_SERVICE);
222            switch (dpm.getStorageEncryptionStatus()) {
223                case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
224                    // The device is currently encrypted. Disable security_settings_unencrypted
225                    keys.addAll(getNonIndexableKeysFromXml(
226                            context, R.xml.security_settings_unencrypted));
227                    break;
228                default:
229                    // This device supports encryption but isn't encrypted.
230                    keys.addAll(getNonIndexableKeysFromXml(
231                            context, R.xml.security_settings_encrypted));
232                    break;
233            }
234
235            return keys;
236        }
237    }
238
239}
240