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