PrivacySettings.java revision ac81f26e30352dd441c099012c4489701d9aee2f
1/*
2 * Copyright (C) 2009 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.backup.IBackupManager;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
25import android.os.Bundle;
26import android.os.RemoteException;
27import android.os.ServiceManager;
28import android.os.UserHandle;
29import android.os.UserManager;
30import android.provider.SearchIndexableResource;
31import android.provider.Settings;
32import android.support.annotation.VisibleForTesting;
33import android.support.v14.preference.SwitchPreference;
34import android.support.v7.preference.Preference;
35import android.support.v7.preference.Preference.OnPreferenceChangeListener;
36import android.support.v7.preference.PreferenceScreen;
37import android.util.Log;
38
39import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
40import com.android.settings.search.BaseSearchIndexProvider;
41import com.android.settings.search.Indexable;
42import com.android.settingslib.RestrictedLockUtils;
43
44import java.util.ArrayList;
45import java.util.Collection;
46import java.util.HashSet;
47import java.util.List;
48import java.util.Set;
49
50/**
51 * Gesture lock pattern settings.
52 */
53public class PrivacySettings extends SettingsPreferenceFragment implements Indexable {
54
55    // Vendor specific
56    private static final String GSETTINGS_PROVIDER = "com.google.settings";
57    @VisibleForTesting
58    static final String BACKUP_DATA = "backup_data";
59    @VisibleForTesting
60    static final String AUTO_RESTORE = "auto_restore";
61    @VisibleForTesting
62    static final String CONFIGURE_ACCOUNT = "configure_account";
63    @VisibleForTesting
64    static final String DATA_MANAGEMENT = "data_management";
65    private static final String BACKUP_INACTIVE = "backup_inactive";
66    private static final String FACTORY_RESET = "factory_reset";
67    private static final String TAG = "PrivacySettings";
68    private IBackupManager mBackupManager;
69    private Preference mBackup;
70    private SwitchPreference mAutoRestore;
71    private Preference mConfigure;
72    private Preference mManageData;
73    private boolean mEnabled;
74
75    @Override
76    public int getMetricsCategory() {
77        return MetricsEvent.PRIVACY;
78    }
79
80    @Override
81    public void onCreate(Bundle savedInstanceState) {
82        super.onCreate(savedInstanceState);
83        // Don't allow any access if this is not an admin user.
84        // TODO: backup/restore currently only works with owner user b/22760572
85        mEnabled = UserManager.get(getActivity()).isAdminUser();
86        if (!mEnabled) {
87            return;
88        }
89
90        addPreferencesFromResource(R.xml.privacy_settings);
91        final PreferenceScreen screen = getPreferenceScreen();
92        mBackupManager = IBackupManager.Stub.asInterface(
93                ServiceManager.getService(Context.BACKUP_SERVICE));
94
95        setPreferenceReferences(screen);
96
97        Set<String> keysToRemove = new HashSet<>();
98        getNonVisibleKeys(getActivity(), keysToRemove);
99        final int screenPreferenceCount = screen.getPreferenceCount();
100        for (int i = screenPreferenceCount - 1; i >= 0; --i) {
101            Preference preference = screen.getPreference(i);
102            if (keysToRemove.contains(preference.getKey())) {
103                screen.removePreference(preference);
104            }
105        }
106
107        updateToggles();
108    }
109
110    @Override
111    public void onResume() {
112        super.onResume();
113
114        // Refresh UI
115        if (mEnabled) {
116            updateToggles();
117        }
118    }
119
120    @VisibleForTesting
121    void setPreferenceReferences(PreferenceScreen screen) {
122        mBackup = screen.findPreference(BACKUP_DATA);
123
124        mAutoRestore = (SwitchPreference) screen.findPreference(AUTO_RESTORE);
125        mAutoRestore.setOnPreferenceChangeListener(preferenceChangeListener);
126
127        mConfigure = screen.findPreference(CONFIGURE_ACCOUNT);
128        mManageData = screen.findPreference(DATA_MANAGEMENT);
129    }
130
131    private OnPreferenceChangeListener preferenceChangeListener = new OnPreferenceChangeListener() {
132        @Override
133        public boolean onPreferenceChange(Preference preference, Object newValue) {
134            if (!(preference instanceof SwitchPreference)) {
135                return true;
136            }
137            boolean nextValue = (Boolean) newValue;
138            boolean result = false;
139            if (preference == mAutoRestore) {
140                try {
141                    mBackupManager.setAutoRestore(nextValue);
142                    result = true;
143                } catch (RemoteException e) {
144                    mAutoRestore.setChecked(!nextValue);
145                }
146            }
147            return result;
148        }
149    };
150
151
152    /*
153     * Creates toggles for each backup/reset preference.
154     */
155    private void updateToggles() {
156        ContentResolver res = getContentResolver();
157
158        boolean backupEnabled = false;
159        Intent configIntent = null;
160        String configSummary = null;
161        Intent manageIntent = null;
162        String manageLabel = null;
163        try {
164            backupEnabled = mBackupManager.isBackupEnabled();
165            String transport = mBackupManager.getCurrentTransport();
166            configIntent = validatedActivityIntent(
167                    mBackupManager.getConfigurationIntent(transport), "config");
168            configSummary = mBackupManager.getDestinationString(transport);
169            manageIntent = validatedActivityIntent(
170                    mBackupManager.getDataManagementIntent(transport), "management");
171            manageLabel = mBackupManager.getDataManagementLabel(transport);
172
173            mBackup.setSummary(backupEnabled
174                    ? R.string.accessibility_feature_state_on
175                    : R.string.accessibility_feature_state_off);
176        } catch (RemoteException e) {
177            // leave it 'false' and disable the UI; there's no backup manager
178            mBackup.setEnabled(false);
179        }
180
181        mAutoRestore.setChecked(Settings.Secure.getInt(res,
182                Settings.Secure.BACKUP_AUTO_RESTORE, 1) == 1);
183        mAutoRestore.setEnabled(backupEnabled);
184
185        final boolean configureEnabled = (configIntent != null) && backupEnabled;
186        mConfigure.setEnabled(configureEnabled);
187        mConfigure.setIntent(configIntent);
188        setConfigureSummary(configSummary);
189
190        final boolean manageEnabled = (manageIntent != null) && backupEnabled;
191        if (manageEnabled) {
192            mManageData.setIntent(manageIntent);
193            if (manageLabel != null) {
194                mManageData.setTitle(manageLabel);
195            }
196        } else {
197            // Hide the item if data management intent is not supported by transport.
198            getPreferenceScreen().removePreference(mManageData);
199        }
200    }
201
202    private Intent validatedActivityIntent(Intent intent, String logLabel) {
203        if (intent != null) {
204            PackageManager pm = getPackageManager();
205            List<ResolveInfo> resolved = pm.queryIntentActivities(intent, 0);
206            if (resolved == null || resolved.isEmpty()) {
207                intent = null;
208                Log.e(TAG, "Backup " + logLabel + " intent " + intent
209                        + " fails to resolve; ignoring");
210            }
211        }
212        return intent;
213    }
214
215    private void setConfigureSummary(String summary) {
216        if (summary != null) {
217            mConfigure.setSummary(summary);
218        } else {
219            mConfigure.setSummary(R.string.backup_configure_account_default_summary);
220        }
221    }
222
223    @Override
224    protected int getHelpResource() {
225        return R.string.help_url_backup_reset;
226    }
227
228    /**
229     * For Search.
230     */
231    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
232            new PrivacySearchIndexProvider();
233
234    private static class PrivacySearchIndexProvider extends BaseSearchIndexProvider {
235
236        boolean mIsPrimary;
237
238        public PrivacySearchIndexProvider() {
239            super();
240
241            mIsPrimary = UserHandle.myUserId() == UserHandle.USER_SYSTEM;
242        }
243
244        @Override
245        public List<SearchIndexableResource> getXmlResourcesToIndex(
246                Context context, boolean enabled) {
247
248            List<SearchIndexableResource> result = new ArrayList<SearchIndexableResource>();
249
250            // For non-primary user, no backup or reset is available
251            // TODO: http://b/22388012
252            if (!mIsPrimary) {
253                return result;
254            }
255
256            SearchIndexableResource sir = new SearchIndexableResource(context);
257            sir.xmlResId = R.xml.privacy_settings;
258            result.add(sir);
259
260            return result;
261        }
262
263        @Override
264        public List<String> getNonIndexableKeys(Context context) {
265            final List<String> nonVisibleKeys = new ArrayList<>();
266            getNonVisibleKeys(context, nonVisibleKeys);
267            return nonVisibleKeys;
268        }
269    }
270
271    private static void getNonVisibleKeys(Context context, Collection<String> nonVisibleKeys) {
272        final IBackupManager backupManager = IBackupManager.Stub.asInterface(
273                ServiceManager.getService(Context.BACKUP_SERVICE));
274        boolean isServiceActive = false;
275        try {
276            isServiceActive = backupManager.isBackupServiceActive(UserHandle.myUserId());
277        } catch (RemoteException e) {
278            Log.w(TAG, "Failed querying backup manager service activity status. " +
279                    "Assuming it is inactive.");
280        }
281        boolean vendorSpecific = context.getPackageManager().
282                resolveContentProvider(GSETTINGS_PROVIDER, 0) == null;
283        if (vendorSpecific || isServiceActive) {
284            nonVisibleKeys.add(BACKUP_INACTIVE);
285        }
286        if (vendorSpecific || !isServiceActive) {
287            nonVisibleKeys.add(BACKUP_DATA);
288            nonVisibleKeys.add(AUTO_RESTORE);
289            nonVisibleKeys.add(CONFIGURE_ACCOUNT);
290        }
291        if (RestrictedLockUtils.hasBaseUserRestriction(context,
292                UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId())) {
293            nonVisibleKeys.add(FACTORY_RESET);
294        }
295    }
296}
297