am d9015233: Set up a sync preference and policy for syncing [2]
* commit 'd9015233f50724294bb408f1c56715a581dc4bed': Set up a sync preference and policy for syncing [2]main
commit
c11c9d262d
|
@ -46,5 +46,5 @@ public final class ProductionFlags {
|
||||||
/**
|
/**
|
||||||
* When {@code true}, personal dictionary sync feature is ready to be enabled.
|
* When {@code true}, personal dictionary sync feature is ready to be enabled.
|
||||||
*/
|
*/
|
||||||
public static final boolean ENABLE_PERSONAL_DICTIONARY_SYNC = false;
|
public static final boolean ENABLE_PERSONAL_DICTIONARY_SYNC = ENABLE_ACCOUNT_SIGN_IN && false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.sync;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
|
||||||
|
|
||||||
public class BeanstalkManager {
|
|
||||||
private static final Object sLock = new Object();
|
|
||||||
|
|
||||||
@GuardedBy("sLock")
|
|
||||||
private static BeanstalkManager sInstance;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the singleton instance of {@link BeanstalkManager}.
|
|
||||||
*/
|
|
||||||
@Nonnull
|
|
||||||
public static BeanstalkManager getInstance(Context context) {
|
|
||||||
synchronized(sLock) {
|
|
||||||
if (sInstance == null) {
|
|
||||||
sInstance = new BeanstalkManager(context.getApplicationContext());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BeanstalkManager(final Context context) {
|
|
||||||
// Intentional private constructor for singleton.
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onCreate() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void requestSync() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onDestroy() {
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -56,9 +56,11 @@
|
||||||
<!-- Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
|
<!-- Option for enabling or disabling the split keyboard layout. [CHAR LIMIT=65]-->
|
||||||
<string name="enable_split_keyboard">Enable split keyboard</string>
|
<string name="enable_split_keyboard">Enable split keyboard</string>
|
||||||
|
|
||||||
<string name="sync_now_title" translatable="false">Sync Now</string>
|
<!-- TODO: Enable translation for user-visible strings -->
|
||||||
<string name="sync_now_summary" translatable="false">Sync your personal dictionary</string>
|
<string name="cloud_sync_title" translatable="false">Enable sync</string>
|
||||||
<string name="sync_now_summary_disabled_signed_out" translatable="false">Select an account to enable sync</string>
|
<string name="cloud_sync_summary" translatable="false">Sync your personal dictionary across devices</string>
|
||||||
|
<string name="cloud_sync_summary_disabled_signed_out" translatable="false">Select an account to enable sync</string>
|
||||||
|
<string name="sync_now_title" translatable="false">[DEBUG] Sync Now</string>
|
||||||
|
|
||||||
<!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
|
<!-- Option name for including other IMEs in the language switch list [CHAR LIMIT=30] -->
|
||||||
<string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
|
<string name="include_other_imes_in_language_switch_list">Switch to other input methods</string>
|
||||||
|
|
|
@ -28,7 +28,15 @@
|
||||||
android:title="@string/switch_accounts"
|
android:title="@string/switch_accounts"
|
||||||
android:summary="@string/no_accounts_selected" />
|
android:summary="@string/no_accounts_selected" />
|
||||||
|
|
||||||
<!-- title will be set programmatically to embed application name -->
|
<!-- Summary will be set programmatically to reflect the account status -->
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="pref_enable_cloud_sync"
|
||||||
|
android:title="@string/cloud_sync_title"
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:persistent="true"
|
||||||
|
android:disableDependentsState="false" />
|
||||||
|
|
||||||
|
<!-- Title will be set programmatically to embed application name -->
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="pref_enable_metrics_logging"
|
android:key="pref_enable_metrics_logging"
|
||||||
android:summary="@string/enable_metrics_logging_summary"
|
android:summary="@string/enable_metrics_logging_summary"
|
||||||
|
@ -38,5 +46,6 @@
|
||||||
<!-- This preference (acts like a button) enables the user to initiate an one time sync. -->
|
<!-- This preference (acts like a button) enables the user to initiate an one time sync. -->
|
||||||
<Preference android:key="pref_beanstalk"
|
<Preference android:key="pref_beanstalk"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/sync_now_title" />
|
android:title="@string/sync_now_title"
|
||||||
|
android:dependency="pref_enable_cloud_sync" />
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
|
@ -87,7 +87,6 @@ import com.android.inputmethod.latin.settings.SettingsActivity;
|
||||||
import com.android.inputmethod.latin.settings.SettingsValues;
|
import com.android.inputmethod.latin.settings.SettingsValues;
|
||||||
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
|
||||||
import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
|
import com.android.inputmethod.latin.suggestions.SuggestionStripViewAccessor;
|
||||||
import com.android.inputmethod.latin.sync.BeanstalkManager;
|
|
||||||
import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
|
import com.android.inputmethod.latin.touchinputconsumer.GestureConsumer;
|
||||||
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
import com.android.inputmethod.latin.utils.ApplicationUtils;
|
||||||
import com.android.inputmethod.latin.utils.CapsModeUtils;
|
import com.android.inputmethod.latin.utils.CapsModeUtils;
|
||||||
|
@ -561,7 +560,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
AudioAndHapticFeedbackManager.init(this);
|
AudioAndHapticFeedbackManager.init(this);
|
||||||
AccessibilityUtils.init(this);
|
AccessibilityUtils.init(this);
|
||||||
mStatsUtilsManager.onCreate(this /* context */);
|
mStatsUtilsManager.onCreate(this /* context */);
|
||||||
BeanstalkManager.getInstance(this /* context */).onCreate();
|
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
mHandler.onCreate();
|
mHandler.onCreate();
|
||||||
|
@ -709,7 +707,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
unregisterReceiver(mDictionaryPackInstallReceiver);
|
unregisterReceiver(mDictionaryPackInstallReceiver);
|
||||||
unregisterReceiver(mDictionaryDumpBroadcastReceiver);
|
unregisterReceiver(mDictionaryDumpBroadcastReceiver);
|
||||||
mStatsUtilsManager.onDestroy();
|
mStatsUtilsManager.onDestroy();
|
||||||
BeanstalkManager.getInstance(this /* context */).onDestroy();
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,12 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.settings;
|
package com.android.inputmethod.latin.settings;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ACCOUNT_NAME;
|
||||||
|
import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
@ -33,7 +38,6 @@ import com.android.inputmethod.latin.R;
|
||||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
import com.android.inputmethod.latin.accounts.LoginAccountUtils;
|
import com.android.inputmethod.latin.accounts.LoginAccountUtils;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlags;
|
import com.android.inputmethod.latin.define.ProductionFlags;
|
||||||
import com.android.inputmethod.latin.sync.BeanstalkManager;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -41,19 +45,18 @@ import javax.annotation.Nullable;
|
||||||
* "Accounts & Privacy" settings sub screen.
|
* "Accounts & Privacy" settings sub screen.
|
||||||
*
|
*
|
||||||
* This settings sub screen handles the following preferences:
|
* This settings sub screen handles the following preferences:
|
||||||
* <li> Account selection/management for IME
|
* <li> Account selection/management for IME </li>
|
||||||
* <li> TODO: Sync preferences
|
* <li> Sync preferences </li>
|
||||||
* <li> TODO: Privacy preferences
|
* <li> Privacy preferences </li>
|
||||||
* <li> Sync now
|
|
||||||
*/
|
*/
|
||||||
public final class AccountsSettingsFragment extends SubScreenFragment {
|
public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
|
private static final String PREF_SYNC_NOW = "pref_beanstalk";
|
||||||
static final String PREF_SYNC_NOW = "pref_beanstalk";
|
|
||||||
|
|
||||||
private final DialogInterface.OnClickListener mAccountSelectedListener =
|
@UsedForTesting static final String AUTHORITY = "com.android.inputmethod.latin.provider";
|
||||||
new AccountSelectedListener();
|
static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
|
||||||
private final DialogInterface.OnClickListener mAccountSignedOutListener =
|
|
||||||
new AccountSignedOutListener();
|
private final DialogInterface.OnClickListener mAccountChangedListener =
|
||||||
|
new AccountChangedListener();
|
||||||
private final Preference.OnPreferenceClickListener mSyncNowListener = new SyncNowListener();
|
private final Preference.OnPreferenceClickListener mSyncNowListener = new SyncNowListener();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,47 +84,55 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
|
removePreference(Settings.PREF_ENABLE_METRICS_LOGGING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
|
||||||
|
removePreference(PREF_ACCCOUNT_SWITCHER);
|
||||||
|
removePreference(PREF_ENABLE_CLOUD_SYNC);
|
||||||
|
removePreference(PREF_SYNC_NOW);
|
||||||
|
}
|
||||||
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
|
removePreference(PREF_ENABLE_CLOUD_SYNC);
|
||||||
removePreference(PREF_SYNC_NOW);
|
removePreference(PREF_SYNC_NOW);
|
||||||
} else {
|
} else {
|
||||||
final Preference syncNowPreference = findPreference(PREF_SYNC_NOW);
|
final Preference syncNowPreference = findPreference(PREF_SYNC_NOW);
|
||||||
if (syncNowPreference != null) {
|
syncNowPreference.setOnPreferenceClickListener(mSyncNowListener);
|
||||||
syncNowPreference.setOnPreferenceClickListener(mSyncNowListener);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
refreshUi();
|
refreshAccountAndDependentPreferences(getCurrentlySelectedAccount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) {
|
||||||
// TODO: Look at the preference that changed before refreshing the view.
|
if (TextUtils.equals(key, PREF_ACCOUNT_NAME)) {
|
||||||
refreshUi();
|
refreshAccountAndDependentPreferences(
|
||||||
|
prefs.getString(PREF_ACCOUNT_NAME, null));
|
||||||
|
} else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) {
|
||||||
|
final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
|
||||||
|
updateSyncPolicy(syncEnabled, LoginAccountUtils.getCurrentAccount(getActivity()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshUi() {
|
private void refreshAccountAndDependentPreferences(@Nullable final String currentAccount) {
|
||||||
refreshAccountSelection();
|
|
||||||
refreshSyncNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshAccountSelection() {
|
|
||||||
if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
|
if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String currentAccount = getCurrentlySelectedAccount();
|
|
||||||
final Preference accountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
|
final Preference accountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER);
|
||||||
if (currentAccount == null) {
|
if (currentAccount == null) {
|
||||||
// No account is currently selected.
|
// No account is currently selected.
|
||||||
accountSwitcher.setSummary(getString(R.string.no_accounts_selected));
|
accountSwitcher.setSummary(getString(R.string.no_accounts_selected));
|
||||||
|
// Disable the sync preference UI.
|
||||||
|
disableSyncPreference();
|
||||||
} else {
|
} else {
|
||||||
// Set the currently selected account.
|
// Set the currently selected account.
|
||||||
accountSwitcher.setSummary(getString(R.string.account_selected, currentAccount));
|
accountSwitcher.setSummary(getString(R.string.account_selected, currentAccount));
|
||||||
|
// Enable the sync preference UI.
|
||||||
|
enableSyncPreference();
|
||||||
}
|
}
|
||||||
|
// Set up onClick listener for the account picker preference.
|
||||||
final Context context = getActivity();
|
final Context context = getActivity();
|
||||||
final String[] accountsForLogin = LoginAccountUtils.getAccountsForLogin(context);
|
final String[] accountsForLogin = LoginAccountUtils.getAccountsForLogin(context);
|
||||||
accountSwitcher.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
accountSwitcher.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@ -129,39 +140,64 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
if (accountsForLogin.length == 0) {
|
if (accountsForLogin.length == 0) {
|
||||||
// TODO: Handle account addition.
|
// TODO: Handle account addition.
|
||||||
Toast.makeText(getActivity(),
|
Toast.makeText(getActivity(), getString(R.string.account_select_cancel),
|
||||||
getString(R.string.account_select_cancel), Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
createAccountPicker(accountsForLogin, currentAccount).show();
|
createAccountPicker(accountsForLogin, currentAccount).show();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Depending on the account selection, enable/disable preferences that
|
|
||||||
// depend on an account.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refreshes the "Sync Now" feature
|
* Enables the Sync preference UI and updates its summary.
|
||||||
*/
|
*/
|
||||||
private void refreshSyncNow() {
|
private void enableSyncPreference() {
|
||||||
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Preference syncNowPreference = findPreference(PREF_SYNC_NOW);
|
final Preference syncPreference = findPreference(PREF_ENABLE_CLOUD_SYNC);
|
||||||
if (syncNowPreference == null) {
|
syncPreference.setEnabled(true);
|
||||||
|
syncPreference.setSummary(R.string.cloud_sync_summary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the Sync preference UI and updates its summary to indicate
|
||||||
|
* the fact that an account needs to be selected for sync.
|
||||||
|
*/
|
||||||
|
private void disableSyncPreference() {
|
||||||
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final String currentAccount = getCurrentlySelectedAccount();
|
final Preference syncPreference = findPreference(PREF_ENABLE_CLOUD_SYNC);
|
||||||
if (currentAccount == null) {
|
syncPreference.setEnabled(false);
|
||||||
syncNowPreference.setEnabled(false);
|
syncPreference.setSummary(R.string.cloud_sync_summary_disabled_signed_out);
|
||||||
syncNowPreference.setSummary(R.string.sync_now_summary_disabled_signed_out);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a non-null accountToUse, this method looks at the enabled value to either
|
||||||
|
* set or unset the syncable property of the sync authority.
|
||||||
|
* If the account is null, this method is a no-op currently, but we may want
|
||||||
|
* to perform some cleanup in the future.
|
||||||
|
*/
|
||||||
|
@UsedForTesting
|
||||||
|
void updateSyncPolicy(boolean enabled, Account accountToUse) {
|
||||||
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accountToUse != null) {
|
||||||
|
final int syncable = enabled ? 1 : 0;
|
||||||
|
ContentResolver.setIsSyncable(accountToUse, AUTHORITY, syncable);
|
||||||
|
// TODO: Also add a periodic sync here.
|
||||||
|
// See ContentResolver.addPeriodicSync
|
||||||
} else {
|
} else {
|
||||||
syncNowPreference.setEnabled(true);
|
// Without an account, we cannot really set the sync to off.
|
||||||
syncNowPreference.setSummary(R.string.sync_now_summary);
|
// Hopefully the account sign-out listener would have taken care of that for us.
|
||||||
|
// But cases such as clear data are still not handled cleanly.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +206,10 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isSyncEnabled() {
|
||||||
|
return getSharedPreferences().getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an account picker dialog showing the given accounts in a list and selecting
|
* Creates an account picker dialog showing the given accounts in a list and selecting
|
||||||
* the selected account by default.
|
* the selected account by default.
|
||||||
|
@ -200,51 +240,55 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
|
||||||
.setTitle(R.string.account_select_title)
|
.setTitle(R.string.account_select_title)
|
||||||
.setSingleChoiceItems(accounts, index, null)
|
.setSingleChoiceItems(accounts, index, null)
|
||||||
.setPositiveButton(R.string.account_select_ok, mAccountSelectedListener)
|
.setPositiveButton(R.string.account_select_ok, mAccountChangedListener)
|
||||||
.setNegativeButton(R.string.account_select_cancel, null);
|
.setNegativeButton(R.string.account_select_cancel, null);
|
||||||
if (isSignedIn) {
|
if (isSignedIn) {
|
||||||
builder.setNeutralButton(R.string.account_select_sign_out, mAccountSignedOutListener);
|
builder.setNeutralButton(R.string.account_select_sign_out, mAccountChangedListener);
|
||||||
}
|
}
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for an account being selected from the picker.
|
* Listener for a account selection changes from the picker.
|
||||||
* Persists the account to shared preferences.
|
* Persists/removes the account to/from shared preferences and sets up sync if required.
|
||||||
*/
|
*/
|
||||||
class AccountSelectedListener implements DialogInterface.OnClickListener {
|
class AccountChangedListener implements DialogInterface.OnClickListener {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
final ListView lv = ((AlertDialog)dialog).getListView();
|
switch (which) {
|
||||||
final Object selectedItem = lv.getItemAtPosition(lv.getCheckedItemPosition());
|
case DialogInterface.BUTTON_POSITIVE: // Signed in
|
||||||
getSharedPreferences()
|
final ListView lv = ((AlertDialog)dialog).getListView();
|
||||||
.edit()
|
final Object selectedItem = lv.getItemAtPosition(lv.getCheckedItemPosition());
|
||||||
.putString(LocalSettingsConstants.PREF_ACCOUNT_NAME, (String) selectedItem)
|
getSharedPreferences()
|
||||||
.apply();
|
.edit()
|
||||||
|
.putString(PREF_ACCOUNT_NAME, (String) selectedItem)
|
||||||
|
.apply();
|
||||||
|
// Attempt starting sync for the new account if sync was
|
||||||
|
// previously enabled.
|
||||||
|
// If not, stop it.
|
||||||
|
updateSyncPolicy(isSyncEnabled(),
|
||||||
|
LoginAccountUtils.getCurrentAccount(getActivity()));
|
||||||
|
break;
|
||||||
|
case DialogInterface.BUTTON_NEUTRAL: // Signed out
|
||||||
|
// Stop sync for the account that's being signed out of.
|
||||||
|
updateSyncPolicy(false, LoginAccountUtils.getCurrentAccount(getActivity()));
|
||||||
|
getSharedPreferences()
|
||||||
|
.edit()
|
||||||
|
.remove(PREF_ACCOUNT_NAME)
|
||||||
|
.apply();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for sign-out being initiated from from the picker.
|
* Listener that initiates the process of sync in the background.
|
||||||
* Removed the account from shared preferences.
|
|
||||||
*/
|
|
||||||
class AccountSignedOutListener implements DialogInterface.OnClickListener {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
getSharedPreferences()
|
|
||||||
.edit()
|
|
||||||
.remove(LocalSettingsConstants.PREF_ACCOUNT_NAME)
|
|
||||||
.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener that initates the process of sync in the background.
|
|
||||||
*/
|
*/
|
||||||
class SyncNowListener implements Preference.OnPreferenceClickListener {
|
class SyncNowListener implements Preference.OnPreferenceClickListener {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
public boolean onPreferenceClick(final Preference preference) {
|
||||||
BeanstalkManager.getInstance(getActivity() /* context */).requestSync();
|
ContentResolver.requestSync(
|
||||||
|
LoginAccountUtils.getCurrentAccount(getActivity()), AUTHORITY, Bundle.EMPTY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,9 @@ public class LocalSettingsConstants {
|
||||||
// Preference key for the current account.
|
// Preference key for the current account.
|
||||||
// Do not restore.
|
// Do not restore.
|
||||||
public static final String PREF_ACCOUNT_NAME = "pref_account_name";
|
public static final String PREF_ACCOUNT_NAME = "pref_account_name";
|
||||||
|
// Preference key for enabling cloud sync feature.
|
||||||
|
// Do not restore.
|
||||||
|
public static final String PREF_ENABLE_CLOUD_SYNC = "pref_enable_cloud_sync";
|
||||||
|
|
||||||
// List of preference keys to skip from being restored by backup agent.
|
// 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.
|
// These preferences are tied to a device and hence should not be restored.
|
||||||
|
@ -36,6 +39,7 @@ public class LocalSettingsConstants {
|
||||||
// shared preferences which makes it non-trivial to move these out to
|
// shared preferences which makes it non-trivial to move these out to
|
||||||
// a different shared preferences file.
|
// a different shared preferences file.
|
||||||
public static final String[] PREFS_TO_SKIP_RESTORING = new String[] {
|
public static final String[] PREFS_TO_SKIP_RESTORING = new String[] {
|
||||||
PREF_ACCOUNT_NAME
|
PREF_ACCOUNT_NAME,
|
||||||
|
PREF_ENABLE_CLOUD_SYNC
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,20 @@
|
||||||
|
|
||||||
package com.android.inputmethod.latin.settings;
|
package com.android.inputmethod.latin.settings;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.latin.settings.AccountsSettingsFragment.AUTHORITY;
|
||||||
|
|
||||||
|
import android.accounts.Account;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
import android.test.suitebuilder.annotation.MediumTest;
|
import android.test.suitebuilder.annotation.MediumTest;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
import com.android.inputmethod.latin.define.ProductionFlags;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -32,6 +38,7 @@ public class AccountsSettingsFragmentTests
|
||||||
extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
|
extends ActivityInstrumentationTestCase2<TestFragmentActivity> {
|
||||||
private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
|
private static final String FRAG_NAME = AccountsSettingsFragment.class.getName();
|
||||||
private static final long TEST_TIMEOUT_MILLIS = 5000;
|
private static final long TEST_TIMEOUT_MILLIS = 5000;
|
||||||
|
private static final Account TEST_ACCOUNT = new Account("account-for-test", "account-type");
|
||||||
|
|
||||||
private AlertDialog mDialog;
|
private AlertDialog mDialog;
|
||||||
|
|
||||||
|
@ -47,6 +54,13 @@ public class AccountsSettingsFragmentTests
|
||||||
setActivityIntent(intent);
|
setActivityIntent(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
super.tearDown();
|
||||||
|
// reset the syncable state to unknown
|
||||||
|
ContentResolver.setIsSyncable(TEST_ACCOUNT, AUTHORITY, -1);
|
||||||
|
}
|
||||||
|
|
||||||
public void testEmptyAccounts() {
|
public void testEmptyAccounts() {
|
||||||
final AccountsSettingsFragment fragment =
|
final AccountsSettingsFragment fragment =
|
||||||
(AccountsSettingsFragment) getActivity().mFragment;
|
(AccountsSettingsFragment) getActivity().mFragment;
|
||||||
|
@ -129,4 +143,57 @@ public class AccountsSettingsFragmentTests
|
||||||
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEGATIVE).getVisibility());
|
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_NEGATIVE).getVisibility());
|
||||||
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_POSITIVE).getVisibility());
|
assertEquals(View.VISIBLE, mDialog.getButton(Dialog.BUTTON_POSITIVE).getVisibility());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testUpdateSyncPolicy_enable() {
|
||||||
|
// This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
|
||||||
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Should be unknown by default.
|
||||||
|
assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
|
||||||
|
|
||||||
|
final AccountsSettingsFragment fragment =
|
||||||
|
(AccountsSettingsFragment) getActivity().mFragment;
|
||||||
|
fragment.updateSyncPolicy(true, TEST_ACCOUNT);
|
||||||
|
|
||||||
|
// Should be syncable now.
|
||||||
|
assertEquals(1, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSyncPolicy_disable() {
|
||||||
|
// This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
|
||||||
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Should be unknown by default.
|
||||||
|
assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
|
||||||
|
|
||||||
|
final AccountsSettingsFragment fragment =
|
||||||
|
(AccountsSettingsFragment) getActivity().mFragment;
|
||||||
|
fragment.updateSyncPolicy(false, TEST_ACCOUNT);
|
||||||
|
|
||||||
|
// Should not be syncable now.
|
||||||
|
assertEquals(0, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUpdateSyncPolicy_enableDisable() {
|
||||||
|
// This test is a no-op when ENABLE_PERSONAL_DICTIONARY_SYNC is not enabled
|
||||||
|
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Should be unknown by default.
|
||||||
|
assertTrue(ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY) < 0);
|
||||||
|
|
||||||
|
final AccountsSettingsFragment fragment =
|
||||||
|
(AccountsSettingsFragment) getActivity().mFragment;
|
||||||
|
fragment.updateSyncPolicy(true, TEST_ACCOUNT);
|
||||||
|
|
||||||
|
// Should be syncable now.
|
||||||
|
assertEquals(1, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
||||||
|
|
||||||
|
fragment.updateSyncPolicy(false, TEST_ACCOUNT);
|
||||||
|
|
||||||
|
// Should not be syncable now.
|
||||||
|
assertEquals(0, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue