Move sync policy related code out of account settings
Bug: 17981687 Bug: 17464069 Change-Id: I0ae3400564fd346cc84af74dfef65f01cc1ce6a8
This commit is contained in:
parent
296b11503e
commit
b17a3bc4e8
3 changed files with 76 additions and 115 deletions
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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.accounts;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles changes to account used to sign in to the keyboard.
|
||||||
|
* e.g. account switching/sign-in/sign-out from the keyboard
|
||||||
|
* user toggling the sync preference.
|
||||||
|
*/
|
||||||
|
public class AccountStateChangedListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the current account being used in keyboard is signed out.
|
||||||
|
*
|
||||||
|
* @param oldAccount the account that was signed out of.
|
||||||
|
*/
|
||||||
|
public static void onAccountSignedOut(@NonNull String oldAccount) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user signs-in to the keyboard.
|
||||||
|
* This may be called when the user switches accounts to sign in with a different account.
|
||||||
|
*
|
||||||
|
* @param oldAccount the previous account that was being used for sign-in.
|
||||||
|
* May be null for a fresh sign-in.
|
||||||
|
* @param newAccount the account being used for sign-in.
|
||||||
|
*/
|
||||||
|
public static void onAccountSignedIn(@Nullable String oldAccount, @NonNull String newAccount) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the user toggles the sync preference.
|
||||||
|
*
|
||||||
|
* @param account the account being used for sync.
|
||||||
|
* @param syncEnabled indicates whether sync has been enabled or not.
|
||||||
|
*/
|
||||||
|
public static void onSyncPreferenceChanged(@Nullable String account, boolean syncEnabled) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces an immediate sync to happen.
|
||||||
|
* This should only be used for debugging purposes.
|
||||||
|
*
|
||||||
|
* @param account the account to use for sync.
|
||||||
|
*/
|
||||||
|
public static void forceSync(@Nullable String account) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,9 +19,7 @@ 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_ACCOUNT_NAME;
|
||||||
import static com.android.inputmethod.latin.settings.LocalSettingsConstants.PREF_ENABLE_CLOUD_SYNC;
|
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;
|
||||||
|
@ -37,6 +35,7 @@ import com.android.inputmethod.annotations.UsedForTesting;
|
||||||
import com.android.inputmethod.latin.R;
|
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.accounts.AccountStateChangedListener;
|
||||||
import com.android.inputmethod.latin.define.ProductionFlags;
|
import com.android.inputmethod.latin.define.ProductionFlags;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -52,7 +51,6 @@ import javax.annotation.Nullable;
|
||||||
public final class AccountsSettingsFragment extends SubScreenFragment {
|
public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
private static final String PREF_SYNC_NOW = "pref_beanstalk";
|
private static final String PREF_SYNC_NOW = "pref_beanstalk";
|
||||||
|
|
||||||
@UsedForTesting static final String AUTHORITY = "com.android.inputmethod.latin.provider";
|
|
||||||
static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
|
static final String PREF_ACCCOUNT_SWITCHER = "account_switcher";
|
||||||
|
|
||||||
private final DialogInterface.OnClickListener mAccountChangedListener =
|
private final DialogInterface.OnClickListener mAccountChangedListener =
|
||||||
|
@ -111,7 +109,8 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
prefs.getString(PREF_ACCOUNT_NAME, null));
|
prefs.getString(PREF_ACCOUNT_NAME, null));
|
||||||
} else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) {
|
} else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) {
|
||||||
final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
|
final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false);
|
||||||
updateSyncPolicy(syncEnabled, getSignedInAccountName());
|
AccountStateChangedListener.onSyncPreferenceChanged(
|
||||||
|
getSignedInAccountName(), syncEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,36 +176,6 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
syncPreference.setSummary(R.string.cloud_sync_summary_disabled_signed_out);
|
syncPreference.setSummary(R.string.cloud_sync_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.
|
|
||||||
*
|
|
||||||
* @param enabled indicates whether the sync preference is enabled or not.
|
|
||||||
* @param accountToUse indicaes the account to be used for sync, or null if the user
|
|
||||||
* is not logged in.
|
|
||||||
*/
|
|
||||||
@UsedForTesting
|
|
||||||
void updateSyncPolicy(boolean enabled, @Nullable String accountToUse) {
|
|
||||||
if (!ProductionFlags.ENABLE_PERSONAL_DICTIONARY_SYNC) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (accountToUse != null) {
|
|
||||||
final int syncable = enabled ? 1 : 0;
|
|
||||||
ContentResolver.setIsSyncable(
|
|
||||||
new Account(accountToUse, LoginAccountUtils.ACCOUNT_TYPE),
|
|
||||||
AUTHORITY, syncable);
|
|
||||||
// TODO: Also add a periodic sync here.
|
|
||||||
// See ContentResolver.addPeriodicSync
|
|
||||||
} else {
|
|
||||||
// Without an account, we cannot really set the sync to off.
|
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
String getSignedInAccountName() {
|
String getSignedInAccountName() {
|
||||||
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null);
|
||||||
|
@ -261,22 +230,20 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
class AccountChangedListener 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 String oldAccount = getSignedInAccountName();
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case DialogInterface.BUTTON_POSITIVE: // Signed in
|
case DialogInterface.BUTTON_POSITIVE: // Signed in
|
||||||
final ListView lv = ((AlertDialog)dialog).getListView();
|
final ListView lv = ((AlertDialog)dialog).getListView();
|
||||||
final Object selectedItem = lv.getItemAtPosition(lv.getCheckedItemPosition());
|
final String newAccount =
|
||||||
|
(String) lv.getItemAtPosition(lv.getCheckedItemPosition());
|
||||||
getSharedPreferences()
|
getSharedPreferences()
|
||||||
.edit()
|
.edit()
|
||||||
.putString(PREF_ACCOUNT_NAME, (String) selectedItem)
|
.putString(PREF_ACCOUNT_NAME, newAccount)
|
||||||
.apply();
|
.apply();
|
||||||
// Attempt starting sync for the new account if sync was
|
AccountStateChangedListener.onAccountSignedIn(oldAccount, newAccount);
|
||||||
// previously enabled.
|
|
||||||
// If not, stop it.
|
|
||||||
updateSyncPolicy(isSyncEnabled(), getSignedInAccountName());
|
|
||||||
break;
|
break;
|
||||||
case DialogInterface.BUTTON_NEUTRAL: // Signed out
|
case DialogInterface.BUTTON_NEUTRAL: // Signed out
|
||||||
// Stop sync for the account that's being signed out of.
|
AccountStateChangedListener.onAccountSignedOut(oldAccount);
|
||||||
updateSyncPolicy(false, getSignedInAccountName());
|
|
||||||
getSharedPreferences()
|
getSharedPreferences()
|
||||||
.edit()
|
.edit()
|
||||||
.remove(PREF_ACCOUNT_NAME)
|
.remove(PREF_ACCOUNT_NAME)
|
||||||
|
@ -292,9 +259,7 @@ public final class AccountsSettingsFragment extends SubScreenFragment {
|
||||||
class SyncNowListener implements Preference.OnPreferenceClickListener {
|
class SyncNowListener implements Preference.OnPreferenceClickListener {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(final Preference preference) {
|
public boolean onPreferenceClick(final Preference preference) {
|
||||||
ContentResolver.requestSync(
|
AccountStateChangedListener.forceSync(getSignedInAccountName());
|
||||||
new Account(getSignedInAccountName(), LoginAccountUtils.ACCOUNT_TYPE),
|
|
||||||
AUTHORITY, Bundle.EMPTY);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,14 @@
|
||||||
|
|
||||||
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.accounts.LoginAccountUtils;
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -39,9 +32,6 @@ 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 String TEST_ACCOUNT_NAME = "AccountsSettingsFragmentTests";
|
|
||||||
private static final Account TEST_ACCOUNT =
|
|
||||||
new Account(TEST_ACCOUNT_NAME, LoginAccountUtils.ACCOUNT_TYPE);
|
|
||||||
|
|
||||||
private AlertDialog mDialog;
|
private AlertDialog mDialog;
|
||||||
|
|
||||||
|
@ -57,13 +47,6 @@ 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;
|
||||||
|
@ -146,57 +129,4 @@ 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_NAME);
|
|
||||||
|
|
||||||
// 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_NAME);
|
|
||||||
|
|
||||||
// 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_NAME);
|
|
||||||
|
|
||||||
// Should be syncable now.
|
|
||||||
assertEquals(1, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
|
||||||
|
|
||||||
fragment.updateSyncPolicy(false, TEST_ACCOUNT_NAME);
|
|
||||||
|
|
||||||
// Should not be syncable now.
|
|
||||||
assertEquals(0, ContentResolver.getIsSyncable(TEST_ACCOUNT, AUTHORITY));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue