Merge commit 'e0c5d80d' into mit
* commit 'e0c5d80d':
Use telephony-common
Change-Id: I56b4a75ac390e7710d3c3a9275a68c5dd6d20c2c
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index f958b12..0678347 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -17,13 +17,13 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="sharedUserLabel" msgid="8024311725474286801">"Apl Inti Android"</string>
- <string name="app_label" msgid="3389954322874982620">"Penyimpanan Kenalan"</string>
- <string name="provider_label" msgid="6012150850819899907">"Kenalan"</string>
- <string name="upgrade_msg" msgid="8640807392794309950">"Meningkatkan versi basis data kenalan."</string>
- <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Peningkatan versi kenalan memerlukan lebih banyak memori."</string>
- <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Meningkatkan versi penyimpanan untuk kenalan"</string>
+ <string name="app_label" msgid="3389954322874982620">"Penyimpanan Kontak"</string>
+ <string name="provider_label" msgid="6012150850819899907">"Kontak"</string>
+ <string name="upgrade_msg" msgid="8640807392794309950">"Meningkatkan versi basis kontak."</string>
+ <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Peningkatan versi kontak memerlukan lebih banyak memori."</string>
+ <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Meningkatkan versi penyimpanan untuk kontak"</string>
<string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"Sentuh untuk menyelesaikan peningkatan versi."</string>
- <string name="default_directory" msgid="93961630309570294">"Kenalan"</string>
+ <string name="default_directory" msgid="93961630309570294">"Kontak"</string>
<string name="local_invisible_directory" msgid="705244318477396120">"Lainnya"</string>
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Akses semua pesan suara"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Mengizinkan apl menyimpan dan mengambil semua pesan suara yang dapat diakses oleh perangkat ini."</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 402b8c1..baaf5ee 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -22,7 +22,7 @@
<string name="upgrade_msg" msgid="8640807392794309950">"正在升级联系人数据库。"</string>
<string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"联系人升级需要更多的存储空间。"</string>
<string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"正在升级存储器以容纳更多联系人"</string>
- <string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"请触摸以完成升级。"</string>
+ <string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"触摸可完成升级。"</string>
<string name="default_directory" msgid="93961630309570294">"联系人"</string>
<string name="local_invisible_directory" msgid="705244318477396120">"其他"</string>
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"访问所有语音邮件"</string>
diff --git a/src/com/android/providers/contacts/AbstractContactsProvider.java b/src/com/android/providers/contacts/AbstractContactsProvider.java
index a33320f..226652e 100644
--- a/src/com/android/providers/contacts/AbstractContactsProvider.java
+++ b/src/com/android/providers/contacts/AbstractContactsProvider.java
@@ -38,9 +38,12 @@
public abstract class AbstractContactsProvider extends ContentProvider
implements SQLiteTransactionListener {
- protected static final String TAG = "ContactsProvider";
+ public static final String TAG = "ContactsProvider";
- protected static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);
+ public static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);
+
+ /** Set true to enable detailed transaction logging. */
+ public static final boolean ENABLE_TRANSACTION_LOG = false; // Don't submit with true.
/**
* Duration in ms to sleep after successfully yielding the lock during a batch operation.
@@ -72,14 +75,32 @@
* created by this provider will automatically retrieve a writable database from this helper
* and initiate a transaction on that database. This should be used to ensure that operations
* across multiple databases are all blocked on a single DB lock (to prevent deadlock cases).
+ *
+ * Hint: It's always {@link ContactsDatabaseHelper}.
+ *
+ * TODO Change the structure to make it obvious that it's actually always set, and is the
+ * {@link ContactsDatabaseHelper}.
*/
private SQLiteOpenHelper mSerializeOnDbHelper;
/**
* The tag corresponding to the database used for serializing transactions.
+ *
+ * Hint: It's always the contacts db helper tag.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
*/
private String mSerializeDbTag;
+ /**
+ * The transaction listener used with {@link #mSerializeOnDbHelper}.
+ *
+ * Hint: It's always {@link ContactsProvider2}.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
+ */
+ private SQLiteTransactionListener mSerializedDbTransactionListener;
+
@Override
public boolean onCreate() {
Context context = getContext();
@@ -94,12 +115,14 @@
/**
* Specifies a database helper (and corresponding tag) to serialize all transactions on.
- * @param serializeOnDbHelper The database helper to use for serializing transactions.
- * @param tag The tag for this database.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
*/
- public void setDbHelperToSerializeOn(SQLiteOpenHelper serializeOnDbHelper, String tag) {
+ public void setDbHelperToSerializeOn(SQLiteOpenHelper serializeOnDbHelper, String tag,
+ SQLiteTransactionListener listener) {
mSerializeOnDbHelper = serializeOnDbHelper;
mSerializeDbTag = tag;
+ mSerializedDbTransactionListener = listener;
}
public ContactsTransaction getCurrentTransaction() {
@@ -227,12 +250,16 @@
* @param callerIsBatch Whether the caller is operating in batch mode.
*/
private ContactsTransaction startTransaction(boolean callerIsBatch) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "startTransaction " + getClass().getSimpleName() +
+ " callerIsBatch=" + callerIsBatch, new RuntimeException("startTransaction"));
+ }
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction == null) {
transaction = new ContactsTransaction(callerIsBatch);
if (mSerializeOnDbHelper != null) {
transaction.startTransactionForDb(mSerializeOnDbHelper.getWritableDatabase(),
- mSerializeDbTag, this);
+ mSerializeDbTag, mSerializedDbTransactionListener);
}
mTransactionHolder.set(transaction);
}
@@ -245,6 +272,10 @@
* @param callerIsBatch Whether the caller is operating in batch mode.
*/
private void endTransaction(boolean callerIsBatch) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "endTransaction " + getClass().getSimpleName() +
+ " callerIsBatch=" + callerIsBatch, new RuntimeException("endTransaction"));
+ }
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction != null && (!transaction.isBatch() || callerIsBatch)) {
try {
diff --git a/src/com/android/providers/contacts/AccountWithDataSet.java b/src/com/android/providers/contacts/AccountWithDataSet.java
index 3fea8a6..b7484cd 100644
--- a/src/com/android/providers/contacts/AccountWithDataSet.java
+++ b/src/com/android/providers/contacts/AccountWithDataSet.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
-import com.android.internal.util.Objects;
-
import android.accounts.Account;
import android.text.TextUtils;
+import com.android.internal.util.Objects;
+
/**
* Account information that includes the data set, if any.
*/
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index 89ae591..21a16f1 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -20,10 +20,6 @@
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
import static com.android.providers.contacts.util.DbQueryUtils.getInequalityClause;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.SelectionBuilder;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -38,6 +34,10 @@
import android.provider.CallLog.Calls;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.SelectionBuilder;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.HashMap;
/**
diff --git a/src/com/android/providers/contacts/ContactDirectoryManager.java b/src/com/android/providers/contacts/ContactDirectoryManager.java
index 7116ed6..f243e79 100644
--- a/src/com/android/providers/contacts/ContactDirectoryManager.java
+++ b/src/com/android/providers/contacts/ContactDirectoryManager.java
@@ -16,13 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -41,6 +34,13 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
diff --git a/src/com/android/providers/contacts/ContactLocaleUtils.java b/src/com/android/providers/contacts/ContactLocaleUtils.java
index 2eb2ad6..0e7b292 100644
--- a/src/com/android/providers/contacts/ContactLocaleUtils.java
+++ b/src/com/android/providers/contacts/ContactLocaleUtils.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.HanziToPinyin.Token;
-
import android.provider.ContactsContract.FullNameStyle;
import android.util.SparseArray;
+import com.android.providers.contacts.HanziToPinyin.Token;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index 67429ca..62f49ae 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -16,11 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.content.SyncStateContentProviderHelper;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
-import com.android.providers.contacts.util.NeededForTesting;
-import com.google.android.collect.Sets;
-
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -80,6 +75,11 @@
import android.text.util.Rfc822Tokenizer;
import android.util.Log;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
+import com.android.providers.contacts.util.NeededForTesting;
+import com.google.android.collect.Sets;
+
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -779,6 +779,10 @@
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
}
+ public SQLiteDatabase getDatabase(boolean writable) {
+ return writable ? getWritableDatabase() : getReadableDatabase();
+ }
+
/**
* Clear all the cached database information and re-initialize it.
*
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index c321489..484aa79 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -16,51 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.content.ProjectionMap;
-import com.android.common.content.SyncStateContentProviderHelper;
-import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
-import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
-import com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Joins;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsDatabaseHelper.ViewGroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Views;
-import com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-import com.android.providers.contacts.aggregation.ContactAggregator.AggregationSuggestionParameter;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
-import com.android.providers.contacts.aggregation.ProfileAggregator;
-import com.android.providers.contacts.util.Clock;
-import com.android.providers.contacts.util.DbQueryUtils;
-import com.android.providers.contacts.util.NeededForTesting;
-import com.android.vcard.VCardComposer;
-import com.android.vcard.VCardConfig;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
@@ -151,6 +106,51 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.common.content.ProjectionMap;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
+import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
+import com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Joins;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.ContactsDatabaseHelper.ViewGroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Views;
+import com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+import com.android.providers.contacts.aggregation.ContactAggregator.AggregationSuggestionParameter;
+import com.android.providers.contacts.aggregation.ProfileAggregator;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
+import com.android.providers.contacts.util.Clock;
+import com.android.providers.contacts.util.DbQueryUtils;
+import com.android.providers.contacts.util.NeededForTesting;
+import com.android.vcard.VCardComposer;
+import com.android.vcard.VCardConfig;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -1264,13 +1264,6 @@
/* package */ static final String PROFILE_DB_TAG = "profile";
/**
- * The active (thread-local) database. This will be switched between a contacts-specific
- * database and a profile-specific database, depending on what the current operation is
- * targeted to.
- */
- private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>();
-
- /**
* The thread-local holder of the active transaction. Shared between this and the profile
* provider, to keep transactions on both databases synchronized.
*/
@@ -1393,7 +1386,7 @@
mDbHelper.set(mContactsHelper);
// Set up the DB helper for keeping transactions serialized.
- setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG);
+ setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG, this);
mContactDirectoryManager = new ContactDirectoryManager(this);
mGlobalSearchSupport = new GlobalSearchSupport(this);
@@ -1413,8 +1406,8 @@
};
// Set up the sub-provider for handling profiles.
- mProfileProvider = getProfileProvider();
- mProfileProvider.setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG);
+ mProfileProvider = newProfileProvider();
+ mProfileProvider.setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG, this);
ProviderInfo profileInfo = new ProviderInfo();
profileInfo.readPermission = "android.permission.READ_PROFILE";
profileInfo.writePermission = "android.permission.WRITE_PROFILE";
@@ -1521,6 +1514,8 @@
}
protected void performBackgroundTask(int task, Object arg) {
+ // Make sure we operate on the contacts db by default.
+ switchToContactMode();
switch (task) {
case BACKGROUND_TASK_INITIALIZE: {
initForDefaultLocale();
@@ -1551,6 +1546,8 @@
switchToProfileMode();
accountsChanged |= updateAccountsInBackground(accounts);
+ switchToContactMode();
+
updateContactsAccountCount(accounts);
updateDirectoriesInBackground(accountsChanged);
break;
@@ -1601,6 +1598,8 @@
cleanupPhotoStore();
switchToProfileMode();
cleanupPhotoStore();
+
+ switchToContactMode(); // Switch to the default, just in case.
break;
}
}
@@ -1705,8 +1704,7 @@
@VisibleForTesting
protected void cleanupPhotoStore() {
- SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
- mActiveDb.set(db);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// Assemble the set of photo store file IDs that are in use, and send those to the photo
// store. Any photos that aren't in that set will be deleted, and any photos that no
@@ -1759,7 +1757,9 @@
// using internal APIs or direct DB access to avoid permission errors.
if (!missingPhotoIds.isEmpty()) {
try {
- db.beginTransactionWithListener(this);
+ // Need to set the db listener because we need to run onCommit afterwards.
+ // Make sure to use the proper listener depending on the current mode.
+ db.beginTransactionWithListener(inProfileMode() ? mProfileProvider : this);
for (long missingPhotoId : missingPhotoIds) {
if (photoFileIdToDataId.containsKey(missingPhotoId)) {
long dataId = photoFileIdToDataId.get(missingPhotoId);
@@ -1796,7 +1796,7 @@
return mTransactionHolder;
}
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new ProfileProvider(this);
}
@@ -1835,7 +1835,8 @@
return Locale.getDefault();
}
- private boolean inProfileMode() {
+ @VisibleForTesting
+ final boolean inProfileMode() {
Boolean profileMode = mInProfileMode.get();
return profileMode != null && profileMode;
}
@@ -1921,7 +1922,10 @@
* Switches the provider's thread-local context variables to prepare for performing
* a profile operation.
*/
- protected void switchToProfileMode() {
+ private void switchToProfileMode() {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "switchToProfileMode", new RuntimeException("switchToProfileMode"));
+ }
mDbHelper.set(mProfileHelper);
mTransactionContext.set(mProfileTransactionContext);
mAggregator.set(mProfileAggregator);
@@ -1933,15 +1937,15 @@
* Switches the provider's thread-local context variables to prepare for performing
* a contacts operation.
*/
- protected void switchToContactMode() {
+ private void switchToContactMode() {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "switchToContactMode", new RuntimeException("switchToContactMode"));
+ }
mDbHelper.set(mContactsHelper);
mTransactionContext.set(mContactTransactionContext);
mAggregator.set(mContactAggregator);
mPhotoStore.set(mContactsPhotoStore);
mInProfileMode.set(false);
-
- // Clear out the active database; modification operations will set this to the contacts DB.
- mActiveDb.set(null);
}
@Override
@@ -2000,17 +2004,10 @@
}
}
- /**
- * Replaces the current (thread-local) database to use for the operation with the given one.
- * @param db The database to use.
- */
- /* package */ void substituteDb(SQLiteDatabase db) {
- mActiveDb.set(db);
- }
-
@Override
public Bundle call(String method, String arg, Bundle extras) {
waitForAccess(mReadAccessLatch);
+ switchToContactMode();
if (method.equals(Authorization.AUTHORIZATION_METHOD)) {
Uri uri = (Uri) extras.getParcelable(Authorization.KEY_URI_TO_AUTHORIZE);
@@ -2110,13 +2107,20 @@
@Override
public void onBegin() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "onBeginTransaction: " + (inProfileMode() ? "profile" : "contacts"));
+ onBeginTransactionInternal(false);
+ }
+
+ protected void onBeginTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onBeginTransaction: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onBeginTransactionInternal"));
}
- if (inProfileMode()) {
+ if (forProfile) {
+ switchToProfileMode();
mProfileAggregator.clearPendingAggregations();
mProfileTransactionContext.clearExceptSearchIndexUpdates();
} else {
+ switchToContactMode();
mContactAggregator.clearPendingAggregations();
mContactTransactionContext.clearExceptSearchIndexUpdates();
}
@@ -2124,11 +2128,23 @@
@Override
public void onCommit() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "beforeTransactionCommit: " + (inProfileMode() ? "profile" : "contacts"));
+ onCommitTransactionInternal(false);
+ }
+
+ protected void onCommitTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onCommitTransactionInternal: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onCommitTransactionInternal"));
}
+ if (forProfile) {
+ switchToProfileMode();
+ } else {
+ switchToContactMode();
+ }
+
flushTransactionalChanges();
- mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get());
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ mAggregator.get().aggregateInTransaction(mTransactionContext.get(), db);
if (mVisibleTouched) {
mVisibleTouched = false;
mDbHelper.get().updateAllVisible();
@@ -2147,13 +2163,21 @@
@Override
public void onRollback() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "beforeTransactionRollback: " + (inProfileMode() ? "profile" : "contacts"));
+ onRollbackTransactionInternal(false);
+ }
+
+ protected void onRollbackTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onRollbackTransactionInternal: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onRollbackTransactionInternal"));
}
- // mDbHelper may not be pointing at the "right" db helper due to a bug,
- // so we invalidate both for now.
- mContactsHelper.invalidateAllCache();
- mProfileHelper.invalidateAllCache();
+ if (forProfile) {
+ switchToProfileMode();
+ } else {
+ switchToContactMode();
+ }
+
+ mDbHelper.get().invalidateAllCache();
}
private void updateSearchIndexInTransaction() {
@@ -2167,12 +2191,13 @@
private void flushTransactionalChanges() {
if (VERBOSE_LOGGING) {
- Log.v(TAG, "flushTransactionChanges");
+ Log.v(TAG, "flushTransactionalChanges: " + (inProfileMode() ? "profile" : "contacts"));
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) {
- mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId);
- mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(),
+ mDbHelper.get().updateRawContactDisplayName(db, rawContactId);
+ mAggregator.get().onRawContactInsert(mTransactionContext.get(), db,
rawContactId);
}
@@ -2182,7 +2207,7 @@
mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL);
appendIds(mSb, dirtyRawContacts);
mSb.append(")");
- mActiveDb.get().execSQL(mSb.toString());
+ db.execSQL(mSb.toString());
}
Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds();
@@ -2191,13 +2216,13 @@
mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL);
appendIds(mSb, updatedRawContacts);
mSb.append(")");
- mActiveDb.get().execSQL(mSb.toString());
+ db.execSQL(mSb.toString());
}
// Update sync states.
for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) {
long id = entry.getKey();
- if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) {
+ if (mDbHelper.get().getSyncState().update(db, id, entry.getValue()) <= 0) {
throw new IllegalStateException(
"unable to update sync state, does it still exist?");
}
@@ -2265,10 +2290,7 @@
Log.v(TAG, "insertInTransaction: uri=" + uri + " values=[" + values + "]");
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final boolean callerIsSyncAdapter =
readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false);
@@ -2279,7 +2301,7 @@
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values);
+ id = mDbHelper.get().getSyncState().insert(db, values);
break;
case CONTACTS: {
@@ -2506,7 +2528,9 @@
mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
}
- long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ long rawContactId = db.insert(Tables.RAW_CONTACTS,
RawContacts.CONTACT_ID, mValues);
int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT;
if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) {
@@ -2538,7 +2562,8 @@
}
private Long findGroupByRawContactId(String selection, long rawContactId) {
- Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS,
PROJECTION_GROUP_ID, selection,
new String[]{Long.toString(rawContactId)},
null /* groupBy */, null /* having */, null /* orderBy */);
@@ -2570,7 +2595,8 @@
groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId);
groupMembershipValues.put(DataColumns.MIMETYPE_ID,
mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE));
- mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.insert(Tables.DATA, null, groupMembershipValues);
}
private void deleteDataGroupMembership(long rawContactId, long groupId) {
@@ -2578,7 +2604,8 @@
Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)),
Long.toString(groupId),
Long.toString(rawContactId)};
- mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs);
}
/**
@@ -2611,7 +2638,8 @@
mValues.remove(Data.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = rowHandler.insert(db, mTransactionContext.get(), rawContactId, mValues);
if (!callerIsSyncAdapter) {
mTransactionContext.get().markRawContactDirty(rawContactId);
}
@@ -2642,7 +2670,8 @@
mValues.remove(RawContacts.ACCOUNT_TYPE);
// Insert the new stream item.
- id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = db.insert(Tables.STREAM_ITEMS, null, mValues);
if (id == -1) {
// Insertion failed.
return 0;
@@ -2682,7 +2711,8 @@
// Process the photo and store it.
if (processStreamItemPhoto(mValues, false)) {
// Insert the stream item photo.
- id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = db.insert(Tables.STREAM_ITEM_PHOTOS, null, mValues);
}
}
return id;
@@ -2734,7 +2764,8 @@
*/
private long lookupRawContactIdForStreamId(long streamItemId) {
long rawContactId = -1;
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.STREAM_ITEMS,
new String[]{StreamItems.RAW_CONTACT_ID},
StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)},
null, null, null);
@@ -2786,7 +2817,8 @@
*/
private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) {
long postCleanupInsertedStreamId = insertedStreamItemId;
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID},
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ Cursor c = db.query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID},
StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)},
null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC");
try {
@@ -2802,7 +2834,7 @@
// The stream item just inserted is being deleted.
postCleanupInsertedStreamId = 0;
}
- deleteStreamItem(c.getLong(0));
+ deleteStreamItem(db, c.getLong(0));
c.moveToPrevious();
}
}
@@ -2818,6 +2850,8 @@
private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) {
int count = 0;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Note that the query will return data according to the access restrictions,
// so we don't need to worry about deleting data we don't have permission to read.
Uri dataUri = inProfileMode()
@@ -2830,7 +2864,7 @@
long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID);
String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c);
+ count += rowHandler.delete(db, mTransactionContext.get(), c);
if (!callerIsSyncAdapter) {
mTransactionContext.get().markRawContactDirty(rawContactId);
}
@@ -2847,6 +2881,8 @@
*/
public int deleteData(long dataId, String[] allowedMimeTypes) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Note that the query will return data according to the access restrictions,
// so we don't need to worry about deleting data we don't have permission to read.
mSelectionArgs1[0] = String.valueOf(dataId);
@@ -2872,7 +2908,7 @@
+ Lists.newArrayList(allowedMimeTypes));
}
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c);
+ return rowHandler.delete(db, mTransactionContext.get(), c);
} finally {
c.close();
}
@@ -2907,12 +2943,14 @@
mValues.put(Groups.DIRTY, 1);
}
- long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ long result = db.insert(Tables.GROUPS, Groups.TITLE, mValues);
if (!callerIsSyncAdapter && isFavoritesGroup) {
// If the inserted group is a favorite group, add all starred raw contacts to it.
mSelectionArgs1[0] = Long.toString(accountId);
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS,
+ Cursor c = db.query(Tables.RAW_CONTACTS,
new String[]{RawContacts._ID, RawContacts.STARRED},
RawContactsColumns.CONCRETE_ACCOUNT_ID + "=?", mSelectionArgs1,
null, null, null);
@@ -2975,8 +3013,10 @@
c.close();
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// If we didn't find a duplicate, we're fine to insert.
- final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values);
+ final long id = db.insert(Tables.SETTINGS, null, values);
if (values.containsKey(Settings.UNGROUPED_VISIBLE)) {
mVisibleTouched = true;
@@ -2993,6 +3033,8 @@
final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL);
String customProtocol = null;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) {
customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL);
if (TextUtils.isEmpty(customProtocol)) {
@@ -3068,7 +3110,7 @@
Cursor cursor = null;
try {
- cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION,
+ cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION,
mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null,
Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID);
if (cursor.moveToFirst()) {
@@ -3110,7 +3152,7 @@
values.getAsString(StatusUpdates.CHAT_CAPABILITY));
// Insert the presence update
- mActiveDb.get().replace(Tables.PRESENCE, null, mValues);
+ db.replace(Tables.PRESENCE, null, mValues);
}
@@ -3237,10 +3279,7 @@
" selection=[" + selection + "] args=" + Arrays.toString(selectionArgs));
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
flushTransactionalChanges();
final boolean callerIsSyncAdapter =
@@ -3249,14 +3288,14 @@
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection,
+ return mDbHelper.get().getSyncState().delete(db, selection,
selectionArgs);
case SYNCSTATE_ID: {
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId,
+ return mDbHelper.get().getSyncState().delete(db, selectionWithId,
selectionArgs);
}
@@ -3264,7 +3303,7 @@
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId,
+ return mProfileHelper.getSyncState().delete(db, selectionWithId,
selectionArgs);
}
@@ -3289,7 +3328,7 @@
"Missing a lookup key", uri));
}
final String lookupKey = pathSegments.get(2);
- final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ final long contactId = lookupContactIdByLookupKey(db, lookupKey);
return deleteContact(contactId, callerIsSyncAdapter);
}
@@ -3311,7 +3350,7 @@
args[0] = String.valueOf(contactId);
args[1] = Uri.encode(lookupKey);
lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?");
- Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null,
+ Cursor c = query(db, lookupQb, null, selection, args, null, null,
null, null, null);
try {
if (c.getCount() == 1) {
@@ -3335,7 +3374,7 @@
case PROFILE_RAW_CONTACTS: {
invalidateFastScrollingIndexCache();
int numDeletes = 0;
- Cursor c = mActiveDb.get().query(Views.RAW_CONTACTS,
+ Cursor c = db.query(Views.RAW_CONTACTS,
new String[]{RawContacts._ID, RawContacts.CONTACT_ID},
appendAccountIdToSelection(uri, selection), selectionArgs,
null, null, null);
@@ -3388,7 +3427,7 @@
case GROUPS: {
int numDeletes = 0;
- Cursor c = mActiveDb.get().query(Views.GROUPS, Projections.ID,
+ Cursor c = db.query(Views.GROUPS, Projections.ID,
appendAccountIdToSelection(uri, selection), selectionArgs,
null, null, null);
try {
@@ -3464,21 +3503,22 @@
}
public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mGroupIdCache.clear();
final long groupMembershipMimetypeId = mDbHelper.get()
.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
- mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "="
+ db.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "="
+ groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "="
+ groupId, null);
try {
if (callerIsSyncAdapter) {
- return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null);
+ return db.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null);
} else {
mValues.clear();
mValues.put(Groups.DELETED, 1);
mValues.put(Groups.DIRTY, 1);
- return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId,
+ return db.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId,
null);
}
} finally {
@@ -3487,20 +3527,22 @@
}
private int deleteSettings(Uri uri, String selection, String[] selectionArgs) {
- final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ final int count = db.delete(Tables.SETTINGS, selection, selectionArgs);
mVisibleTouched = true;
return count;
}
private int deleteContact(long contactId, boolean callerIsSyncAdapter) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mSelectionArgs1[0] = Long.toString(contactId);
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
+ Cursor c = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
RawContacts.CONTACT_ID + "=?", mSelectionArgs1,
null, null, null);
try {
while (c.moveToNext()) {
long rawContactId = c.getLong(0);
- markRawContactAsDeleted(rawContactId, callerIsSyncAdapter);
+ markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
}
} finally {
c.close();
@@ -3508,36 +3550,38 @@
mProviderStatusUpdateNeeded = true;
- return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null);
+ return db.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null);
}
public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) {
mAggregator.get().invalidateAggregationExceptionCache();
mProviderStatusUpdateNeeded = true;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Find and delete stream items associated with the raw contact.
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS,
+ Cursor c = db.query(Tables.STREAM_ITEMS,
new String[]{StreamItems._ID},
StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)},
null, null, null);
try {
while (c.moveToNext()) {
- deleteStreamItem(c.getLong(0));
+ deleteStreamItem(db, c.getLong(0));
}
} finally {
c.close();
}
if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) {
- mActiveDb.get().delete(Tables.PRESENCE,
+ db.delete(Tables.PRESENCE,
PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null);
- int count = mActiveDb.get().delete(Tables.RAW_CONTACTS,
+ int count = db.delete(Tables.RAW_CONTACTS,
RawContacts._ID + "=" + rawContactId, null);
mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId);
return count;
} else {
mDbHelper.get().removeContactIfSingleton(rawContactId);
- return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter);
+ return markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
}
}
@@ -3545,7 +3589,8 @@
* Returns whether the given raw contact ID is local (i.e. has no account associated with it).
*/
private boolean rawContactIsLocal(long rawContactId) {
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, Projections.LITERAL_ONE,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.RAW_CONTACTS, Projections.LITERAL_ONE,
RawContactsColumns.CONCRETE_ID + "=? AND " +
RawContactsColumns.ACCOUNT_ID + "=" + Clauses.LOCAL_ACCOUNT_ID,
new String[] {String.valueOf(rawContactId)}, null, null, null);
@@ -3562,20 +3607,22 @@
if (VERBOSE_LOGGING) {
Log.v(TAG, "deleting data from status_updates for " + selection);
}
- mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection),
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection),
selectionArgs);
- return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs);
+ return db.delete(Tables.PRESENCE, selection, selectionArgs);
}
private int deleteStreamItems(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
int count = 0;
- final Cursor c = mActiveDb.get().query(Views.STREAM_ITEMS, Projections.ID,
+ final Cursor c = db.query(Views.STREAM_ITEMS, Projections.ID,
selection, selectionArgs, null, null, null);
try {
c.moveToPosition(-1);
while (c.moveToNext()) {
- count += deleteStreamItem(c.getLong(0));
+ count += deleteStreamItem(db, c.getLong(0));
}
} finally {
c.close();
@@ -3583,25 +3630,28 @@
return count;
}
- private int deleteStreamItem(long streamItemId) {
+ private int deleteStreamItem(SQLiteDatabase db, long streamItemId) {
deleteStreamItemPhotos(streamItemId);
- return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?",
+ return db.delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?",
new String[]{String.valueOf(streamItemId)});
}
private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ return db.delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs);
}
private int deleteStreamItemPhotos(long streamItemId) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// Note that this does not enforce the modifying account.
- return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS,
+ return db.delete(Tables.STREAM_ITEM_PHOTOS,
StreamItemPhotos.STREAM_ITEM_ID + "=?",
new String[]{String.valueOf(streamItemId)});
}
- private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) {
+ private int markRawContactAsDeleted(SQLiteDatabase db, long rawContactId,
+ boolean callerIsSyncAdapter) {
mSyncToNetwork = true;
mValues.clear();
@@ -3610,11 +3660,11 @@
mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1);
mValues.putNull(RawContacts.CONTACT_ID);
mValues.put(RawContacts.DIRTY, 1);
- return updateRawContact(rawContactId, mValues, callerIsSyncAdapter);
+ return updateRawContact(db, rawContactId, mValues, callerIsSyncAdapter);
}
private int deleteDataUsage() {
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
db.execSQL("UPDATE " + Tables.RAW_CONTACTS + " SET " +
Contacts.TIMES_CONTACTED + "=0," +
Contacts.LAST_TIME_CONTACTED + "=NULL"
@@ -3637,10 +3687,7 @@
" values=[" + values + "]");
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
int count = 0;
@@ -3657,7 +3704,7 @@
switch(match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().update(mActiveDb.get(), values,
+ return mDbHelper.get().getSyncState().update(db, values,
appendAccountToSelection(uri, selection), selectionArgs);
case SYNCSTATE_ID: {
@@ -3665,7 +3712,7 @@
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mDbHelper.get().getSyncState().update(mActiveDb.get(), values,
+ return mDbHelper.get().getSyncState().update(db, values,
selectionWithId, selectionArgs);
}
@@ -3674,7 +3721,7 @@
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mProfileHelper.getSyncState().update(mActiveDb.get(), values,
+ return mProfileHelper.getSyncState().update(db, values,
selectionWithId, selectionArgs);
}
@@ -3687,7 +3734,8 @@
case CONTACTS_ID: {
invalidateFastScrollingIndexCache();
- count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter);
+ count = updateContactOptions(db, ContentUris.parseId(uri), values,
+ callerIsSyncAdapter);
break;
}
@@ -3701,8 +3749,8 @@
"Missing a lookup key", uri));
}
final String lookupKey = pathSegments.get(2);
- final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
- count = updateContactOptions(contactId, values, callerIsSyncAdapter);
+ final long contactId = lookupContactIdByLookupKey(db, lookupKey);
+ count = updateContactOptions(db, contactId, values, callerIsSyncAdapter);
break;
}
@@ -3790,7 +3838,7 @@
}
case AGGREGATION_EXCEPTIONS: {
- count = updateAggregationException(mActiveDb.get(), values);
+ count = updateAggregationException(db, values);
break;
}
@@ -3875,12 +3923,13 @@
private int updateStatusUpdate(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// update status_updates table, if status is provided
// TODO should account type/name be appended to the where clause?
int updateCount = 0;
ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values);
if (settableValues.size() > 0) {
- updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES,
+ updateCount = db.update(Tables.STATUS_UPDATES,
settableValues,
getWhereClauseForStatusUpdatesTable(selection),
selectionArgs);
@@ -3889,7 +3938,7 @@
// now update the Presence table
settableValues = getSettableColumnsForPresenceTable(values);
if (settableValues.size() > 0) {
- updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues,
+ updateCount = db.update(Tables.PRESENCE, settableValues,
selection, selectionArgs);
}
// TODO updateCount is not entirely a valid count of updated rows because 2 tables could
@@ -3906,8 +3955,10 @@
values.remove(RawContacts.ACCOUNT_NAME);
values.remove(RawContacts.ACCOUNT_TYPE);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// If there's been no exception, the update should be fine.
- return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs);
+ return db.update(Tables.STREAM_ITEMS, values, selection, selectionArgs);
}
private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection,
@@ -3920,10 +3971,12 @@
values.remove(RawContacts.ACCOUNT_NAME);
values.remove(RawContacts.ACCOUNT_TYPE);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Process the photo (since we're updating, it's valid for the photo to not be present).
if (processStreamItemPhoto(values, true)) {
// If there's been no exception, the update should be fine.
- return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection,
+ return db.update(Tables.STREAM_ITEM_PHOTOS, values, selection,
selectionArgs);
}
return 0;
@@ -3983,7 +4036,7 @@
String[] selectionArgs, boolean callerIsSyncAdapter) {
mGroupIdCache.clear();
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final ContactsDatabaseHelper dbHelper = mDbHelper.get();
final ContentValues updatedValues = new ContentValues();
@@ -4068,7 +4121,8 @@
private int updateSettings(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ final int count = db.update(Tables.SETTINGS, values, selection, selectionArgs);
if (values.containsKey(Settings.UNGROUPED_VISIBLE)) {
mVisibleTouched = true;
}
@@ -4088,13 +4142,14 @@
}
int count = 0;
- Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ Cursor cursor = db.query(Views.RAW_CONTACTS,
Projections.ID, selection,
selectionArgs, null, null, null);
try {
while (cursor.moveToNext()) {
long rawContactId = cursor.getLong(0);
- updateRawContact(rawContactId, values, callerIsSyncAdapter);
+ updateRawContact(db, rawContactId, values, callerIsSyncAdapter);
count++;
}
} finally {
@@ -4104,7 +4159,7 @@
return count;
}
- private int updateRawContact(long rawContactId, ContentValues values,
+ private int updateRawContact(SQLiteDatabase db, long rawContactId, ContentValues values,
boolean callerIsSyncAdapter) {
final String selection = RawContactsColumns.CONCRETE_ID + " = ?";
mSelectionArgs1[0] = Long.toString(rawContactId);
@@ -4127,7 +4182,7 @@
String oldDataSet = null;
if (requestUndoDelete || isAccountChanging) {
- Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS,
+ Cursor cursor = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS,
selection, mSelectionArgs1, null, null, null);
try {
if (cursor.moveToFirst()) {
@@ -4172,7 +4227,7 @@
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT);
}
- int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1);
+ int count = db.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1);
if (count != 0) {
if (values.containsKey(RawContacts.AGGREGATION_MODE)) {
int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE);
@@ -4195,7 +4250,7 @@
// If it is starred, add a group membership, if one doesn't already exist
// otherwise delete any matching group memberships.
if (!callerIsSyncAdapter && isAccountChanging) {
- boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(),
+ boolean starred = 0 != DatabaseUtils.longForQuery(db,
SELECTION_STARRED_FROM_RAW_CONTACTS,
new String[]{Long.toString(rawContactId)});
updateFavoritesMembership(rawContactId, starred);
@@ -4209,7 +4264,7 @@
}
if (values.containsKey(RawContacts.SOURCE_ID)) {
- mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId);
+ mAggregator.get().updateLookupKeyForRawContact(db, rawContactId);
}
if (values.containsKey(RawContacts.NAME_VERIFIED)) {
@@ -4218,7 +4273,7 @@
if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) {
mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId);
}
- mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId);
+ mAggregator.get().updateDisplayNameForRawContact(db, rawContactId);
}
if (requestUndoDelete && previousDeleted == 1) {
// Note before the accounts refactoring, we used to use the *old* account here,
@@ -4273,10 +4328,12 @@
return 0;
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
boolean updated =
- rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c,
+ rowHandler.update(db, mTransactionContext.get(), values, c,
callerIsSyncAdapter);
if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS);
@@ -4287,13 +4344,15 @@
private int updateContactOptions(ContentValues values, String selection,
String[] selectionArgs, boolean callerIsSyncAdapter) {
int count = 0;
- Cursor cursor = mActiveDb.get().query(Views.CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ Cursor cursor = db.query(Views.CONTACTS,
new String[] { Contacts._ID }, selection, selectionArgs, null, null, null);
try {
while (cursor.moveToNext()) {
long contactId = cursor.getLong(0);
- updateContactOptions(contactId, values, callerIsSyncAdapter);
+ updateContactOptions(db, contactId, values, callerIsSyncAdapter);
count++;
}
} finally {
@@ -4303,7 +4362,7 @@
return count;
}
- private int updateContactOptions(long contactId, ContentValues values,
+ private int updateContactOptions(SQLiteDatabase db, long contactId, ContentValues values,
boolean callerIsSyncAdapter) {
mValues.clear();
@@ -4329,11 +4388,11 @@
}
mSelectionArgs1[0] = String.valueOf(contactId);
- mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?"
+ db.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?"
+ " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1);
if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) {
- Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS,
+ Cursor cursor = db.query(Views.RAW_CONTACTS,
new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?",
mSelectionArgs1, null, null, null);
try {
@@ -4361,13 +4420,13 @@
ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED,
values, Contacts.STARRED);
- int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?",
+ int rslt = db.update(Tables.CONTACTS, mValues, Contacts._ID + "=?",
mSelectionArgs1);
if (values.containsKey(Contacts.LAST_TIME_CONTACTED) &&
!values.containsKey(Contacts.TIMES_CONTACTED)) {
- mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1);
- mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1);
+ db.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1);
+ db.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1);
}
return rslt;
}
@@ -4416,6 +4475,7 @@
return 1;
}
+ @Override
public void onAccountsUpdated(Account[] accounts) {
scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS);
}
@@ -4499,7 +4559,6 @@
final ContactsDatabaseHelper dbHelper = mDbHelper.get();
final SQLiteDatabase db = dbHelper.getWritableDatabase();
- mActiveDb.set(db);
db.beginTransaction();
// WARNING: This method can be run in either contacts mode or profile mode. It is
@@ -4716,7 +4775,6 @@
// Otherwise proceed with a normal query against the contacts DB.
switchToContactMode();
- mActiveDb.set(mContactsHelper.getReadableDatabase());
String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY);
if (directory == null) {
return addSnippetExtrasToCursor(uri,
@@ -4868,10 +4926,7 @@
String[] selectionArgs, String sortOrder, final long directoryId,
final CancellationSignal cancellationSignal) {
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getReadableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String groupBy = null;
@@ -4886,7 +4941,7 @@
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection,
+ return mDbHelper.get().getSyncState().query(db, projection, selection,
selectionArgs, sortOrder);
case CONTACTS: {
@@ -4918,7 +4973,7 @@
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(lookupQb, uri, projection);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey,
cancellationSignal);
@@ -4929,7 +4984,7 @@
setTablesAndProjectionMapForContacts(qb, uri, projection);
selectionArgs = insertSelectionArg(selectionArgs,
- String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey)));
+ String.valueOf(lookupContactIdByLookupKey(db, lookupKey)));
qb.appendWhere(Contacts._ID + "=?");
break;
}
@@ -4953,7 +5008,7 @@
lookupQb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID);
}
lookupQb.appendWhere(" AND ");
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey,
cancellationSignal);
@@ -4965,7 +5020,7 @@
}
setTablesAndProjectionMapForData(qb, uri, projection, false);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
selectionArgs = insertSelectionArg(selectionArgs,
String.valueOf(contactId));
if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) {
@@ -4996,7 +5051,7 @@
long contactId = Long.parseLong(pathSegments.get(3));
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForStreamItems(lookupQb);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
StreamItems.CONTACT_ID, contactId,
StreamItems.CONTACT_LOOKUP_KEY, lookupKey,
@@ -5007,7 +5062,7 @@
}
setTablesAndProjectionMapForStreamItems(qb);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId));
qb.appendWhere(RawContacts.CONTACT_ID + "=?");
break;
@@ -5015,7 +5070,7 @@
case CONTACTS_AS_VCARD: {
final String lookupKey = Uri.encode(uri.getPathSegments().get(2));
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
qb.setTables(Views.CONTACTS);
qb.setProjectionMap(sContactsVCardProjectionMap);
selectionArgs = insertSelectionArg(selectionArgs,
@@ -5027,7 +5082,7 @@
case CONTACTS_AS_MULTI_VCARD: {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
String currentDateString = dateFormat.format(new Date()).toString();
- return mActiveDb.get().rawQuery(
+ return db.rawQuery(
"SELECT" +
" 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," +
" NULL AS " + OpenableColumns.SIZE,
@@ -5173,7 +5228,7 @@
System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length);
}
- Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs);
+ Cursor cursor = db.rawQuery(unionQuery, doubledSelectionArgs);
if (cursor != null) {
cursor.setNotificationUri(getContext().getContentResolver(),
ContactsContract.AUTHORITY_URI);
@@ -5262,7 +5317,7 @@
setTablesAndProjectionMapForEntities(lookupQb, uri, projection);
lookupQb.appendWhere(" AND ");
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Contacts.Entity.CONTACT_ID, contactId,
Contacts.Entity.LOOKUP_KEY, lookupKey,
@@ -5274,7 +5329,7 @@
setTablesAndProjectionMapForEntities(qb, uri, projection);
selectionArgs = insertSelectionArg(selectionArgs,
- String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey)));
+ String.valueOf(lookupContactIdByLookupKey(db, lookupKey)));
qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?");
break;
}
@@ -5734,7 +5789,7 @@
// were returned, fall back to doing a match of the trailing 7 digits.
qb.setStrict(true);
boolean foundResult = false;
- Cursor cursor = query(mActiveDb.get(), qb, projection, selection, selectionArgs,
+ Cursor cursor = query(db, qb, projection, selection, selectionArgs,
sortOrder, groupBy, null, limit, cancellationSignal);
try {
if (cursor.getCount() > 0) {
@@ -5867,7 +5922,7 @@
case SEARCH_SUGGESTIONS: {
return mGlobalSearchSupport.handleSearchSuggestionsQuery(
- mActiveDb.get(), uri, projection, limit);
+ db, uri, projection, limit);
}
case SEARCH_SHORTCUT: {
@@ -5875,7 +5930,7 @@
String filter = getQueryParameter(
uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
return mGlobalSearchSupport.handleSearchShortcutRefresh(
- mActiveDb.get(), projection, lookupKey, filter);
+ db, projection, lookupKey, filter);
}
case RAW_CONTACT_ENTITIES:
@@ -5925,11 +5980,11 @@
qb.setStrict(true);
Cursor cursor =
- query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy,
+ query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy,
having, limit, cancellationSignal);
if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) {
- bundleFastScrollingIndexExtras(cursor, uri, mActiveDb.get(), qb, selection,
+ bundleFastScrollingIndexExtras(cursor, uri, db, qb, selection,
selectionArgs, sortOrder, addressBookIndexerCountExpression,
cancellationSignal);
}
@@ -5990,10 +6045,6 @@
}
private void invalidateFastScrollingIndexCache() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "invalidatemFastScrollingIndexCache");
- }
-
// FastScrollingIndexCache is thread-safe, no need to synchronize here.
mFastScrollingIndexCache.invalidate();
}
@@ -7078,20 +7129,15 @@
public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode)
throws FileNotFoundException {
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- if (mode.equals("r")) {
- mActiveDb.set(mContactsHelper.getReadableDatabase());
- } else {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
- }
+ final boolean writing = mode.contains("w");
+
+ final SQLiteDatabase db = mDbHelper.get().getDatabase(writing);
int match = sUriMatcher.match(uri);
switch (match) {
case CONTACTS_ID_PHOTO: {
long contactId = Long.parseLong(uri.getPathSegments().get(1));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=" + Contacts.PHOTO_ID + " AND " +
RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)});
@@ -7103,7 +7149,7 @@
"Display photos retrieved by contact ID can only be read.");
}
long contactId = Long.parseLong(uri.getPathSegments().get(1));
- Cursor c = mActiveDb.get().query(Tables.CONTACTS,
+ Cursor c = db.query(Tables.CONTACTS,
new String[]{Contacts.PHOTO_FILE_ID},
Contacts._ID + "=?", new String[]{String.valueOf(contactId)},
null, null, null);
@@ -7125,7 +7171,7 @@
throw new IllegalArgumentException(
"Display photos retrieved by contact ID can only be read.");
}
- Cursor c = mActiveDb.get().query(Tables.CONTACTS,
+ Cursor c = db.query(Tables.CONTACTS,
new String[]{Contacts.PHOTO_FILE_ID}, null, null, null, null, null);
try {
if (c.moveToFirst()) {
@@ -7163,7 +7209,7 @@
long contactId = Long.parseLong(pathSegments.get(3));
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(lookupQb, uri, projection);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, null, null, null, null, null,
Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey, null);
if (c != null) {
@@ -7175,7 +7221,7 @@
return openDisplayPhotoForRead(photoFileId);
} else {
long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=?", new String[]{String.valueOf(photoId)});
}
} finally {
@@ -7186,8 +7232,8 @@
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(qb, uri, projection);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
- Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?",
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
+ Cursor c = qb.query(db, projection, Contacts._ID + "=?",
new String[]{String.valueOf(contactId)}, null, null, null);
try {
c.moveToFirst();
@@ -7196,7 +7242,7 @@
return openDisplayPhotoForRead(photoFileId);
} else {
long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=?", new String[]{String.valueOf(photoId)});
}
} finally {
@@ -7213,7 +7259,7 @@
String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID};
setTablesAndProjectionMapForData(qb, uri, projection, false);
long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE);
- Cursor c = qb.query(mActiveDb.get(), projection,
+ Cursor c = qb.query(db, projection,
Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?",
new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)},
null, null, Data.IS_PRIMARY + " DESC");
@@ -7251,7 +7297,7 @@
case DATA_ID: {
long dataId = Long.parseLong(uri.getPathSegments().get(1));
long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE);
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId,
new String[]{String.valueOf(dataId)});
}
@@ -7290,7 +7336,7 @@
inBuilder.append(",");
}
// TODO: Figure out what to do if the profile contact is in the list.
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
inBuilder.append(contactId);
index++;
}
@@ -7955,10 +8001,9 @@
SQLiteDatabase db = null;
boolean success = false;
try {
- // Re-aggregation os only for the contacts DB.
+ // Re-aggregation is only for the contacts DB.
switchToContactMode();
db = mContactsHelper.getWritableDatabase();
- mActiveDb.set(db);
// Start the actual process.
db.beginTransaction();
@@ -8038,7 +8083,7 @@
}
rawContactIdSelect.append(")");
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mSelectionArgs1[0] = String.valueOf(currentTimeMillis);
@@ -8080,7 +8125,7 @@
/* package */ int updateDataUsageStat(
List<Long> dataIds, String type, long currentTimeMillis) {
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final String typeString = String.valueOf(getDataUsageFeedbackType(type, null));
final String currentTimeMillisString = String.valueOf(currentTimeMillis);
@@ -8253,4 +8298,15 @@
}
throw new IllegalArgumentException("Invalid usage type " + type);
}
+
+ /** Use only for debug logging */
+ @Override
+ public String toString() {
+ return "ContactsProvider2";
+ }
+
+ @NeededForTesting
+ public void switchToProfileModeForTest() {
+ switchToProfileMode();
+ }
}
diff --git a/src/com/android/providers/contacts/ContactsTransaction.java b/src/com/android/providers/contacts/ContactsTransaction.java
index 7a92cae..c6c11d9 100644
--- a/src/com/android/providers/contacts/ContactsTransaction.java
+++ b/src/com/android/providers/contacts/ContactsTransaction.java
@@ -16,11 +16,12 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteTransactionListener;
+import android.util.Log;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
import java.util.List;
import java.util.Map;
@@ -40,13 +41,16 @@
/**
* The list of databases that have been enlisted in this transaction.
+ *
+ * Note we insert elements to the head of the list, so that we endTransaction() in the reverse
+ * order.
*/
- private List<SQLiteDatabase> mDatabasesForTransaction;
+ private final List<SQLiteDatabase> mDatabasesForTransaction;
/**
* The mapping of tags to databases involved in this transaction.
*/
- private Map<String, SQLiteDatabase> mDatabaseTagMap;
+ private final Map<String, SQLiteDatabase> mDatabaseTagMap;
/**
* Whether any actual changes have been made successfully in this transaction.
@@ -97,8 +101,16 @@
*/
public void startTransactionForDb(SQLiteDatabase db, String tag,
SQLiteTransactionListener listener) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "startTransactionForDb: db=" + db.getPath() +
+ " tag=" + tag + " listener=" + listener +
+ " startTransaction=" + !hasDbInTransaction(tag),
+ new RuntimeException("startTransactionForDb"));
+ }
if (!hasDbInTransaction(tag)) {
- mDatabasesForTransaction.add(db);
+ // Insert a new db into the head of the list, so that we'll endTransaction() in
+ // the reverse order.
+ mDatabasesForTransaction.add(0, db);
mDatabaseTagMap.put(tag, db);
if (listener != null) {
db.beginTransactionWithListener(listener);
@@ -154,13 +166,33 @@
}
/**
+ * @return the tag for a database. Only intended to be used for logging.
+ */
+ private String getTagForDb(SQLiteDatabase db) {
+ for (String tag : mDatabaseTagMap.keySet()) {
+ if (db == mDatabaseTagMap.get(tag)) {
+ return tag;
+ }
+ }
+ return null;
+ }
+
+ /**
* Completes the transaction, ending the DB transactions for all associated databases.
* @param callerIsBatch Whether this is being performed in the context of a batch operation.
* If it is not, and the transaction is marked as batch, this call is a no-op.
*/
public void finish(boolean callerIsBatch) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "ContactsTransaction.finish callerIsBatch=" +
+ callerIsBatch, new RuntimeException("ContactsTransaction.finish"));
+ }
if (!mBatch || callerIsBatch) {
for (SQLiteDatabase db : mDatabasesForTransaction) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "ContactsTransaction.finish: " +
+ "endTransaction for " + getTagForDb(db));
+ }
// If an exception was thrown while yielding, it's possible that we no longer have
// a lock on this database, so we need to check before attempting to end its
// transaction. Otherwise, we should always expect to be in a transaction (and will
diff --git a/src/com/android/providers/contacts/DataRowHandler.java b/src/com/android/providers/contacts/DataRowHandler.java
index b98f6c7..0366532 100644
--- a/src/com/android/providers/contacts/DataRowHandler.java
+++ b/src/com/android/providers/contacts/DataRowHandler.java
@@ -15,12 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -33,6 +27,12 @@
import android.provider.ContactsContract.Data;
import android.text.TextUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handles inserts and update for a specific Data type.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java b/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
index b717d31..0bb17c2 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -24,6 +22,8 @@
import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
import android.text.TextUtils;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Superclass for data row handlers that deal with types (e.g. Home, Work, Other) and
* labels, which are custom types.
diff --git a/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java b/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
index 0202fd6..502b835 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
@@ -15,10 +15,10 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.Context;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
public class DataRowHandlerForCustomMimetype extends DataRowHandler {
public DataRowHandlerForCustomMimetype(Context context,
diff --git a/src/com/android/providers/contacts/DataRowHandlerForEmail.java b/src/com/android/providers/contacts/DataRowHandlerForEmail.java
index f1fa941..38cb2e1 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForEmail.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForEmail.java
@@ -15,15 +15,15 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for email address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
index 3a4b167..0d2427a 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
@@ -15,15 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -33,6 +24,15 @@
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
+import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/DataRowHandlerForIdentity.java b/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
index 440e430..48ce5e4 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
@@ -15,14 +15,14 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Identity;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for Identity data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForIm.java b/src/com/android/providers/contacts/DataRowHandlerForIm.java
index 009bb89..faf10ad 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForIm.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForIm.java
@@ -15,13 +15,13 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Im;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for IM address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForNickname.java b/src/com/android/providers/contacts/DataRowHandlerForNickname.java
index 0fec6ee..95f24f5 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForNickname.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForNickname.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -25,6 +22,9 @@
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for nickname data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForNote.java b/src/com/android/providers/contacts/DataRowHandlerForNote.java
index 317af1a..ea73637 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForNote.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForNote.java
@@ -15,13 +15,13 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Note;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for note data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForOrganization.java b/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
index 7384ccb..44146e8 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
@@ -15,10 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -27,6 +23,10 @@
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.Data;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for organization data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
index 99313e9..da7d66c 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
@@ -15,11 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -28,6 +23,11 @@
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for phone number data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoto.java b/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
index 7560ed4..bfaa501 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -24,6 +22,8 @@
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.util.Log;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
import java.io.IOException;
/**
diff --git a/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java b/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
index c84d2e8..01ee1ba 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -26,6 +23,9 @@
import android.provider.ContactsContract.FullNameStyle;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for email address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java b/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
index 6898a43..26483ed 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -25,6 +22,9 @@
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for postal address data rows.
*/
diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java
index c13f4a8..fda8321 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -20,11 +20,6 @@
import static android.Manifest.permission.ADD_VOICEMAIL;
import static com.android.providers.contacts.Manifest.permission.READ_WRITE_ALL_VOICEMAIL;
-import com.android.common.io.MoreCloseables;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.DbQueryUtils;
-import com.google.android.collect.Lists;
-
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -43,6 +38,11 @@
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.common.io.MoreCloseables;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.DbQueryUtils;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
diff --git a/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java b/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
index 6777e43..fcda8f1 100644
--- a/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
+++ b/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
@@ -16,16 +16,15 @@
package com.android.providers.contacts;
+import android.content.ContentValues;
+import android.content.Context;
+import android.provider.CallLog.Calls;
+
import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
-import android.content.ContentValues;
-import android.content.Context;
-import android.provider.CallLog.Calls;
-import android.util.Log;
-
import java.util.Locale;
/**
diff --git a/src/com/android/providers/contacts/FastScrollingIndexCache.java b/src/com/android/providers/contacts/FastScrollingIndexCache.java
index c1c5602..f07a855 100644
--- a/src/com/android/providers/contacts/FastScrollingIndexCache.java
+++ b/src/com/android/providers/contacts/FastScrollingIndexCache.java
@@ -16,11 +16,9 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.Context;
import android.content.SharedPreferences;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
@@ -28,6 +26,9 @@
import android.text.TextUtils;
import android.util.Log;
+import com.google.android.collect.Maps;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.Map;
import java.util.regex.Pattern;
diff --git a/src/com/android/providers/contacts/LegacyApiSupport.java b/src/com/android/providers/contacts/LegacyApiSupport.java
index 78cbc9d..9859d11 100644
--- a/src/com/android/providers/contacts/LegacyApiSupport.java
+++ b/src/com/android/providers/contacts/LegacyApiSupport.java
@@ -15,19 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.ExtensionsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-
import android.accounts.Account;
import android.app.SearchManager;
import android.content.ContentUris;
@@ -65,6 +52,19 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.ExtensionsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+
import java.util.HashMap;
import java.util.Locale;
diff --git a/src/com/android/providers/contacts/NameLookupBuilder.java b/src/com/android/providers/contacts/NameLookupBuilder.java
index 5ebbcd1..8375b88 100644
--- a/src/com/android/providers/contacts/NameLookupBuilder.java
+++ b/src/com/android/providers/contacts/NameLookupBuilder.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
+import android.provider.ContactsContract.FullNameStyle;
+
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import android.provider.ContactsContract.FullNameStyle;
-
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
diff --git a/src/com/android/providers/contacts/NameNormalizer.java b/src/com/android/providers/contacts/NameNormalizer.java
index d91bd7c..c2b945e 100644
--- a/src/com/android/providers/contacts/NameNormalizer.java
+++ b/src/com/android/providers/contacts/NameNormalizer.java
@@ -17,10 +17,10 @@
import com.android.providers.contacts.util.Hex;
-import java.util.Locale;
-import java.text.Collator;
import java.text.CollationKey;
+import java.text.Collator;
import java.text.RuleBasedCollator;
+import java.util.Locale;
/**
* Converts a name to a normalized form by removing all non-letter characters and normalizing
diff --git a/src/com/android/providers/contacts/NameSplitter.java b/src/com/android/providers/contacts/NameSplitter.java
index fd5b096..43743ee 100644
--- a/src/com/android/providers/contacts/NameSplitter.java
+++ b/src/com/android/providers/contacts/NameSplitter.java
@@ -15,14 +15,14 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.util.NeededForTesting;
-
import android.content.ContentValues;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.FullNameStyle;
import android.provider.ContactsContract.PhoneticNameStyle;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;
+import com.android.providers.contacts.util.NeededForTesting;
+
import java.lang.Character.UnicodeBlock;
import java.util.HashSet;
import java.util.Locale;
diff --git a/src/com/android/providers/contacts/PhotoPriorityResolver.java b/src/com/android/providers/contacts/PhotoPriorityResolver.java
index c0dc4d9..150811c 100644
--- a/src/com/android/providers/contacts/PhotoPriorityResolver.java
+++ b/src/com/android/providers/contacts/PhotoPriorityResolver.java
@@ -16,22 +16,22 @@
package com.android.providers.contacts;
-import com.android.internal.util.XmlUtils;
-import com.google.android.collect.Maps;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
import android.content.res.XmlResourceParser;
import android.util.Log;
+import com.android.internal.util.XmlUtils;
+import com.google.android.collect.Maps;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/PhotoProcessor.java b/src/com/android/providers/contacts/PhotoProcessor.java
index cf81ff3..1b8fc3f 100644
--- a/src/com/android/providers/contacts/PhotoProcessor.java
+++ b/src/com/android/providers/contacts/PhotoProcessor.java
@@ -15,13 +15,18 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MemoryUtils;
-
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.SystemProperties;
+import com.android.providers.contacts.util.MemoryUtils;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -43,6 +48,12 @@
/** Compression for thumbnails that also have a display photo */
private static final int COMPRESSION_THUMBNAIL_LOW = 90;
+ private static final Paint WHITE_PAINT = new Paint();
+
+ static {
+ WHITE_PAINT.setColor(Color.WHITE);
+ }
+
private static int sMaxThumbnailDim;
private static int sMaxDisplayPhotoDim;
@@ -169,43 +180,65 @@
if (mOriginal == null) {
throw new IOException("Invalid image file");
}
- mDisplayPhoto = getScaledBitmap(mMaxDisplayPhotoDim);
- mThumbnailPhoto = getScaledBitmap(mMaxThumbnailPhotoDim);
+ mDisplayPhoto = getNormalizedBitmap(mOriginal, mMaxDisplayPhotoDim, mForceCropToSquare);
+ mThumbnailPhoto = getNormalizedBitmap(mOriginal,mMaxThumbnailPhotoDim, mForceCropToSquare);
}
/**
* Scales down the original bitmap to fit within the given maximum width and height.
* If the bitmap already fits in those dimensions, the original bitmap will be
* returned unmodified unless the photo processor is set up to crop it to a square.
+ *
+ * Also, if the image has transparency, conevrt it to white.
+ *
+ * @param original Original bitmap
* @param maxDim Maximum width and height (in pixels) for the image.
+ * @param forceCropToSquare See {@link #PhotoProcessor(Bitmap, int, int, boolean)}
* @return A bitmap that fits the maximum dimensions.
*/
@SuppressWarnings({"SuspiciousNameCombination"})
- private Bitmap getScaledBitmap(int maxDim) {
- Bitmap scaledBitmap = mOriginal;
- int width = mOriginal.getWidth();
- int height = mOriginal.getHeight();
+ @VisibleForTesting
+ static Bitmap getNormalizedBitmap(Bitmap original, int maxDim, boolean forceCropToSquare) {
+ final boolean originalHasAlpha = original.hasAlpha();
+
+ // All cropXxx's are in the original coordinate.
+ int cropWidth = original.getWidth();
+ int cropHeight = original.getHeight();
int cropLeft = 0;
int cropTop = 0;
- if (mForceCropToSquare && width != height) {
+ if (forceCropToSquare && cropWidth != cropHeight) {
// Crop the image to the square at its center.
- if (height > width) {
- cropTop = (height - width) / 2;
- height = width;
+ if (cropHeight > cropWidth) {
+ cropTop = (cropHeight - cropWidth) / 2;
+ cropHeight = cropWidth;
} else {
- cropLeft = (width - height) / 2;
- width = height;
+ cropLeft = (cropWidth - cropHeight) / 2;
+ cropWidth = cropHeight;
}
}
- float scaleFactor = ((float) maxDim) / Math.max(width, height);
- if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0) {
- // Need to scale or crop the photo.
- Matrix matrix = new Matrix();
- if (scaleFactor < 1.0f) matrix.setScale(scaleFactor, scaleFactor);
- scaledBitmap = Bitmap.createBitmap(
- mOriginal, cropLeft, cropTop, width, height, matrix, true);
+ // Calculate the scale factor. We don't want to scale up, so the max scale is 1f.
+ final float scaleFactor = Math.min(1f, ((float) maxDim) / Math.max(cropWidth, cropHeight));
+
+ if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0 || originalHasAlpha) {
+ final int newWidth = (int) (cropWidth * scaleFactor);
+ final int newHeight = (int) (cropHeight * scaleFactor);
+ final Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight,
+ Bitmap.Config.ARGB_8888);
+ final Canvas c = new Canvas(scaledBitmap);
+
+ if (originalHasAlpha) {
+ c.drawRect(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), WHITE_PAINT);
+ }
+
+ final Rect src = new Rect(cropLeft, cropTop,
+ cropLeft + cropWidth, cropTop + cropHeight);
+ final RectF dst = new RectF(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight());
+
+ c.drawBitmap(original, src, dst, null);
+ return scaledBitmap;
+ } else {
+ return original;
}
- return scaledBitmap;
}
/**
diff --git a/src/com/android/providers/contacts/PhotoStore.java b/src/com/android/providers/contacts/PhotoStore.java
index e0b5fb4..e7be48c 100644
--- a/src/com/android/providers/contacts/PhotoStore.java
+++ b/src/com/android/providers/contacts/PhotoStore.java
@@ -15,17 +15,16 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.provider.ContactsContract.PhotoFiles;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
diff --git a/src/com/android/providers/contacts/ProfileAwareUriMatcher.java b/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
index de5cce1..051c60e 100644
--- a/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
+++ b/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
import android.content.UriMatcher;
import android.net.Uri;
import android.provider.ContactsContract;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
diff --git a/src/com/android/providers/contacts/ProfileDatabaseHelper.java b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
index 9b707a3..a23e521 100644
--- a/src/com/android/providers/contacts/ProfileDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.NeededForTesting;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.Profile;
+import com.android.providers.contacts.util.NeededForTesting;
+
/**
* A separate version of the contacts database helper for storing the user's profile data.
*/
diff --git a/src/com/android/providers/contacts/ProfileProvider.java b/src/com/android/providers/contacts/ProfileProvider.java
index d97760d..ba10e8b 100644
--- a/src/com/android/providers/contacts/ProfileProvider.java
+++ b/src/com/android/providers/contacts/ProfileProvider.java
@@ -81,7 +81,6 @@
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder, CancellationSignal cancellationSignal) {
enforceReadPermission(uri);
- mDelegate.substituteDb(getDatabaseHelper().getReadableDatabase());
return mDelegate.queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1,
cancellationSignal);
}
@@ -112,10 +111,8 @@
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
if (mode != null && mode.contains("w")) {
enforceWritePermission();
- mDelegate.substituteDb(getDatabaseHelper().getWritableDatabase());
} else {
enforceReadPermission(uri);
- mDelegate.substituteDb(getDatabaseHelper().getReadableDatabase());
}
return mDelegate.openAssetFileLocal(uri, mode);
}
@@ -124,7 +121,6 @@
ContactsTransaction transaction = getCurrentTransaction();
SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
transaction.startTransactionForDb(db, ContactsProvider2.PROFILE_DB_TAG, this);
- mDelegate.substituteDb(db);
}
@Override
@@ -142,20 +138,17 @@
@Override
public void onBegin() {
- mDelegate.switchToProfileMode();
- mDelegate.onBegin();
+ mDelegate.onBeginTransactionInternal(true);
}
@Override
public void onCommit() {
- mDelegate.switchToProfileMode();
- mDelegate.onCommit();
+ mDelegate.onCommitTransactionInternal(true);
}
@Override
public void onRollback() {
- mDelegate.switchToProfileMode();
- mDelegate.onRollback();
+ mDelegate.onRollbackTransactionInternal(true);
}
@Override
@@ -167,4 +160,10 @@
public String getType(Uri uri) {
return mDelegate.getType(uri);
}
+
+ /** Use only for debug logging */
+ @Override
+ public String toString() {
+ return "ProfileProvider";
+ }
}
diff --git a/src/com/android/providers/contacts/SearchIndexManager.java b/src/com/android/providers/contacts/SearchIndexManager.java
index bd4e1cc..361b5d8 100644
--- a/src/com/android/providers/contacts/SearchIndexManager.java
+++ b/src/com/android/providers/contacts/SearchIndexManager.java
@@ -15,14 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.google.android.collect.Lists;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -37,6 +29,14 @@
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.android.collect.Lists;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
diff --git a/src/com/android/providers/contacts/VoicemailCleanupService.java b/src/com/android/providers/contacts/VoicemailCleanupService.java
index 39f5be5..4ad1406 100644
--- a/src/com/android/providers/contacts/VoicemailCleanupService.java
+++ b/src/com/android/providers/contacts/VoicemailCleanupService.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.google.common.annotations.VisibleForTesting;
-
import android.app.IntentService;
import android.content.ContentResolver;
import android.content.Intent;
@@ -25,6 +23,8 @@
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.google.common.annotations.VisibleForTesting;
+
/**
* A service that cleans up voicemail related data for packages that are uninstalled.
*/
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index 79d8f92..b2f6b1e 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -19,11 +19,6 @@
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.SelectionBuilder;
-import com.android.providers.contacts.util.TypedUriMatcherImpl;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
@@ -38,6 +33,11 @@
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.SelectionBuilder;
+import com.android.providers.contacts.util.TypedUriMatcherImpl;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.FileNotFoundException;
import java.util.List;
diff --git a/src/com/android/providers/contacts/VoicemailContentTable.java b/src/com/android/providers/contacts/VoicemailContentTable.java
index 3b72653..3f00b26 100644
--- a/src/com/android/providers/contacts/VoicemailContentTable.java
+++ b/src/com/android/providers/contacts/VoicemailContentTable.java
@@ -19,10 +19,6 @@
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-import com.android.providers.contacts.util.CloseUtils;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -38,6 +34,10 @@
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+import com.android.providers.contacts.util.CloseUtils;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/src/com/android/providers/contacts/VoicemailStatusTable.java b/src/com/android/providers/contacts/VoicemailStatusTable.java
index a0a61ba..2c1861b 100644
--- a/src/com/android/providers/contacts/VoicemailStatusTable.java
+++ b/src/com/android/providers/contacts/VoicemailStatusTable.java
@@ -18,9 +18,6 @@
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -32,6 +29,9 @@
import android.os.ParcelFileDescriptor;
import android.provider.VoicemailContract.Status;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+
/**
* Implementation of {@link VoicemailTable.Delegate} for the voicemail status table.
*/
diff --git a/src/com/android/providers/contacts/VoicemailTable.java b/src/com/android/providers/contacts/VoicemailTable.java
index db35c98..9e6c431 100644
--- a/src/com/android/providers/contacts/VoicemailTable.java
+++ b/src/com/android/providers/contacts/VoicemailTable.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+
import java.io.FileNotFoundException;
/**
diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator.java b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
index d3931e6..baae2e5 100644
--- a/src/com/android/providers/contacts/aggregation/ContactAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
@@ -16,6 +16,29 @@
package com.android.providers.contacts.aggregation;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.provider.ContactsContract.AggregationExceptions;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Identity;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Contacts.AggregationSuggestions;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.FullNameStyle;
+import android.provider.ContactsContract.PhotoFiles;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StatusUpdates;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.Log;
+
import com.android.providers.contacts.ContactLookupKey;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
@@ -42,29 +65,6 @@
import com.android.providers.contacts.aggregation.util.ContactMatcher.MatchScore;
import com.google.android.collect.Maps;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.database.sqlite.SQLiteStatement;
-import android.net.Uri;
-import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Identity;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Contacts.AggregationSuggestions;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.FullNameStyle;
-import android.provider.ContactsContract.PhotoFiles;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.StatusUpdates;
-import android.text.TextUtils;
-import android.util.EventLog;
-import android.util.Log;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
index fedf5fe..276a05f 100644
--- a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
@@ -23,11 +23,11 @@
import com.android.providers.contacts.ContactLookupKey;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.NameSplitter;
import com.android.providers.contacts.PhotoPriorityResolver;
import com.android.providers.contacts.TransactionContext;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
/**
* A version of the ContactAggregator for use against the profile database.
diff --git a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
index d6b799f..9643d81 100644
--- a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
+++ b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts.aggregation.util;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
import com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.google.android.collect.Maps;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-
import java.lang.ref.SoftReference;
import java.util.BitSet;
import java.util.HashMap;
diff --git a/tests/res/drawable-nodpi/transparent_10x10.png b/tests/res/drawable-nodpi/transparent_10x10.png
new file mode 100644
index 0000000..d11c2cd
--- /dev/null
+++ b/tests/res/drawable-nodpi/transparent_10x10.png
Binary files differ
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 1154186..3759196 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -18,11 +18,6 @@
import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.Hex;
-import com.android.providers.contacts.util.MockClock;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -62,6 +57,11 @@
import android.test.mock.MockContentResolver;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.Hex;
+import com.android.providers.contacts.util.MockClock;
+import com.google.android.collect.Sets;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
diff --git a/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java b/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
index 0ce9bca..4c0d2df 100644
--- a/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
+++ b/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.internal.telephony.CallerInfo;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.net.Uri;
import android.provider.ContactsContract.RawContacts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.internal.telephony.CallerInfo;
+
/**
* Integration test for {@link CallerInfo} and {@link ContactsProvider2}.
*
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
index f1ff776..96cbb9b 100644
--- a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
@@ -16,9 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
@@ -39,6 +36,9 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.google.android.collect.Lists;
+
/**
* Unit tests for {@link ContactDirectoryManager}. Run the test like this:
*
diff --git a/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java b/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
index 739b2cb..08f3a07 100644
--- a/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
+++ b/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
-
import android.content.ContentUris;
import android.net.Uri;
import android.provider.ContactsContract.AggregationExceptions;
@@ -25,6 +23,8 @@
import android.provider.ContactsContract.RawContacts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
+
import java.util.ArrayList;
/**
diff --git a/tests/src/com/android/providers/contacts/ContactsActor.java b/tests/src/com/android/providers/contacts/ContactsActor.java
index 038eb97..e75c52e 100644
--- a/tests/src/com/android/providers/contacts/ContactsActor.java
+++ b/tests/src/com/android/providers/contacts/ContactsActor.java
@@ -16,9 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MockSharedPreferences;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
@@ -59,6 +56,9 @@
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
+import com.android.providers.contacts.util.MockSharedPreferences;
+import com.google.android.collect.Sets;
+
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
diff --git a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
index a9d8a36..faddeea 100644
--- a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.google.android.collect.Sets;
-import android.test.suitebuilder.annotation.SmallTest;
-
import java.util.Set;
@SmallTest
diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
index 69cd9fa..694f0f3 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -26,6 +24,8 @@
import android.os.Binder;
import android.test.mock.MockPackageManager;
+import com.google.android.collect.Lists;
+
import java.util.HashMap;
import java.util.List;
diff --git a/tests/src/com/android/providers/contacts/ContactsMockResources.java b/tests/src/com/android/providers/contacts/ContactsMockResources.java
index 248d6da..6d98665 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockResources.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockResources.java
@@ -16,10 +16,10 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-
import android.test.mock.MockResources;
+import com.google.android.collect.Maps;
+
import java.util.Map;
final class ContactsMockResources extends MockResources {
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index 5706925..80e194d 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -18,16 +18,6 @@
import static com.android.providers.contacts.TestUtils.cv;
-import com.android.internal.util.ArrayUtils;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.tests.R;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -76,6 +66,16 @@
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
+import com.android.internal.util.ArrayUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.tests.R;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -5756,7 +5756,7 @@
PhotoStore profilePhotoStore = provider.getProfilePhotoStore();
// Trigger an initial cleanup so another one won't happen while we're running this test.
- provider.switchToProfileMode();
+ provider.switchToProfileModeForTest();
provider.cleanupPhotoStore();
// Create the profile contact and add a photo.
@@ -5787,7 +5787,7 @@
profilePhotoStore.remove(streamItemPhotoFileId);
// Manually trigger another cleanup in the provider.
- provider.switchToProfileMode();
+ provider.switchToProfileModeForTest();
provider.cleanupPhotoStore();
// The following things should have happened.
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
new file mode 100644
index 0000000..6a82bf9
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2012 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.providers.contacts;
+
+import static com.android.providers.contacts.TestUtils.cv;
+
+import com.google.android.collect.Lists;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentValues;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Profile;
+import android.provider.ContactsContract.RawContacts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Tests to make sure we're handling DB transactions properly in regard to two databases,
+ * the profile db and the contacts db.
+ */
+@LargeTest
+public class ContactsProvider2TransactionTest extends BaseContactsProvider2Test {
+ private SynchronousContactsProvider2 mProvider;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mProvider = (SynchronousContactsProvider2) getProvider();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ mProvider = null;
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for insert.
+ */
+ public void testTransactionCallback_insert() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Insert a raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Insert a profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for update.
+ */
+ public void testTransactionCallback_update() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Make sure to create a raw contact and a profile raw contact.
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ values.clear();
+ values.put(RawContacts.LAST_TIME_CONTACTED, 99999);
+
+ // Update all raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.update(RawContacts.CONTENT_URI, values, null, null) > 0);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Update all profile raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.update(Profile.CONTENT_RAW_CONTACTS_URI, values, null, null) > 0);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for delete.
+ */
+ public void testTransactionCallback_delete() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Make sure to create a raw contact and a profile raw contact.
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ // Delete all raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.delete(RawContacts.CONTENT_URI, null, null) > 0);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+ // Delete all profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.delete(Profile.CONTENT_RAW_CONTACTS_URI, null, null) > 0);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+ /**
+ * Make sure we start/finish transactions on the right databases for bulk insert.
+ */
+ public void testTransactionCallback_bulkInsert() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Insert a raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.bulkInsert(RawContacts.CONTENT_URI, new ContentValues[] {values});
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Insert a profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.bulkInsert(Profile.CONTENT_RAW_CONTACTS_URI, new ContentValues[] {values});
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Add an operation to create a raw contact.
+ */
+ private static void addInsertContactOperations(ArrayList<ContentProviderOperation> ops) {
+ ContentProviderOperation.Builder b;
+ b = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
+ b.withValue(RawContacts.STARRED, 1);
+ b.withValue(RawContacts.TIMES_CONTACTED, 200001);
+ ops.add(b.build());
+
+ b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
+ b.withValue(StructuredName.DISPLAY_NAME, "Regular Contact");
+ b.withValue(StructuredName.GIVEN_NAME, "Regular");
+ b.withValue(StructuredName.FAMILY_NAME, "Contact");
+ b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ ops.add(b.build());
+ }
+
+ /**
+ * Check for a contact created that'll be created for {@link #addInsertContactOperations}.
+ */
+ private void checkStoredContact() {
+ assertStoredValues(Contacts.CONTENT_URI, cv(
+ Contacts.DISPLAY_NAME, "Regular Contact",
+ RawContacts.TIMES_CONTACTED, 200001
+ ));
+ }
+
+ /**
+ * Add an operation to create a profile raw contact.
+ */
+ private static void addInsertProfileOperations(ArrayList<ContentProviderOperation> ops) {
+ ContentProviderOperation.Builder b;
+ b = ContentProviderOperation.newInsert(Profile.CONTENT_RAW_CONTACTS_URI);
+ b.withValue(RawContacts.STARRED, 1);
+ b.withValue(RawContacts.TIMES_CONTACTED, 100001);
+ ops.add(b.build());
+
+ b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
+ b.withValue(StructuredName.DISPLAY_NAME, "Profile Contact");
+ b.withValue(StructuredName.GIVEN_NAME, "Profile");
+ b.withValue(StructuredName.FAMILY_NAME, "Contact");
+ b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ ops.add(b.build());
+ }
+
+ /**
+ * Check for a profile contact created that'll be created for
+ * {@link #addInsertProfileOperations}.
+ */
+ private void checkStoredProfile() {
+ assertStoredValues(Profile.CONTENT_URI, cv(
+ Contacts.DISPLAY_NAME, "Profile Contact",
+ RawContacts.TIMES_CONTACTED, 100001
+ ));
+ }
+
+ public void testTransactionCallback_contactBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ addInsertContactOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+ checkStoredContact();
+ }
+
+ public void testTransactionCallback_profileBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ addInsertProfileOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ }
+
+ public void testTransactionCallback_mixedBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ // Create a raw contact and a profile raw contact in a single batch.
+
+ addInsertContactOperations(ops);
+ addInsertProfileOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ checkStoredContact();
+ }
+
+ public void testTransactionCallback_mixedBatchReversed() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ // Create a profile raw contact and a raw contact in a single batch.
+
+ addInsertProfileOperations(ops);
+ addInsertContactOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ checkStoredContact();
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/DirectoryTest.java b/tests/src/com/android/providers/contacts/DirectoryTest.java
index e9592c1..c62824b 100644
--- a/tests/src/com/android/providers/contacts/DirectoryTest.java
+++ b/tests/src/com/android/providers/contacts/DirectoryTest.java
@@ -26,7 +26,7 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
-import android.test.suitebuilder.annotation.MediumTest;;
+import android.test.suitebuilder.annotation.MediumTest;
/**
diff --git a/tests/src/com/android/providers/contacts/EvenMoreAsserts.java b/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
index c73128a..1fc15f2 100644
--- a/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
+++ b/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
@@ -16,19 +16,19 @@
package com.android.providers.contacts;
-import com.google.android.collect.Sets;
-
import android.content.Context;
import android.graphics.BitmapFactory;
+import com.google.android.collect.Sets;
+
+import junit.framework.Assert;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Set;
-import junit.framework.Assert;
-
/**
* Contains additional assertion methods not found in Junit or MoreAsserts.
*/
diff --git a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
index 7ca2a87..281834f 100644
--- a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
+++ b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MockSharedPreferences;
-
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.ContactCounts;
@@ -27,6 +25,8 @@
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.providers.contacts.util.MockSharedPreferences;
+
@SmallTest
public class FastScrollingIndexCacheTest extends AndroidTestCase {
private MockSharedPreferences mPrefs;
diff --git a/tests/src/com/android/providers/contacts/GroupsTest.java b/tests/src/com/android/providers/contacts/GroupsTest.java
index 3d85064..15cfc71 100644
--- a/tests/src/com/android/providers/contacts/GroupsTest.java
+++ b/tests/src/com/android/providers/contacts/GroupsTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentUris;
@@ -32,9 +30,10 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.Settings;
-import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
/**
diff --git a/tests/src/com/android/providers/contacts/HanziToPinyinTest.java b/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
index 7ffb855..d1433ce 100644
--- a/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
+++ b/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
@@ -16,17 +16,17 @@
package com.android.providers.contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.providers.contacts.HanziToPinyin.Token;
-import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
-import junit.framework.TestCase;
-
@SmallTest
public class HanziToPinyinTest extends TestCase {
private final static String ONE_HANZI = "\u675C";
diff --git a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
index e515af2..c752e4e 100644
--- a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
+++ b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.tests.*;
-
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
diff --git a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
index a5cff7a..a54193e 100644
--- a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
+++ b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
@@ -19,12 +19,12 @@
import android.provider.ContactsContract.FullNameStyle;
import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
-import junit.framework.TestCase;
-
/**
* Unit tests for {@link NameLookupBuilder}.
*
diff --git a/tests/src/com/android/providers/contacts/NameSplitterTest.java b/tests/src/com/android/providers/contacts/NameSplitterTest.java
index 785fb01..d9007fc 100644
--- a/tests/src/com/android/providers/contacts/NameSplitterTest.java
+++ b/tests/src/com/android/providers/contacts/NameSplitterTest.java
@@ -16,16 +16,16 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.NameSplitter.Name;
-
import android.provider.ContactsContract.FullNameStyle;
import android.provider.ContactsContract.PhoneticNameStyle;
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.NameSplitter.Name;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link NameSplitter}.
*
diff --git a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
index 20058ad..4b159a8 100644
--- a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
+++ b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
@@ -16,12 +16,12 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-
import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.google.android.collect.Maps;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/src/com/android/providers/contacts/PhotoProcessorTest.java b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
new file mode 100644
index 0000000..3d882d5
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 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.providers.contacts;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+
+import com.android.providers.contacts.tests.R;
+
+
+/**
+ * Tests for {@link PhotoProcessor}.
+ *
+ * Most of tests are covered by {@link PhotoStoreTest}.
+ */
+public class PhotoProcessorTest extends AndroidTestCase {
+
+ public void testTransparency() {
+ final Drawable source = getTestContext().getResources().getDrawable(
+ R.drawable.transparent_10x10);
+ final Bitmap sourceBitmap = ((BitmapDrawable) source).getBitmap();
+
+ final Bitmap normalized = PhotoProcessor.getNormalizedBitmap(sourceBitmap, 50, false);
+
+ // Make sure it's not scaled up.
+ assertEquals(10, normalized.getWidth());
+ assertEquals(10, normalized.getHeight());
+
+ // Make sure the transparent pixel is now 100% white.
+ assertEquals(Color.argb(255, 255, 255, 255), normalized.getPixel(0, 0));
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/PhotoStoreTest.java b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
index 1550d0b..4e797f7 100644
--- a/tests/src/com/android/providers/contacts/PhotoStoreTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
@@ -16,9 +16,7 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.tests.R;
-import com.android.providers.contacts.util.Hex;
+import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -26,17 +24,17 @@
import android.provider.ContactsContract.PhotoFiles;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.tests.R;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-
/**
* Tests for {@link PhotoStore}.
*/
@@ -81,7 +79,7 @@
public void testStoreNonSquare300x200Photo() throws IOException {
// The longer side should be downscaled to the target size
- runStorageTestForResource(R.drawable.earth_300x200, 256, 171);
+ runStorageTestForResource(R.drawable.earth_300x200, 256, 170);
}
public void testStoreNonSquare300x200PhotoWithCrop() throws IOException {
diff --git a/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java b/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
index b4be173..eba9d53 100644
--- a/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
+++ b/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.PostalSplitter.Postal;
-
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.PostalSplitter.Postal;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link PostalSplitter}, especially for ja_JP locale.
* This class depends on the assumption that all the tests in {@link NameSplitterTest} pass.
diff --git a/tests/src/com/android/providers/contacts/PostalSplitterTest.java b/tests/src/com/android/providers/contacts/PostalSplitterTest.java
index 6778b79..d12b3f3 100644
--- a/tests/src/com/android/providers/contacts/PostalSplitterTest.java
+++ b/tests/src/com/android/providers/contacts/PostalSplitterTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.PostalSplitter.Postal;
-
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.PostalSplitter.Postal;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link PostalSplitter}, especially for en_US locale.
*
diff --git a/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java b/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
index f4b8bab..7b3fe95 100644
--- a/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
+++ b/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
@@ -27,8 +27,6 @@
import android.provider.ContactsContract.Contacts;
import android.test.suitebuilder.annotation.MediumTest;
-import junit.framework.Assert;
-
/**
* Unit tests for {@link ContactsProvider2}, to make sure the queries don't allow sql injection.
*
diff --git a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
index 3d28ad1..1d127c7 100644
--- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
+++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
@@ -19,6 +19,9 @@
import android.accounts.Account;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
+import android.util.Log;
+
+import junit.framework.Assert;
import java.util.Locale;
@@ -46,7 +49,7 @@
}
@Override
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new SynchronousProfileProvider(this);
}
@@ -202,6 +205,7 @@
@Override
public void wipeData() {
+ Log.i(TAG, "wipeData");
super.wipeData();
SQLiteDatabase db = getDatabaseHelper(getContext()).getWritableDatabase();
db.execSQL("replace into SQLITE_SEQUENCE (name,seq) values('raw_contacts', 42)");
@@ -210,4 +214,84 @@
getContactDirectoryManagerForTest().scanAllPackages();
}
+
+ // Flags to remember which transaction callback has been called for which mode.
+ private boolean mOnBeginTransactionInternalCalledInProfileMode;
+ private boolean mOnCommitTransactionInternalCalledInProfileMode;
+ private boolean mOnRollbackTransactionInternalCalledInProfileMode;
+
+ private boolean mOnBeginTransactionInternalCalledInContactMode;
+ private boolean mOnCommitTransactionInternalCalledInContactMode;
+ private boolean mOnRollbackTransactionInternalCalledInContactMode;
+
+ public void resetTrasactionCallbackCalledFlags() {
+ mOnBeginTransactionInternalCalledInProfileMode = false;
+ mOnCommitTransactionInternalCalledInProfileMode = false;
+ mOnRollbackTransactionInternalCalledInProfileMode = false;
+
+ mOnBeginTransactionInternalCalledInContactMode = false;
+ mOnCommitTransactionInternalCalledInContactMode = false;
+ mOnRollbackTransactionInternalCalledInContactMode = false;
+ }
+
+ @Override
+ protected void onBeginTransactionInternal(boolean forProfile) {
+ super.onBeginTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnBeginTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnBeginTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ @Override
+ protected void onCommitTransactionInternal(boolean forProfile) {
+ super.onCommitTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnCommitTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnCommitTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ @Override
+ protected void onRollbackTransactionInternal(boolean forProfile) {
+ super.onRollbackTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnRollbackTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnRollbackTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ public void assertCommitTransactionCalledForProfileMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+ public void assertRollbackTransactionCalledForProfileMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+ public void assertNoTransactionsForProfileMode() {
+ Assert.assertFalse("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+
+ public void assertCommitTransactionCalledForContactMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode);
+ Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInContactMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInContactMode);
+ }
+
+ public void assertRollbackTransactionCalledForContactMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInContactMode);
+ Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInContactMode);
+ }
}
diff --git a/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java b/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
index 93ad70f..308e67a 100644
--- a/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
+++ b/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
@@ -16,7 +16,6 @@
package com.android.providers.contacts;
-import android.accounts.Account;
import android.content.Context;
import java.util.Locale;
diff --git a/tests/src/com/android/providers/contacts/TestUtils.java b/tests/src/com/android/providers/contacts/TestUtils.java
index 00789bf..b6d6a27 100644
--- a/tests/src/com/android/providers/contacts/TestUtils.java
+++ b/tests/src/com/android/providers/contacts/TestUtils.java
@@ -21,12 +21,12 @@
import android.database.Cursor;
import android.util.Log;
+import junit.framework.Assert;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import junit.framework.Assert;
-
public class TestUtils {
private TestUtils() {
}
diff --git a/tests/src/com/android/providers/contacts/VCardTest.java b/tests/src/com/android/providers/contacts/VCardTest.java
index b022ebd..820c263 100644
--- a/tests/src/com/android/providers/contacts/VCardTest.java
+++ b/tests/src/com/android/providers/contacts/VCardTest.java
@@ -16,12 +16,12 @@
package com.android.providers.contacts;
-import com.android.vcard.VCardComposer;
-import com.android.vcard.VCardConfig;
-
import android.content.ContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.vcard.VCardComposer;
+import com.android.vcard.VCardConfig;
+
/**
* Tests (or integration tests) verifying if vCard library works well with {@link ContentResolver}.
*
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index 74195b5..8fdbccf 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.io.MoreCloseables;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
@@ -30,6 +28,8 @@
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.common.io.MoreCloseables;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
index 795ea9c..16d06c8 100644
--- a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
@@ -16,25 +16,15 @@
package com.android.providers.contacts.aggregation;
-import com.android.providers.contacts.BaseContactsProvider2Test;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsProvider2;
-import com.android.providers.contacts.TestUtils;
-import com.android.providers.contacts.tests.R;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
-import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
@@ -46,6 +36,11 @@
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.BaseContactsProvider2Test;
+import com.android.providers.contacts.TestUtils;
+import com.android.providers.contacts.tests.R;
+import com.google.android.collect.Lists;
+
/**
* Unit tests for {@link ContactAggregator}.
*
diff --git a/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
index 7f9f053..b833220 100644
--- a/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
@@ -16,12 +16,11 @@
package com.android.providers.contacts.aggregation.util;
-import com.android.providers.contacts.NameNormalizer;
-import com.android.providers.contacts.aggregation.util.NameDistance;
-import com.android.providers.contacts.util.Hex;
-
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.providers.contacts.NameNormalizer;
+import com.android.providers.contacts.util.Hex;
+
import junit.framework.TestCase;
/**
diff --git a/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java b/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
index 43f7c06..7769b49 100644
--- a/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
@@ -19,13 +19,13 @@
import static com.android.providers.contacts.util.DbQueryUtils.checkForSupportedColumns;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.EvenMoreAsserts;
-
import android.content.ContentValues;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.EvenMoreAsserts;
+
/**
* Unit tests for the {@link DbQueryUtils} class.
* Run the test like this:
diff --git a/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java b/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
index d00e711..574ce19 100644
--- a/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
+++ b/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
@@ -16,10 +16,10 @@
package com.android.providers.contacts.util;
-import com.google.android.collect.Maps;
-
import android.content.SharedPreferences;
+import com.google.android.collect.Maps;
+
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
diff --git a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
index 48bd608..329e6e2 100644
--- a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
+++ b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
@@ -20,9 +20,6 @@
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.providers.contacts.util.TypedUriMatcherImpl;
-import com.android.providers.contacts.util.UriType;
-
/**
* Unit tests for {@link TypedUriMatcherImpl}.
* Run the test like this: