Loading src/com/android/contacts/activities/PeopleActivity.java +2 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,8 @@ public class PeopleActivity extends ContactsDrawerActivity implements // the syncs is in progress. if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account: syncableAccounts) { if (SyncUtil.isSyncStatusPendingOrActive(account)) { if (SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { swipeRefreshLayout.setRefreshing(true); return; } Loading src/com/android/contacts/list/DefaultContactBrowseListFragment.java +42 −3 Original line number Diff line number Diff line Loading @@ -88,7 +88,9 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment private void bindListHeader(int numberOfContacts) { final ContactListFilter filter = getFilter(); if (!isSearchMode() && numberOfContacts <= 0) { // If the phone has at least one Google account whose sync status is unsyncable or pending // or active, we have to make mAccountFilterContainer visible. if (!isSearchMode() && numberOfContacts <= 0 && shouldShowEmptyView(filter)) { if (filter != null && filter.isContactsFilterType()) { makeViewVisible(mEmptyHomeView); } else { Loading @@ -111,6 +113,38 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment } } /** * If at least one Google account is unsyncable or its sync status is pending or active, we * should not show empty view even if the number of contacts is 0. We should show sync status * with empty list instead. */ private boolean shouldShowEmptyView(ContactListFilter filter) { if (filter == null) { return true; } // TODO(samchen) : Check ContactListFilter.FILTER_TYPE_CUSTOM if (ContactListFilter.FILTER_TYPE_DEFAULT == filter.filterType || ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS == filter.filterType) { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(getContext()) .getAccounts(/* contactsWritableOnly */ true); final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts); if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account : syncableAccounts) { if (SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { return false; } } } } else if (ContactListFilter.FILTER_TYPE_ACCOUNT == filter.filterType) { final Account account = new Account(filter.accountName, filter.accountType); return !(SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)); } return true; } // Show the view that's specified by id and hide the other two. private void makeViewVisible(View view) { mEmptyAccountView.setVisibility(view == mEmptyAccountView ? View.VISIBLE : View.GONE); Loading Loading @@ -251,7 +285,10 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment (int) getResources().getDimension(R.dimen.pull_to_refresh_distance)); } /** Request sync for Google accounts(not include Google+ accounts) in filter. */ /** * Request sync for the Google accounts (not include Google+ accounts) specified by the given * filter. */ private void syncContacts(ContactListFilter filter) { if (filter == null) { return; Loading @@ -265,7 +302,9 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts); if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account : syncableAccounts) { if (!SyncUtil.isSyncStatusPendingOrActive(account)) { // We can prioritize Contacts sync if sync is not initialized yet. if (!SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle); } } Loading src/com/android/contacts/util/SyncUtil.java +17 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ import android.accounts.Account; import android.content.ContentResolver; import android.provider.ContactsContract; import com.android.contacts.common.model.account.GoogleAccountType; import java.util.List; /** * Utilities related to sync. */ Loading @@ -29,7 +33,20 @@ public final class SyncUtil { } public static final boolean isSyncStatusPendingOrActive(Account account) { if (account == null) { return false; } return ContentResolver.isSyncPending(account, ContactsContract.AUTHORITY) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY); } /** * Returns true if the given Google account is not syncable. */ public static final boolean isUnsyncableGoogleAccount(Account account) { if (account == null || !GoogleAccountType.ACCOUNT_TYPE.equals(account.type)) { return false; } return ContentResolver.getIsSyncable(account, ContactsContract.AUTHORITY) <= 0; } } tests/src/com/android/contacts/util/SyncUtilTests.java 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.contacts.util; import android.accounts.Account; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import java.util.ArrayList; import java.util.List; /** * Tests for SyncUtil. */ @SmallTest public class SyncUtilTests extends AndroidTestCase { private static final String TAG = "SyncUtilTests"; private static final String GOOGLE_TYPE = "com.google"; private static final String NOT_GOOGLE_TYPE = "com.abc"; private static final String ACCOUNT_NAME = "ACCOUNT_NAME"; private final Account mGoogleAccount; private final Account mOtherAccount; public SyncUtilTests() { mGoogleAccount = new Account(ACCOUNT_NAME, GOOGLE_TYPE); mOtherAccount = new Account(ACCOUNT_NAME, NOT_GOOGLE_TYPE); } public void testIsUnsyncableGoogleAccount() throws Exception { // The account names of mGoogleAccount and mOtherAccount are not valid, so both accounts // are not syncable. assertTrue(SyncUtil.isUnsyncableGoogleAccount(mGoogleAccount)); assertFalse(SyncUtil.isUnsyncableGoogleAccount(mOtherAccount)); assertFalse(SyncUtil.isUnsyncableGoogleAccount(null)); } } Loading
src/com/android/contacts/activities/PeopleActivity.java +2 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,8 @@ public class PeopleActivity extends ContactsDrawerActivity implements // the syncs is in progress. if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account: syncableAccounts) { if (SyncUtil.isSyncStatusPendingOrActive(account)) { if (SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { swipeRefreshLayout.setRefreshing(true); return; } Loading
src/com/android/contacts/list/DefaultContactBrowseListFragment.java +42 −3 Original line number Diff line number Diff line Loading @@ -88,7 +88,9 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment private void bindListHeader(int numberOfContacts) { final ContactListFilter filter = getFilter(); if (!isSearchMode() && numberOfContacts <= 0) { // If the phone has at least one Google account whose sync status is unsyncable or pending // or active, we have to make mAccountFilterContainer visible. if (!isSearchMode() && numberOfContacts <= 0 && shouldShowEmptyView(filter)) { if (filter != null && filter.isContactsFilterType()) { makeViewVisible(mEmptyHomeView); } else { Loading @@ -111,6 +113,38 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment } } /** * If at least one Google account is unsyncable or its sync status is pending or active, we * should not show empty view even if the number of contacts is 0. We should show sync status * with empty list instead. */ private boolean shouldShowEmptyView(ContactListFilter filter) { if (filter == null) { return true; } // TODO(samchen) : Check ContactListFilter.FILTER_TYPE_CUSTOM if (ContactListFilter.FILTER_TYPE_DEFAULT == filter.filterType || ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS == filter.filterType) { final List<AccountWithDataSet> accounts = AccountTypeManager.getInstance(getContext()) .getAccounts(/* contactsWritableOnly */ true); final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts); if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account : syncableAccounts) { if (SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { return false; } } } } else if (ContactListFilter.FILTER_TYPE_ACCOUNT == filter.filterType) { final Account account = new Account(filter.accountName, filter.accountType); return !(SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)); } return true; } // Show the view that's specified by id and hide the other two. private void makeViewVisible(View view) { mEmptyAccountView.setVisibility(view == mEmptyAccountView ? View.VISIBLE : View.GONE); Loading Loading @@ -251,7 +285,10 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment (int) getResources().getDimension(R.dimen.pull_to_refresh_distance)); } /** Request sync for Google accounts(not include Google+ accounts) in filter. */ /** * Request sync for the Google accounts (not include Google+ accounts) specified by the given * filter. */ private void syncContacts(ContactListFilter filter) { if (filter == null) { return; Loading @@ -265,7 +302,9 @@ public class DefaultContactBrowseListFragment extends ContactBrowseListFragment final List<Account> syncableAccounts = filter.getSyncableAccounts(accounts); if (syncableAccounts != null && syncableAccounts.size() > 0) { for (Account account : syncableAccounts) { if (!SyncUtil.isSyncStatusPendingOrActive(account)) { // We can prioritize Contacts sync if sync is not initialized yet. if (!SyncUtil.isSyncStatusPendingOrActive(account) || SyncUtil.isUnsyncableGoogleAccount(account)) { ContentResolver.requestSync(account, ContactsContract.AUTHORITY, bundle); } } Loading
src/com/android/contacts/util/SyncUtil.java +17 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ import android.accounts.Account; import android.content.ContentResolver; import android.provider.ContactsContract; import com.android.contacts.common.model.account.GoogleAccountType; import java.util.List; /** * Utilities related to sync. */ Loading @@ -29,7 +33,20 @@ public final class SyncUtil { } public static final boolean isSyncStatusPendingOrActive(Account account) { if (account == null) { return false; } return ContentResolver.isSyncPending(account, ContactsContract.AUTHORITY) || ContentResolver.isSyncActive(account, ContactsContract.AUTHORITY); } /** * Returns true if the given Google account is not syncable. */ public static final boolean isUnsyncableGoogleAccount(Account account) { if (account == null || !GoogleAccountType.ACCOUNT_TYPE.equals(account.type)) { return false; } return ContentResolver.getIsSyncable(account, ContactsContract.AUTHORITY) <= 0; } }
tests/src/com/android/contacts/util/SyncUtilTests.java 0 → 100644 +51 −0 Original line number Diff line number Diff line /* * Copyright (C) 2016 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.contacts.util; import android.accounts.Account; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import java.util.ArrayList; import java.util.List; /** * Tests for SyncUtil. */ @SmallTest public class SyncUtilTests extends AndroidTestCase { private static final String TAG = "SyncUtilTests"; private static final String GOOGLE_TYPE = "com.google"; private static final String NOT_GOOGLE_TYPE = "com.abc"; private static final String ACCOUNT_NAME = "ACCOUNT_NAME"; private final Account mGoogleAccount; private final Account mOtherAccount; public SyncUtilTests() { mGoogleAccount = new Account(ACCOUNT_NAME, GOOGLE_TYPE); mOtherAccount = new Account(ACCOUNT_NAME, NOT_GOOGLE_TYPE); } public void testIsUnsyncableGoogleAccount() throws Exception { // The account names of mGoogleAccount and mOtherAccount are not valid, so both accounts // are not syncable. assertTrue(SyncUtil.isUnsyncableGoogleAccount(mGoogleAccount)); assertFalse(SyncUtil.isUnsyncableGoogleAccount(mOtherAccount)); assertFalse(SyncUtil.isUnsyncableGoogleAccount(null)); } }