Loading res/xml/account_type_settings.xml +2 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ android:key="remove_account" android:layout="@layout/remove_account_button" android:order="1000" android:selectable="false"/> android:selectable="false" settings:allowDividerAbove="true"/> </PreferenceScreen> src/com/android/settings/accounts/AccountSyncPreferenceController.java +64 −1 Original line number Diff line number Diff line Loading @@ -19,25 +19,32 @@ package com.android.settings.accounts; import static android.content.Intent.EXTRA_USER; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.os.Bundle; import android.os.UserHandle; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.accounts.AuthenticatorHelper; import com.android.settingslib.core.AbstractPreferenceController; public class AccountSyncPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin { implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener { private static final String TAG = "AccountSyncController"; private static final String KEY_ACCOUNT_SYNC = "account_sync"; private Account mAccount; private UserHandle mUserHandle; private AuthenticatorHelper mAuthenticatorHelper; private Preference mPreference; public AccountSyncPreferenceController(Context context) { super(context); Loading Loading @@ -67,8 +74,64 @@ public class AccountSyncPreferenceController extends AbstractPreferenceControlle return KEY_ACCOUNT_SYNC; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); } @Override public void updateState(Preference preference) { updateSummary(preference); } @Override public void onAccountsUpdate(UserHandle userHandle) { updateSummary(mPreference); } public void init(Account account, UserHandle userHandle) { mAccount = account; mUserHandle = userHandle; mAuthenticatorHelper = new AuthenticatorHelper(mContext, mUserHandle, this); } @VisibleForTesting void updateSummary(Preference preference) { if (mAccount == null) { return; } final int userId = mUserHandle.getIdentifier(); final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId); int total = 0; int enabled = 0; if (syncAdapters != null) { for (int i = 0, n = syncAdapters.length; i < n; i++) { final SyncAdapterType sa = syncAdapters[i]; if (!sa.accountType.equals(mAccount.type) || !sa.isUserVisible()) { continue; } final int syncState = ContentResolver.getIsSyncableAsUser(mAccount, sa.authority, userId); if (syncState > 0) { total++; final boolean syncEnabled = ContentResolver.getSyncAutomaticallyAsUser( mAccount, sa.authority, userId); final boolean oneTimeSyncMode = !ContentResolver.getMasterSyncAutomaticallyAsUser(userId); if (oneTimeSyncMode || syncEnabled) { enabled++; } } } } if (enabled == 0) { preference.setSummary(R.string.account_sync_summary_all_off); } else if (enabled == total) { preference.setSummary(R.string.account_sync_summary_all_on); } else { preference.setSummary( mContext.getString(R.string.account_sync_summary_some_on, enabled, total)); } } } src/com/android/settings/applications/LayoutPreference.java +15 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.applications; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.VisibleForTesting; import android.support.v4.content.res.TypedArrayUtils; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; import android.util.AttributeSet; Loading @@ -33,19 +34,30 @@ import com.android.settings.Utils; public class LayoutPreference extends Preference { private final View.OnClickListener mClickListener = v -> performClick(v); private boolean mAllowDividerAbove; private boolean mAllowDividerBelow; @VisibleForTesting View mRootView; public LayoutPreference(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray a = context.obtainStyledAttributes( TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference); mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove, R.styleable.Preference_allowDividerAbove, false); mAllowDividerBelow = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerBelow, R.styleable.Preference_allowDividerBelow, false); a.recycle(); a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.Preference, 0, 0); int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout, 0); if (layoutResource == 0) { throw new IllegalArgumentException("LayoutPreference requires a layout to be defined"); } a.recycle(); // Need to create view now so that findViewById can be called immediately. final View view = LayoutInflater.from(getContext()) .inflate(layoutResource, null, false); Loading Loading @@ -78,6 +90,8 @@ public class LayoutPreference extends Preference { final boolean selectable = isSelectable(); holder.itemView.setFocusable(selectable); holder.itemView.setClickable(selectable); holder.setDividerAllowedAbove(mAllowDividerAbove); holder.setDividerAllowedBelow(mAllowDividerBelow); FrameLayout layout = (FrameLayout) holder.itemView; layout.removeAllViews(); Loading tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java +136 −12 Original line number Diff line number Diff line Loading @@ -16,11 +16,17 @@ package com.android.settings.accounts; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.when; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorDescription; import android.content.Context; import android.content.Intent; import android.content.SyncAdapterType; import android.os.UserHandle; import android.support.v7.preference.Preference; Loading @@ -28,29 +34,58 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.testutils.shadow.ShadowAccountManager; import com.android.settings.testutils.shadow.ShadowContentResolver; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public class AccountSyncPreferenceControllerTest { @Mock(answer = RETURNS_DEEP_STUBS) private AccountManager mAccountManager; private Context mContext; private AccountSyncPreferenceController mController; private Preference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); ShadowApplication application = ShadowApplication.getInstance(); application.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager); mContext = application.getApplicationContext(); when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn( new AuthenticatorDescription[0]); when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); mPreference = new Preference(mContext); mPreference.setKey("account_sync"); mController = new AccountSyncPreferenceController(mContext); mController.init(new Account("acct1", "type1"), new UserHandle(3)); } @After public void tearDown() { ShadowContentResolver.reset(); } @Test public void handlePreferenceTreeClick_shouldStartFragment() { final ShadowApplication application = ShadowApplication.getInstance(); final Context context = application.getApplicationContext(); final Preference preference = new Preference(context); preference.setKey("account_sync"); final AccountSyncPreferenceController controller = new AccountSyncPreferenceController(context); controller.init(new Account("acct1", "type1"), mock(UserHandle.class)); controller.handlePreferenceTreeClick(preference); mController.handlePreferenceTreeClick(mPreference); final Intent nextActivity = application.getNextStartedActivity(); final Intent nextActivity = ShadowApplication.getInstance().getNextStartedActivity(); assertThat(nextActivity.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) .isEqualTo(AccountSyncSettings.class.getName()); Loading @@ -58,4 +93,93 @@ public class AccountSyncPreferenceControllerTest { .isEqualTo(R.string.account_sync_title); } @Test public void updateSummary_adapterInvisible_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, false /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_notSameAccountType_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type5" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_notSyncable_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncable("authority", 0); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_syncDisabled_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncAutomatically("authority", false); ShadowContentResolver.setMasterSyncAutomatically(3, true); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_syncEnabled_shouldCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_on)); } @Test public void updateSummary_multipleSyncAdapters_shouldSetSummary() { SyncAdapterType syncAdapterType1 = new SyncAdapterType("authority1" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType2 = new SyncAdapterType("authority2" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType3 = new SyncAdapterType("authority3" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType4 = new SyncAdapterType("authority4" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType1, syncAdapterType2, syncAdapterType3, syncAdapterType4}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncAutomatically("authority4", false); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_some_on, 3, 4)); } } tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settings.testutils.shadow; import android.accounts.Account; import android.content.ContentResolver; import android.content.SyncAdapterType; Loading @@ -28,12 +29,20 @@ import org.robolectric.annotation.Implements; import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; import java.util.HashMap; import java.util.Map; @Implements(ContentResolver.class) public class ShadowContentResolver { private static SyncAdapterType[] sSyncAdapterTypes = new SyncAdapterType[0]; private static Map<String, Integer> sSyncable = new HashMap<>(); private static Map<String, Boolean> sSyncAutomatically = new HashMap<>(); private static Map<Integer, Boolean> sMasterSyncAutomatically = new HashMap<>(); @Implementation public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { return new SyncAdapterType[0]; return sSyncAdapterTypes; } @Implementation Loading @@ -44,4 +53,44 @@ public class ShadowContentResolver { .add(SearchIndexablesContract.NonIndexableKey.COLUMN_KEY_VALUE, ""); return cursor; } @Implementation public static int getIsSyncableAsUser(Account account, String authority, int userId) { return sSyncable.containsKey(authority) ? sSyncable.get(authority) : 1; } @Implementation public static boolean getSyncAutomaticallyAsUser(Account account, String authority, int userId) { return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true; } @Implementation public static boolean getMasterSyncAutomaticallyAsUser(int userId) { return sMasterSyncAutomatically.containsKey(userId) ? sMasterSyncAutomatically.get(userId) : true; } public static void setSyncAdapterTypes(SyncAdapterType[] syncAdapterTypes) { sSyncAdapterTypes = syncAdapterTypes; } public static void setSyncable(String authority, int syncable) { sSyncable.put(authority, syncable); } public static void setSyncAutomatically(String authority, boolean syncAutomatically) { sSyncAutomatically.put(authority, syncAutomatically); } public static void setMasterSyncAutomatically(int userId, boolean syncAutomatically) { sMasterSyncAutomatically.put(userId, syncAutomatically); } public static void reset() { sSyncable.clear(); sSyncAutomatically.clear(); sMasterSyncAutomatically.clear(); sSyncAdapterTypes = new SyncAdapterType[0]; } } Loading
res/xml/account_type_settings.xml +2 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ android:key="remove_account" android:layout="@layout/remove_account_button" android:order="1000" android:selectable="false"/> android:selectable="false" settings:allowDividerAbove="true"/> </PreferenceScreen>
src/com/android/settings/accounts/AccountSyncPreferenceController.java +64 −1 Original line number Diff line number Diff line Loading @@ -19,25 +19,32 @@ package com.android.settings.accounts; import static android.content.Intent.EXTRA_USER; import android.accounts.Account; import android.content.ContentResolver; import android.content.Context; import android.content.SyncAdapterType; import android.os.Bundle; import android.os.UserHandle; import android.support.annotation.VisibleForTesting; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.accounts.AuthenticatorHelper; import com.android.settingslib.core.AbstractPreferenceController; public class AccountSyncPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin { implements PreferenceControllerMixin, AuthenticatorHelper.OnAccountsUpdateListener { private static final String TAG = "AccountSyncController"; private static final String KEY_ACCOUNT_SYNC = "account_sync"; private Account mAccount; private UserHandle mUserHandle; private AuthenticatorHelper mAuthenticatorHelper; private Preference mPreference; public AccountSyncPreferenceController(Context context) { super(context); Loading Loading @@ -67,8 +74,64 @@ public class AccountSyncPreferenceController extends AbstractPreferenceControlle return KEY_ACCOUNT_SYNC; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mPreference = screen.findPreference(getPreferenceKey()); } @Override public void updateState(Preference preference) { updateSummary(preference); } @Override public void onAccountsUpdate(UserHandle userHandle) { updateSummary(mPreference); } public void init(Account account, UserHandle userHandle) { mAccount = account; mUserHandle = userHandle; mAuthenticatorHelper = new AuthenticatorHelper(mContext, mUserHandle, this); } @VisibleForTesting void updateSummary(Preference preference) { if (mAccount == null) { return; } final int userId = mUserHandle.getIdentifier(); final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(userId); int total = 0; int enabled = 0; if (syncAdapters != null) { for (int i = 0, n = syncAdapters.length; i < n; i++) { final SyncAdapterType sa = syncAdapters[i]; if (!sa.accountType.equals(mAccount.type) || !sa.isUserVisible()) { continue; } final int syncState = ContentResolver.getIsSyncableAsUser(mAccount, sa.authority, userId); if (syncState > 0) { total++; final boolean syncEnabled = ContentResolver.getSyncAutomaticallyAsUser( mAccount, sa.authority, userId); final boolean oneTimeSyncMode = !ContentResolver.getMasterSyncAutomaticallyAsUser(userId); if (oneTimeSyncMode || syncEnabled) { enabled++; } } } } if (enabled == 0) { preference.setSummary(R.string.account_sync_summary_all_off); } else if (enabled == total) { preference.setSummary(R.string.account_sync_summary_all_on); } else { preference.setSummary( mContext.getString(R.string.account_sync_summary_some_on, enabled, total)); } } }
src/com/android/settings/applications/LayoutPreference.java +15 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.settings.applications; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.VisibleForTesting; import android.support.v4.content.res.TypedArrayUtils; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceViewHolder; import android.util.AttributeSet; Loading @@ -33,19 +34,30 @@ import com.android.settings.Utils; public class LayoutPreference extends Preference { private final View.OnClickListener mClickListener = v -> performClick(v); private boolean mAllowDividerAbove; private boolean mAllowDividerBelow; @VisibleForTesting View mRootView; public LayoutPreference(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray a = context.obtainStyledAttributes( TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Preference); mAllowDividerAbove = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerAbove, R.styleable.Preference_allowDividerAbove, false); mAllowDividerBelow = TypedArrayUtils.getBoolean(a, R.styleable.Preference_allowDividerBelow, R.styleable.Preference_allowDividerBelow, false); a.recycle(); a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.Preference, 0, 0); int layoutResource = a.getResourceId(com.android.internal.R.styleable.Preference_layout, 0); if (layoutResource == 0) { throw new IllegalArgumentException("LayoutPreference requires a layout to be defined"); } a.recycle(); // Need to create view now so that findViewById can be called immediately. final View view = LayoutInflater.from(getContext()) .inflate(layoutResource, null, false); Loading Loading @@ -78,6 +90,8 @@ public class LayoutPreference extends Preference { final boolean selectable = isSelectable(); holder.itemView.setFocusable(selectable); holder.itemView.setClickable(selectable); holder.setDividerAllowedAbove(mAllowDividerAbove); holder.setDividerAllowedBelow(mAllowDividerBelow); FrameLayout layout = (FrameLayout) holder.itemView; layout.removeAllViews(); Loading
tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java +136 −12 Original line number Diff line number Diff line Loading @@ -16,11 +16,17 @@ package com.android.settings.accounts; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.when; import android.accounts.Account; import android.accounts.AccountManager; import android.accounts.AuthenticatorDescription; import android.content.Context; import android.content.Intent; import android.content.SyncAdapterType; import android.os.UserHandle; import android.support.v7.preference.Preference; Loading @@ -28,29 +34,58 @@ import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.testutils.shadow.ShadowAccountManager; import com.android.settings.testutils.shadow.ShadowContentResolver; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION, shadows = {ShadowAccountManager.class, ShadowContentResolver.class}) public class AccountSyncPreferenceControllerTest { @Mock(answer = RETURNS_DEEP_STUBS) private AccountManager mAccountManager; private Context mContext; private AccountSyncPreferenceController mController; private Preference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); ShadowApplication application = ShadowApplication.getInstance(); application.setSystemService(Context.ACCOUNT_SERVICE, mAccountManager); mContext = application.getApplicationContext(); when(mAccountManager.getAuthenticatorTypesAsUser(anyInt())).thenReturn( new AuthenticatorDescription[0]); when(mAccountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]); mPreference = new Preference(mContext); mPreference.setKey("account_sync"); mController = new AccountSyncPreferenceController(mContext); mController.init(new Account("acct1", "type1"), new UserHandle(3)); } @After public void tearDown() { ShadowContentResolver.reset(); } @Test public void handlePreferenceTreeClick_shouldStartFragment() { final ShadowApplication application = ShadowApplication.getInstance(); final Context context = application.getApplicationContext(); final Preference preference = new Preference(context); preference.setKey("account_sync"); final AccountSyncPreferenceController controller = new AccountSyncPreferenceController(context); controller.init(new Account("acct1", "type1"), mock(UserHandle.class)); controller.handlePreferenceTreeClick(preference); mController.handlePreferenceTreeClick(mPreference); final Intent nextActivity = application.getNextStartedActivity(); final Intent nextActivity = ShadowApplication.getInstance().getNextStartedActivity(); assertThat(nextActivity.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) .isEqualTo(AccountSyncSettings.class.getName()); Loading @@ -58,4 +93,93 @@ public class AccountSyncPreferenceControllerTest { .isEqualTo(R.string.account_sync_title); } @Test public void updateSummary_adapterInvisible_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, false /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_notSameAccountType_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type5" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_notSyncable_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncable("authority", 0); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_syncDisabled_shouldNotCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncAutomatically("authority", false); ShadowContentResolver.setMasterSyncAutomatically(3, true); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_off)); } @Test public void updateSummary_syncEnabled_shouldCount() { SyncAdapterType syncAdapterType = new SyncAdapterType("authority" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_all_on)); } @Test public void updateSummary_multipleSyncAdapters_shouldSetSummary() { SyncAdapterType syncAdapterType1 = new SyncAdapterType("authority1" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType2 = new SyncAdapterType("authority2" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType3 = new SyncAdapterType("authority3" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType syncAdapterType4 = new SyncAdapterType("authority4" /* authority */, "type1" /* accountType */, true /* userVisible */, true /* supportsUploading */); SyncAdapterType[] syncAdapters = {syncAdapterType1, syncAdapterType2, syncAdapterType3, syncAdapterType4}; ShadowContentResolver.setSyncAdapterTypes(syncAdapters); ShadowContentResolver.setSyncAutomatically("authority4", false); mController.updateSummary(mPreference); assertThat(mPreference.getSummary()) .isEqualTo(mContext.getString(R.string.account_sync_summary_some_on, 3, 4)); } }
tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java +50 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.settings.testutils.shadow; import android.accounts.Account; import android.content.ContentResolver; import android.content.SyncAdapterType; Loading @@ -28,12 +29,20 @@ import org.robolectric.annotation.Implements; import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS; import java.util.HashMap; import java.util.Map; @Implements(ContentResolver.class) public class ShadowContentResolver { private static SyncAdapterType[] sSyncAdapterTypes = new SyncAdapterType[0]; private static Map<String, Integer> sSyncable = new HashMap<>(); private static Map<String, Boolean> sSyncAutomatically = new HashMap<>(); private static Map<Integer, Boolean> sMasterSyncAutomatically = new HashMap<>(); @Implementation public static SyncAdapterType[] getSyncAdapterTypesAsUser(int userId) { return new SyncAdapterType[0]; return sSyncAdapterTypes; } @Implementation Loading @@ -44,4 +53,44 @@ public class ShadowContentResolver { .add(SearchIndexablesContract.NonIndexableKey.COLUMN_KEY_VALUE, ""); return cursor; } @Implementation public static int getIsSyncableAsUser(Account account, String authority, int userId) { return sSyncable.containsKey(authority) ? sSyncable.get(authority) : 1; } @Implementation public static boolean getSyncAutomaticallyAsUser(Account account, String authority, int userId) { return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true; } @Implementation public static boolean getMasterSyncAutomaticallyAsUser(int userId) { return sMasterSyncAutomatically.containsKey(userId) ? sMasterSyncAutomatically.get(userId) : true; } public static void setSyncAdapterTypes(SyncAdapterType[] syncAdapterTypes) { sSyncAdapterTypes = syncAdapterTypes; } public static void setSyncable(String authority, int syncable) { sSyncable.put(authority, syncable); } public static void setSyncAutomatically(String authority, boolean syncAutomatically) { sSyncAutomatically.put(authority, syncAutomatically); } public static void setMasterSyncAutomatically(int userId, boolean syncAutomatically) { sMasterSyncAutomatically.put(userId, syncAutomatically); } public static void reset() { sSyncable.clear(); sSyncAutomatically.clear(); sMasterSyncAutomatically.clear(); sSyncAdapterTypes = new SyncAdapterType[0]; } }