Preventing contacts from joining with Directory entries
Also, moving interactions with PackageManager to the bg thread
Also, skipping a trip to the DB when all we want is the default directories
Change-Id: I3813074af2a01d23d0e90cc2f7905ad1691117a3
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3c8cd18..cfd3ec9 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1244,4 +1244,7 @@
<!-- Text in the editor to show the structured editor -->
<string name="edit_structured_editor_button">...</string>
+
+ <!-- The name of the invisible local contact directory -->
+ <string name="local_invisible_directory">Other</string>
</resources>
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 037c670..74a7a13 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -220,6 +220,7 @@
fragment.setSearchMode(mRequest.isSearchMode());
fragment.setSearchResultsMode(mRequest.isSearchResultsMode());
fragment.setQueryString(mRequest.getQueryString());
+ fragment.setDirectorySearchEnabled(mRequest.isDirectorySearchEnabled());
mListFragment = fragment;
break;
}
@@ -280,6 +281,7 @@
fragment.setLegacyCompatibilityMode(mRequest.isLegacyCompatibilityMode());
fragment.setSearchMode(mRequest.isSearchMode());
fragment.setQueryString(mRequest.getQueryString());
+ fragment.setDirectorySearchEnabled(mRequest.isDirectorySearchEnabled());
fragment.setShortcutRequested(true);
mListFragment = fragment;
break;
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
index b99c0d1..3f42f50 100644
--- a/src/com/android/contacts/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -23,14 +23,11 @@
import android.content.Context;
import android.content.CursorLoader;
-import android.content.pm.PackageManager;
import android.database.Cursor;
-import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.ContactCounts;
import android.provider.ContactsContract.Directory;
import android.text.TextUtils;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -46,23 +43,6 @@
private static final String TAG = "ContactEntryListAdapter";
- private static final class DirectoryQuery {
- public static final Uri URI = Directory.CONTENT_URI;
- public static final String ORDER_BY = Directory._ID;
-
- public static final String[] PROJECTION = {
- Directory._ID,
- Directory.PACKAGE_NAME,
- Directory.TYPE_RESOURCE_ID,
- Directory.DISPLAY_NAME,
- };
-
- public static final int ID = 0;
- public static final int PACKAGE_NAME = 1;
- public static final int TYPE_RESOURCE_ID = 2;
- public static final int DISPLAY_NAME = 3;
- }
-
/**
* The animation is used here to allocate animated name text views.
*/
@@ -77,6 +57,7 @@
private String mQueryString;
private boolean mSearchMode;
private boolean mSearchResultsMode;
+ private boolean mDirectorySearchEnabled;
private boolean mLoading = true;
private boolean mEmptyListEnabled = true;
@@ -159,6 +140,14 @@
mQueryString = queryString;
}
+ public boolean isDirectorySearchEnabled() {
+ return mDirectorySearchEnabled;
+ }
+
+ public void setDirectorySearchEnabled(boolean flag) {
+ mDirectorySearchEnabled = flag;
+ }
+
public int getContactNameDisplayOrder() {
return mDisplayOrder;
}
@@ -215,10 +204,8 @@
mEmptyListEnabled = flag;
}
- public void configureDirectoryLoader(CursorLoader loader) {
- loader.setUri(DirectoryQuery.URI);
- loader.setProjection(DirectoryQuery.PROJECTION);
- loader.setSortOrder(DirectoryQuery.ORDER_BY);
+ public void configureDirectoryLoader(DirectoryListLoader loader) {
+ loader.setDirectorySearchEnabled(mDirectorySearchEnabled);
}
/**
@@ -228,14 +215,21 @@
public void changeDirectories(Cursor cursor) {
HashSet<Long> directoryIds = new HashSet<Long>();
+ int idColumnIndex = cursor.getColumnIndex(Directory._ID);
+ int directoryTypeColumnIndex = cursor.getColumnIndex(DirectoryListLoader.DIRECTORY_TYPE);
+ int displayNameColumnIndex = cursor.getColumnIndex(Directory.DISPLAY_NAME);
+
// TODO preserve the order of partition to match those of the cursor
// Phase I: add new directories
try {
while (cursor.moveToNext()) {
- long id = cursor.getLong(DirectoryQuery.ID);
+ long id = cursor.getLong(idColumnIndex);
directoryIds.add(id);
if (getPartitionByDirectoryId(id) == -1) {
- DirectoryPartition partition = createDirectoryPartition(cursor);
+ DirectoryPartition partition = new DirectoryPartition(false, true);
+ partition.setDirectoryId(id);
+ partition.setDirectoryType(cursor.getString(directoryTypeColumnIndex));
+ partition.setDisplayName(cursor.getString(displayNameColumnIndex));
addPartition(partition);
}
}
@@ -259,25 +253,6 @@
notifyDataSetChanged();
}
- private DirectoryPartition createDirectoryPartition(Cursor cursor) {
- PackageManager pm = getContext().getPackageManager();
- DirectoryPartition partition = new DirectoryPartition(false, true);
- partition.setDirectoryId(cursor.getLong(DirectoryQuery.ID));
- String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME);
- int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID);
- if (!TextUtils.isEmpty(packageName) && typeResourceId != 0) {
- // TODO: should this be done on a background thread?
- try {
- partition.setDirectoryType(pm.getResourcesForApplication(packageName)
- .getString(typeResourceId));
- } catch (Exception e) {
- Log.e(TAG, "Cannot obtain directory type from package: " + packageName);
- }
- }
- partition.setDisplayName(cursor.getString(DirectoryQuery.DISPLAY_NAME));
- return partition;
- }
-
@Override
public void changeCursor(int partitionIndex, Cursor cursor) {
Partition partition = getPartition(partitionIndex);
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index b111e12..9e208bc 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -89,6 +89,7 @@
private boolean mSearchResultsMode;
private boolean mAizyEnabled;
private String mQueryString;
+ private boolean mDirectorySearchEnabled;
private T mAdapter;
private View mView;
@@ -210,16 +211,18 @@
@Override
protected Loader<Cursor> onCreateLoader(int id, Bundle args) {
- CursorLoader loader = new CursorLoader(getActivity(), null, null, null, null, null);
if (id == DIRECTORY_LOADER_ID) {
+ DirectoryListLoader loader = new DirectoryListLoader(getActivity());
mAdapter.configureDirectoryLoader(loader);
+ return loader;
} else {
+ CursorLoader loader = new CursorLoader(getActivity(), null, null, null, null, null);
long directoryId = args != null && args.containsKey(DIRECTORY_ID_ARG_KEY)
? args.getLong(DIRECTORY_ID_ARG_KEY)
: Directory.DEFAULT;
mAdapter.configureLoader(loader, directoryId);
+ return loader;
}
- return loader;
}
private void startLoadingDirectoryPartition(int partitionIndex) {
@@ -408,6 +411,14 @@
}
}
+ public boolean isDirectorySearchEnabled() {
+ return mDirectorySearchEnabled;
+ }
+
+ public void setDirectorySearchEnabled(boolean flag) {
+ mDirectorySearchEnabled = flag;
+ }
+
public boolean isLegacyCompatibilityMode() {
return mLegacyCompatibility;
}
@@ -559,6 +570,7 @@
}
mAdapter.setQueryString(mQueryString);
+ mAdapter.setDirectorySearchEnabled(mDirectorySearchEnabled);
mAdapter.setPinnedPartitionHeadersEnabled(mSearchMode);
mAdapter.setContactNameDisplayOrder(mDisplayOrder);
mAdapter.setSortOrder(mSortOrder);
diff --git a/src/com/android/contacts/list/ContactsRequest.java b/src/com/android/contacts/list/ContactsRequest.java
index 6f2e2e4..5bda8e2 100644
--- a/src/com/android/contacts/list/ContactsRequest.java
+++ b/src/com/android/contacts/list/ContactsRequest.java
@@ -80,6 +80,7 @@
private boolean mDisplayOnlyVisible;
private String mGroupName;
private boolean mLegacyCompatibilityMode;
+ private boolean mDirectorySearchEnabled = true;
/**
* Copies all fields.
@@ -96,6 +97,7 @@
mDisplayOnlyVisible = request.mDisplayOnlyVisible;
mGroupName = request.mGroupName;
mLegacyCompatibilityMode = request.mLegacyCompatibilityMode;
+ mDirectorySearchEnabled = request.mDirectorySearchEnabled;
}
public static Parcelable.Creator<ContactsRequest> CREATOR = new Creator<ContactsRequest>() {
@@ -117,6 +119,7 @@
request.mDisplayOnlyVisible = source.readInt() != 0;
request.mGroupName = source.readString();
request.mLegacyCompatibilityMode = source.readInt() != 0;
+ request.mDirectorySearchEnabled = source.readInt() != 0;
return request;
}
};
@@ -133,6 +136,7 @@
dest.writeInt(mDisplayOnlyVisible ? 1 : 0);
dest.writeString(mGroupName);
dest.writeInt(mLegacyCompatibilityMode ? 1 : 0);
+ dest.writeInt(mDirectorySearchEnabled ? 1 : 0);
}
public int describeContents() {
@@ -226,4 +230,16 @@
public void setLegacyCompatibilityMode(boolean flag) {
mLegacyCompatibilityMode = flag;
}
+
+ /**
+ * Determines whether this search request should include directories or
+ * is limited to local contacts only.
+ */
+ public boolean isDirectorySearchEnabled() {
+ return mDirectorySearchEnabled;
+ }
+
+ public void setDirectorySearchEnabled(boolean flag) {
+ mDirectorySearchEnabled = flag;
+ }
}
diff --git a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
index 24b48d3..dfc4c26 100644
--- a/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/DefaultContactBrowseListFragment.java
@@ -163,19 +163,19 @@
}
}
- public void setEditMode(boolean flag) {
- mEditMode = flag;
- }
-
public boolean isEditMode() {
return mEditMode;
}
- public void setCreateContactEnabled(boolean flag) {
- this.mCreateContactEnabled = flag;
+ public void setEditMode(boolean flag) {
+ mEditMode = flag;
}
public boolean isCreateContactEnabled() {
return mCreateContactEnabled;
}
+
+ public void setCreateContactEnabled(boolean flag) {
+ this.mCreateContactEnabled = flag;
+ }
}
diff --git a/src/com/android/contacts/list/DirectoryListLoader.java b/src/com/android/contacts/list/DirectoryListLoader.java
new file mode 100644
index 0000000..b8cc2c9
--- /dev/null
+++ b/src/com/android/contacts/list/DirectoryListLoader.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import com.android.contacts.R;
+
+import android.content.AsyncTaskLoader;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.ContactsContract.Directory;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * A specialized loader for the list of directories, see {@link Directory}.
+ */
+public class DirectoryListLoader extends AsyncTaskLoader<Cursor> {
+
+ private static final String TAG = "ContactEntryListAdapter";
+
+ private static final class DirectoryQuery {
+ public static final Uri URI = Directory.CONTENT_URI;
+ public static final String ORDER_BY = Directory._ID;
+
+ public static final String[] PROJECTION = {
+ Directory._ID,
+ Directory.PACKAGE_NAME,
+ Directory.TYPE_RESOURCE_ID,
+ Directory.DISPLAY_NAME,
+ };
+
+ public static final int ID = 0;
+ public static final int PACKAGE_NAME = 1;
+ public static final int TYPE_RESOURCE_ID = 2;
+ public static final int DISPLAY_NAME = 3;
+ }
+
+ public static final String DIRECTORY_TYPE = "directoryType";
+
+ private static final String[] RESULT_PROJECTION = {
+ Directory._ID,
+ DIRECTORY_TYPE,
+ Directory.DISPLAY_NAME,
+ };
+
+ private final ContentObserver mObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ forceLoad();
+ }
+ };
+
+ private boolean mDirectorySearchEnabled;
+
+ private MatrixCursor mDefaultDirectoryList;
+
+ public DirectoryListLoader(Context context) {
+ super(context);
+ }
+
+ public void setDirectorySearchEnabled(boolean flag) {
+ mDirectorySearchEnabled = flag;
+ }
+
+ @Override
+ public void startLoading() {
+ getContext().getContentResolver().
+ registerContentObserver(Directory.CONTENT_URI, false, mObserver);
+ forceLoad();
+ }
+
+ @Override
+ public void stopLoading() {
+ getContext().getContentResolver().unregisterContentObserver(mObserver);
+ }
+
+ @Override
+ public Cursor loadInBackground() {
+ if (mDirectorySearchEnabled) {
+ return loadDirectories();
+ } else {
+ return getDefaultDirectories();
+ }
+ }
+
+ private Cursor loadDirectories() {
+ MatrixCursor result = new MatrixCursor(RESULT_PROJECTION);
+ Context context = getContext();
+ PackageManager pm = context.getPackageManager();
+ Cursor cursor = context.getContentResolver().query(DirectoryQuery.URI,
+ DirectoryQuery.PROJECTION, null, null, DirectoryQuery.ORDER_BY);
+ try {
+ while(cursor.moveToNext()) {
+ Object[] row = new Object[RESULT_PROJECTION.length];
+ long directoryId = cursor.getLong(DirectoryQuery.ID);
+ String directoryType = null;
+
+ String packageName = cursor.getString(DirectoryQuery.PACKAGE_NAME);
+ int typeResourceId = cursor.getInt(DirectoryQuery.TYPE_RESOURCE_ID);
+ if (!TextUtils.isEmpty(packageName) && typeResourceId != 0) {
+ try {
+ directoryType = pm.getResourcesForApplication(packageName)
+ .getString(typeResourceId);
+ } catch (Exception e) {
+ Log.e(TAG, "Cannot obtain directory type from package: " + packageName);
+ }
+ }
+ String displayName = cursor.getString(DirectoryQuery.DISPLAY_NAME);
+ result.addRow(new Object[]{directoryId, directoryType, displayName});
+ }
+ } finally {
+ cursor.close();
+ }
+ return result;
+ }
+
+ private Cursor getDefaultDirectories() {
+ if (mDefaultDirectoryList == null) {
+ mDefaultDirectoryList = new MatrixCursor(RESULT_PROJECTION);
+ mDefaultDirectoryList.addRow(new Object[] {
+ Directory.DEFAULT,
+ getContext().getString(R.string.contactsList),
+ null
+ });
+ mDefaultDirectoryList.addRow(new Object[] {
+ Directory.LOCAL_INVISIBLE,
+ getContext().getString(R.string.local_invisible_directory),
+ null
+ });
+ }
+ return mDefaultDirectoryList;
+ }
+
+ @Override
+ public void destroy() {
+ stopLoading();
+ }
+}
diff --git a/src/com/android/contacts/list/JoinContactListFragment.java b/src/com/android/contacts/list/JoinContactListFragment.java
index 74ff844..8c6be47 100644
--- a/src/com/android/contacts/list/JoinContactListFragment.java
+++ b/src/com/android/contacts/list/JoinContactListFragment.java
@@ -154,6 +154,7 @@
public void startSearch(String initialQuery) {
ContactsRequest request = new ContactsRequest();
request.setActionCode(ContactsRequest.ACTION_PICK_CONTACT);
+ request.setDirectorySearchEnabled(false);
ContactsSearchManager.startSearchForResult(getActivity(), initialQuery,
ACTIVITY_REQUEST_CODE_PICKER, request);
}