Don't restore device specific preferences

There are two categories of preferences:
1. That are part of the default shared preference
   They were all getting backed up and restored.
   Added a blacklist to not restore some of these.
   e.g. current account

2. That are in a non-default shared preference file.
   These are not getting backed up currently, but added a specific
   local preference file for all such preferences.

Bug: 17288591
Change-Id: I2f748be971a2337543e5014434aa39313fd1e1d8
This commit is contained in:
Sandeep Siddhartha 2014-10-09 12:21:56 -07:00
parent 6e565332df
commit 1e10d29bc8
7 changed files with 107 additions and 35 deletions

View file

@ -17,15 +17,42 @@
package com.android.inputmethod.latin;
import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.SharedPreferencesBackupHelper;
import android.content.SharedPreferences;
import android.os.ParcelFileDescriptor;
import com.android.inputmethod.latin.settings.LocalSettingsConstants;
import java.io.IOException;
/**
* Backs up the Latin IME shared preferences.
* Backup/restore agent for LatinIME.
* Currently it backs up the default shared preferences.
*/
public final class BackupAgent extends BackupAgentHelper {
private static final String PREF_SUFFIX = "_preferences";
@Override
public void onCreate() {
addHelper("shared_pref", new SharedPreferencesBackupHelper(this,
getPackageName() + "_preferences"));
getPackageName() + PREF_SUFFIX));
}
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
// Let the restore operation go through
super.onRestore(data, appVersionCode, newState);
// Remove the preferences that we don't want restored.
final SharedPreferences.Editor prefEditor = getSharedPreferences(
getPackageName() + PREF_SUFFIX, MODE_PRIVATE).edit();
final String[] prefsToRemove = LocalSettingsConstants.PREFS_TO_SKIP_RESTORING;
for (final String key : prefsToRemove) {
prefEditor.remove(key);
}
// Flush the changes to disk.
prefEditor.commit();
}
}

View file

@ -26,7 +26,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.LocalSettingsConstants;
/**
* {@link BroadcastReceiver} for {@link AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION}.
@ -41,25 +41,14 @@ public class AccountsChangedReceiver extends BroadcastReceiver {
return;
}
// Ideally the account preference could live in a different preferences file
// that wasn't being backed up and restored, however the preference fragments
// currently only deal with the default shared preferences which is why
// separating this out into a different file is not trivial currently.
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
final String currentAccount = prefs.getString(Settings.PREF_ACCOUNT_NAME, null);
if (currentAccount != null) {
final String[] accounts = getAccountsForLogin(context);
boolean accountFound = false;
for (String account : accounts) {
if (TextUtils.equals(currentAccount, account)) {
accountFound = true;
break;
}
}
// The current account was not found in the list of accounts, remove it.
if (!accountFound) {
Log.i(TAG, "The current account was removed from the system: " + currentAccount);
prefs.edit()
.remove(Settings.PREF_ACCOUNT_NAME)
.apply();
}
}
final String currentAccount = prefs.getString(
LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
removeUnknownAccountFromPreference(prefs, getAccountsForLogin(context), currentAccount);
}
/**
@ -69,4 +58,24 @@ public class AccountsChangedReceiver extends BroadcastReceiver {
protected String[] getAccountsForLogin(Context context) {
return LoginAccountUtils.getAccountsForLogin(context);
}
/**
* Removes the currentAccount from preferences if it's not found
* in the list of current accounts.
*/
private static void removeUnknownAccountFromPreference(final SharedPreferences prefs,
final String[] accounts, final String currentAccount) {
if (currentAccount == null) {
return;
}
for (final String account : accounts) {
if (TextUtils.equals(currentAccount, account)) {
return;
}
}
Log.i(TAG, "The current account was removed from the system: " + currentAccount);
prefs.edit()
.remove(LocalSettingsConstants.PREF_ACCOUNT_NAME)
.apply();
}
}

View file

@ -167,7 +167,7 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
@Nullable
private String getCurrentlySelectedAccount() {
return getSharedPreferences().getString(Settings.PREF_ACCOUNT_NAME, null);
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
}
/**
@ -219,7 +219,7 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
final Object selectedItem = lv.getItemAtPosition(lv.getCheckedItemPosition());
getSharedPreferences()
.edit()
.putString(Settings.PREF_ACCOUNT_NAME, (String) selectedItem)
.putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, (String) selectedItem)
.apply();
}
}
@ -233,7 +233,7 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
public void onClick(DialogInterface dialog, int which) {
getSharedPreferences()
.edit()
.remove(Settings.PREF_ACCOUNT_NAME)
.remove(LocalSettingsConstants.PREF_ACCOUNT_NAME)
.apply();
}
}

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.latin.settings;
/**
* Collection of device specific preference constants.
*/
public class LocalSettingsConstants {
// Preference file for storing preferences that are tied to a device
// and are not backed up.
public static final String PREFS_FILE = "local_prefs";
// Preference key for the current account.
// Do not restore.
public static final String PREF_ACCOUNT_NAME = "pref_account_name";
// List of preference keys to skip from being restored by backup agent.
// These preferences are tied to a device and hence should not be restored.
// e.g. account name.
// Ideally they could have been kept in a separate file that wasn't backed up
// however the preference UI currently only deals with the default
// shared preferences which makes it non-trivial to move these out to
// a different shared preferences file.
public static final String[] PREFS_TO_SKIP_RESTORING = new String[] {
PREF_ACCOUNT_NAME
};
}

View file

@ -106,8 +106,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal";
public static final String PREF_ENABLE_METRICS_LOGGING = "pref_enable_metrics_logging";
public static final String PREF_ACCOUNT_NAME = "pref_account_name";
// This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
// This is being used only for the backward compatibility.
private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =

View file

@ -64,7 +64,6 @@ public class SettingsValues {
public final boolean mSoundOn;
public final boolean mKeyPreviewPopupOn;
public final boolean mShowsVoiceInputKey;
public final String mAccountName;
public final boolean mIncludesOtherImesInLanguageSwitchList;
public final boolean mShowsLanguageSwitchKey;
public final boolean mUseContactsDict;
@ -141,7 +140,6 @@ public class SettingsValues {
mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
&& mInputAttributes.mShouldShowVoiceInputKey
&& SubtypeSwitcher.getInstance().isShortcutImeEnabled();
mAccountName = prefs.getString(Settings.PREF_ACCOUNT_NAME, null);
final String autoCorrectionThresholdRawValue = prefs.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
res.getString(R.string.auto_correction_threshold_mode_index_modest));
@ -385,8 +383,6 @@ public class SettingsValues {
sb.append("" + mKeyPreviewPopupOn);
sb.append("\n mShowsVoiceInputKey = ");
sb.append("" + mShowsVoiceInputKey);
sb.append("\n mAccountName = ");
sb.append("" + mAccountName);
sb.append("\n mIncludesOtherImesInLanguageSwitchList = ");
sb.append("" + mIncludesOtherImesInLanguageSwitchList);
sb.append("\n mShowsLanguageSwitchKey = ");

View file

@ -23,7 +23,7 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.test.AndroidTestCase;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.LocalSettingsConstants;
/**
* Tests for {@link AccountsChangedReceiver}.
@ -40,7 +40,7 @@ public class AccountsChangedReceiverTests extends AndroidTestCase {
super.setUp();
mPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
// Keep track of the current account so that we restore it when the test finishes.
mLastKnownAccount = mPrefs.getString(Settings.PREF_ACCOUNT_NAME, null);
mLastKnownAccount = mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
}
@Override
@ -99,13 +99,14 @@ public class AccountsChangedReceiverTests extends AndroidTestCase {
private void updateAccountName(String accountName) {
if (accountName == null) {
mPrefs.edit().remove(Settings.PREF_ACCOUNT_NAME).apply();
mPrefs.edit().remove(LocalSettingsConstants.PREF_ACCOUNT_NAME).apply();
} else {
mPrefs.edit().putString(Settings.PREF_ACCOUNT_NAME, accountName).apply();
mPrefs.edit().putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, accountName).apply();
}
}
private void assertAccountName(String expectedAccountName) {
assertEquals(expectedAccountName, mPrefs.getString(Settings.PREF_ACCOUNT_NAME, null));
assertEquals(expectedAccountName,
mPrefs.getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null));
}
}