summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcus Hagerott <mhagerott@google.com>2020-06-10 10:18:42 -0700
committerMarcus Hagerott <mhagerott@google.com>2020-06-10 12:39:45 -0700
commitc23eb65efc13c87aa76cf2a514232dbf5790a4d5 (patch)
tree2c2551d7cdcae41b316fe81f927c62075729bd42 /src
parent85cf6e6edafd9d56795f1ed6400b97be8920ab21 (diff)
downloadContacts-c23eb65efc13c87aa76cf2a514232dbf5790a4d5.tar.gz
Use framework API to get local contacts account
Test: built the app and manually verified that the local account is available when no google account is present but is hidden when a google account is added and it has not contacts. Bug: 155985097 Change-Id: I7d15c10ce154aabf6d6ced06459c49ac4a7e5053
Diffstat (limited to 'src')
-rw-r--r--src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java3
-rw-r--r--src/com/android/contacts/editor/ContactEditorUtils.java4
-rw-r--r--src/com/android/contacts/model/AccountTypeManager.java35
-rw-r--r--src/com/android/contacts/model/Cp2DeviceLocalAccountLocator.java139
-rw-r--r--src/com/android/contacts/model/DeviceLocalAccountLocator.java84
-rw-r--r--src/com/android/contacts/model/account/AccountWithDataSet.java10
-rw-r--r--src/com/android/contacts/preference/ContactsPreferences.java9
7 files changed, 40 insertions, 244 deletions
diff --git a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
index dea134b5f..8f0509bab 100644
--- a/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorAccountsChangedActivity.java
@@ -141,7 +141,8 @@ public class ContactEditorAccountsChangedActivity extends Activity
mAccountListAdapter = new AccountsListAdapter(this, accounts);
accountListView.setAdapter(mAccountListAdapter);
accountListView.setOnItemClickListener(mAccountListItemClickListener);
- } else if (numAccounts == 1 && !accounts.get(0).getAccount().isNullAccount()) {
+ } else if (numAccounts == 1
+ && !accounts.get(0).getAccount().equals(AccountWithDataSet.getLocalAccount(this))) {
// If the user has 1 writable account we will just show the user a message with 2
// possible action buttons.
view = View.inflate(this,
diff --git a/src/com/android/contacts/editor/ContactEditorUtils.java b/src/com/android/contacts/editor/ContactEditorUtils.java
index 517c2c70b..0e9b5c90b 100644
--- a/src/com/android/contacts/editor/ContactEditorUtils.java
+++ b/src/com/android/contacts/editor/ContactEditorUtils.java
@@ -38,9 +38,11 @@ import java.util.List;
public class ContactEditorUtils {
private static final String TAG = "ContactEditorUtils";
+ private final Context mContext;
private final ContactsPreferences mContactsPrefs;
private ContactEditorUtils(Context context) {
+ mContext = context;
mContactsPrefs = new ContactsPreferences(context);
}
@@ -122,7 +124,7 @@ public class ContactEditorUtils {
public void maybeUpdateDefaultAccount(List<AccountWithDataSet> currentWritableAccounts) {
if (currentWritableAccounts.size() == 1) {
final AccountWithDataSet onlyAccount = currentWritableAccounts.get(0);
- if (!onlyAccount.isNullAccount()
+ if (!onlyAccount.equals(AccountWithDataSet.getLocalAccount(mContext))
&& !onlyAccount.equals(mContactsPrefs.getDefaultAccount())) {
mContactsPrefs.setDefaultAccount(onlyAccount);
}
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 196e67ff9..5a14b09cf 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -27,17 +27,14 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SyncStatusObserver;
import android.content.pm.PackageManager;
-import android.database.ContentObserver;
-import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
-import android.provider.ContactsContract;
-import androidx.core.content.ContextCompat;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.util.Log;
-import com.android.contacts.Experiments;
+import androidx.core.content.ContextCompat;
+import androidx.localbroadcastmanager.content.LocalBroadcastManager;
+
import com.android.contacts.R;
import com.android.contacts.list.ContactListFilterController;
import com.android.contacts.model.account.AccountInfo;
@@ -49,10 +46,10 @@ import com.android.contacts.model.account.FallbackAccountType;
import com.android.contacts.model.account.GoogleAccountType;
import com.android.contacts.model.dataitem.DataKind;
import com.android.contacts.util.concurrent.ContactsExecutors;
-import com.android.contactsbind.experiments.Flags;
-import com.google.common.base.Preconditions;
+
import com.google.common.base.Function;
import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.util.concurrent.FutureCallback;
@@ -376,7 +373,7 @@ class AccountTypeManagerImpl extends AccountTypeManager
*/
public AccountTypeManagerImpl(Context context) {
mContext = context;
- mLocalAccountLocator = DeviceLocalAccountLocator.create(context);
+ mLocalAccountLocator = new DeviceLocalAccountLocator(context, AccountManager.get(context));
mTypeProvider = new AccountTypeProvider(context);
mFallbackAccountType = new FallbackAccountType(context);
@@ -405,26 +402,6 @@ class AccountTypeManagerImpl extends AccountTypeManager
ContentResolver.addStatusChangeListener(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, this);
- // Observe changes to RAW_CONTACTS so that we will update the list of "Device" accounts
- // if a new device contact is added or removed.
- mContext.getContentResolver().registerContentObserver(
- ContactsContract.RawContacts.CONTENT_URI, /* notifyDescendents */ true,
- new ContentObserver(mMainThreadHandler) {
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- reloadLocalAccounts();
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- reloadLocalAccounts();
- }
- });
loadAccountTypes();
}
diff --git a/src/com/android/contacts/model/Cp2DeviceLocalAccountLocator.java b/src/com/android/contacts/model/Cp2DeviceLocalAccountLocator.java
deleted file mode 100644
index 32912dc11..000000000
--- a/src/com/android/contacts/model/Cp2DeviceLocalAccountLocator.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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.model;
-
-import android.accounts.AccountManager;
-import android.content.ContentResolver;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.contacts.model.account.AccountWithDataSet;
-import com.android.contacts.util.DeviceLocalAccountTypeFactory;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Attempts to create accounts for "Device" contacts by querying
- * CP2 for records with {@link android.provider.ContactsContract.RawContacts#ACCOUNT_TYPE} columns
- * that do not exist for any account returned by {@link AccountManager#getAccounts()}
- *
- * This class should be used from a background thread since it does DB queries
- */
-public class Cp2DeviceLocalAccountLocator extends DeviceLocalAccountLocator {
-
- // Note this class is assuming ACCOUNT_NAME and ACCOUNT_TYPE have same values in
- // RawContacts, Groups, and Settings. This assumption simplifies the code somewhat and it
- // is true right now and unlikely to ever change.
- @VisibleForTesting
- static String[] PROJECTION = new String[] {
- ContactsContract.RawContacts.ACCOUNT_NAME, ContactsContract.RawContacts.ACCOUNT_TYPE,
- ContactsContract.RawContacts.DATA_SET
- };
-
- private static final int COL_NAME = 0;
- private static final int COL_TYPE = 1;
- private static final int COL_DATA_SET = 2;
-
- private final ContentResolver mResolver;
- private final DeviceLocalAccountTypeFactory mAccountTypeFactory;
-
- private final String mSelection;
- private final String[] mSelectionArgs;
-
- public Cp2DeviceLocalAccountLocator(ContentResolver contentResolver,
- DeviceLocalAccountTypeFactory factory,
- Set<String> knownAccountTypes) {
- mResolver = contentResolver;
- mAccountTypeFactory = factory;
-
- mSelection = getSelection(knownAccountTypes);
- mSelectionArgs = getSelectionArgs(knownAccountTypes);
- }
-
- @Override
- public List<AccountWithDataSet> getDeviceLocalAccounts() {
-
- final Set<AccountWithDataSet> localAccounts = new HashSet<>();
-
- // Many device accounts have default groups associated with them.
- addAccountsFromQuery(ContactsContract.Groups.CONTENT_URI, localAccounts);
- addAccountsFromQuery(ContactsContract.Settings.CONTENT_URI, localAccounts);
- addAccountsFromQuery(ContactsContract.RawContacts.CONTENT_URI, localAccounts);
-
- return new ArrayList<>(localAccounts);
- }
-
- private void addAccountsFromQuery(Uri uri, Set<AccountWithDataSet> accounts) {
- final Cursor cursor = mResolver.query(uri, PROJECTION, mSelection, mSelectionArgs, null);
-
- if (cursor == null) return;
-
- try {
- addAccountsFromCursor(cursor, accounts);
- } finally {
- cursor.close();
- }
- }
-
- private void addAccountsFromCursor(Cursor cursor, Set<AccountWithDataSet> accounts) {
- while (cursor.moveToNext()) {
- final String name = cursor.getString(COL_NAME);
- final String type = cursor.getString(COL_TYPE);
- final String dataSet = cursor.getString(COL_DATA_SET);
-
- if (DeviceLocalAccountTypeFactory.Util.isLocalAccountType(
- mAccountTypeFactory, type)) {
- accounts.add(new AccountWithDataSet(name, type, dataSet));
- }
- }
- }
-
- @VisibleForTesting
- public String getSelection() {
- return mSelection;
- }
-
- @VisibleForTesting
- public String[] getSelectionArgs() {
- return mSelectionArgs;
- }
-
- private static String getSelection(Set<String> knownAccountTypes) {
- final StringBuilder sb = new StringBuilder()
- .append(ContactsContract.RawContacts.ACCOUNT_TYPE).append(" IS NULL");
- if (knownAccountTypes.isEmpty()) {
- return sb.toString();
- }
- sb.append(" OR ").append(ContactsContract.RawContacts.ACCOUNT_TYPE).append(" NOT IN (");
- for (String ignored : knownAccountTypes) {
- sb.append("?,");
- }
- // Remove trailing ','
- sb.deleteCharAt(sb.length() - 1).append(')');
- return sb.toString();
- }
-
- private static String[] getSelectionArgs(Set<String> knownAccountTypes) {
- if (knownAccountTypes.isEmpty()) return null;
-
- return knownAccountTypes.toArray(new String[knownAccountTypes.size()]);
- }
-}
diff --git a/src/com/android/contacts/model/DeviceLocalAccountLocator.java b/src/com/android/contacts/model/DeviceLocalAccountLocator.java
index 2b987d3e7..e8a2ba0ff 100644
--- a/src/com/android/contacts/model/DeviceLocalAccountLocator.java
+++ b/src/com/android/contacts/model/DeviceLocalAccountLocator.java
@@ -18,92 +18,40 @@ package com.android.contacts.model;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.Context;
-import android.database.Cursor;
import android.provider.ContactsContract;
-import com.android.contacts.Experiments;
import com.android.contacts.model.account.AccountWithDataSet;
import com.android.contacts.model.account.GoogleAccountType;
-import com.android.contactsbind.ObjectFactory;
-import com.android.contactsbind.experiments.Flags;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
/**
* Attempts to detect accounts for device contacts
*/
-public abstract class DeviceLocalAccountLocator {
+public final class DeviceLocalAccountLocator {
- /**
- * Returns a list of device local accounts
- */
- public abstract List<AccountWithDataSet> getDeviceLocalAccounts();
-
- // This works on Nexus and AOSP because the local device account is the null account but most
- // OEMs have a special account name and type for their device account.
- public static final DeviceLocalAccountLocator NULL_ONLY = new DeviceLocalAccountLocator() {
- @Override
- public List<AccountWithDataSet> getDeviceLocalAccounts() {
- return Collections.singletonList(AccountWithDataSet.getNullAccount());
- }
- };
+ private final Context mContext;
+ private final AccountManager mAccountManager;
+ private final List<AccountWithDataSet> mLocalAccount;
- public static DeviceLocalAccountLocator create(Context context,
- Set<String> knownAccountTypes) {
- if (Flags.getInstance().getBoolean(Experiments.CP2_DEVICE_ACCOUNT_DETECTION_ENABLED)) {
- return new Cp2DeviceLocalAccountLocator(context.getContentResolver(),
- ObjectFactory.getDeviceLocalAccountTypeFactory(context), knownAccountTypes);
- }
- return NULL_ONLY;
- }
-
- public static DeviceLocalAccountLocator create(Context context) {
- final AccountManager accountManager =
- (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
- final Set<String> knownTypes = new HashSet<>();
- for (Account account : accountManager.getAccounts()) {
- knownTypes.add(account.type);
- }
- if (Flags.getInstance().getBoolean(Experiments.CP2_DEVICE_ACCOUNT_DETECTION_ENABLED)) {
- return new Cp2DeviceLocalAccountLocator(context.getContentResolver(),
- ObjectFactory.getDeviceLocalAccountTypeFactory(context), knownTypes);
- } else {
- return new NexusDeviceAccountLocator(context, accountManager);
- }
+ public DeviceLocalAccountLocator(Context context, AccountManager accountManager) {
+ mContext = context;
+ mAccountManager = accountManager;
+ mLocalAccount = Collections.singletonList(AccountWithDataSet.getLocalAccount(context));
}
/**
- * On Nexus the "device" account uses "null" values for the account name and type columns
- *
- * <p>However, the focus sync adapter migrates contacts from this null account to a Google
- * account if one exists. Hence, the device account should be returned only when there is no
- * Google Account added or when there already exists contacts in the null account.
- * </p>
+ * Returns a list of device local accounts
*/
- public static class NexusDeviceAccountLocator extends DeviceLocalAccountLocator {
- private final Context mContext;
- private final AccountManager mAccountManager;
-
+ public List<AccountWithDataSet> getDeviceLocalAccounts() {
+ @SuppressWarnings("MissingPermission") final Account[] accounts = mAccountManager
+ .getAccountsByType(GoogleAccountType.ACCOUNT_TYPE);
- public NexusDeviceAccountLocator(Context context, AccountManager accountManager) {
- mContext = context;
- mAccountManager = accountManager;
- }
-
- @Override
- public List<AccountWithDataSet> getDeviceLocalAccounts() {
- @SuppressWarnings("MissingPermission")
- final Account[] accounts = mAccountManager
- .getAccountsByType(GoogleAccountType.ACCOUNT_TYPE);
-
- if (accounts.length > 0 && !AccountWithDataSet.getNullAccount().hasData(mContext)) {
- return Collections.emptyList();
- } else {
- return Collections.singletonList(AccountWithDataSet.getNullAccount());
- }
+ if (accounts.length > 0 && !mLocalAccount.get(0).hasData(mContext)) {
+ return Collections.emptyList();
+ } else {
+ return mLocalAccount;
}
}
}
diff --git a/src/com/android/contacts/model/account/AccountWithDataSet.java b/src/com/android/contacts/model/account/AccountWithDataSet.java
index a16313981..96717624e 100644
--- a/src/com/android/contacts/model/account/AccountWithDataSet.java
+++ b/src/com/android/contacts/model/account/AccountWithDataSet.java
@@ -28,8 +28,6 @@ import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.preference.ContactsPreferences;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
@@ -88,6 +86,14 @@ public class AccountWithDataSet implements Parcelable {
return new AccountWithDataSet(null, null, null);
}
+ public static AccountWithDataSet getLocalAccount(Context context) {
+ return new AccountWithDataSet(
+ RawContacts.getLocalAccountName(context),
+ RawContacts.getLocalAccountType(context),
+ null
+ );
+ }
+
public Account getAccountOrNull() {
if (name != null && type != null) {
return new Account(name, type);
diff --git a/src/com/android/contacts/preference/ContactsPreferences.java b/src/com/android/contacts/preference/ContactsPreferences.java
index 85da89144..e92c35646 100644
--- a/src/com/android/contacts/preference/ContactsPreferences.java
+++ b/src/com/android/contacts/preference/ContactsPreferences.java
@@ -16,7 +16,6 @@
package com.android.contacts.preference;
-import android.app.backup.BackupAgent;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
@@ -27,9 +26,10 @@ import android.os.Looper;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
+
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
-import android.text.TextUtils;
import com.android.contacts.R;
import com.android.contacts.model.account.AccountWithDataSet;
@@ -256,15 +256,16 @@ public class ContactsPreferences implements OnSharedPreferenceChangeListener {
currentWritableAccounts) {
final AccountWithDataSet defaultAccount = getDefaultAccount();
+ AccountWithDataSet localAccount = AccountWithDataSet.getLocalAccount(mContext);
// This shouldn't occur anymore because a "device" account is added in the case that there
// are no other accounts but if there are no writable accounts then the default has been
// initialized if it is "device"
if (currentWritableAccounts.isEmpty()) {
- return defaultAccount == null || !defaultAccount.isNullAccount();
+ return defaultAccount == null || !defaultAccount.equals(localAccount);
}
if (currentWritableAccounts.size() == 1
- && !currentWritableAccounts.get(0).isNullAccount()) {
+ && !currentWritableAccounts.get(0).equals(localAccount)) {
return false;
}