summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicky Wai <rickywai@google.com>2015-03-10 22:45:58 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-03-10 22:46:00 +0000
commit410c29fe803c63342ee73168cd27f4bf7eda1c0e (patch)
tree956cbac02ada1709d0fe1a695d17d3545c5ea487
parent693406016fa0b02b4af4188fd9668a3d74881652 (diff)
parentb88a02f9551b991a8bc767867ae9ec1ccac75950 (diff)
downloadpackages_providers_ContactsProvider-410c29fe803c63342ee73168cd27f4bf7eda1c0e.zip
packages_providers_ContactsProvider-410c29fe803c63342ee73168cd27f4bf7eda1c0e.tar.gz
packages_providers_ContactsProvider-410c29fe803c63342ee73168cd27f4bf7eda1c0e.tar.bz2
Merge "Add private API to get merged primary and enterprise contacts"
-rw-r--r--AndroidManifest.xml3
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java88
2 files changed, 89 insertions, 2 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9142b72..eeaae48 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -47,6 +47,9 @@
<path-permission
android:pathPattern="/contacts/.*/photo"
android:readPermission="android.permission.GLOBAL_SEARCH" />
+ <path-permission
+ android:pathPrefix="/data_enterprise"
+ android:readPermission="android.permission.INTERACT_ACROSS_USERS" />
<grant-uri-permission android:pathPattern=".*" />
</provider>
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 130134b..2c58f38 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -40,9 +40,11 @@ import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.database.AbstractCursor;
import android.database.Cursor;
+import android.database.CursorWrapper;
import android.database.DatabaseUtils;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
+import android.database.MergeCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDoneException;
import android.database.sqlite.SQLiteQueryBuilder;
@@ -155,7 +157,6 @@ import com.android.providers.contacts.util.NeededForTesting;
import com.android.providers.contacts.util.UserUtils;
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;
@@ -339,6 +340,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
private static final int CALLABLES_FILTER = 3013;
private static final int CONTACTABLES = 3014;
private static final int CONTACTABLES_FILTER = 3015;
+ private static final int PHONES_ENTERPRISE = 3016;
private static final int PHONE_LOOKUP = 4000;
private static final int PHONE_LOOKUP_ENTERPRISE = 4001;
@@ -1201,6 +1203,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
matcher.addURI(ContactsContract.AUTHORITY, "data", DATA);
matcher.addURI(ContactsContract.AUTHORITY, "data/#", DATA_ID);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones", PHONES);
+ matcher.addURI(ContactsContract.AUTHORITY, "data_enterprise/phones", PHONES_ENTERPRISE);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/#", PHONES_ID);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter", PHONES_FILTER);
matcher.addURI(ContactsContract.AUTHORITY, "data/phones/filter/*", PHONES_FILTER);
@@ -5650,7 +5653,9 @@ public class ContactsProvider2 extends AbstractContactsProvider
new String[] {DisplayPhoto.DISPLAY_MAX_DIM, DisplayPhoto.THUMBNAIL_MAX_DIM},
new Object[] {getMaxDisplayPhotoDim(), getMaxThumbnailDim()});
}
-
+ case PHONES_ENTERPRISE: {
+ return queryMergedDataPhones(uri, projection, selection, selectionArgs, sortOrder);
+ }
case PHONES:
case CALLABLES: {
final String mimeTypeIsPhoneExpression =
@@ -6487,6 +6492,83 @@ public class ContactsProvider2 extends AbstractContactsProvider
return c;
}
+ private static class EnterprisePhoneCursorWrapper extends CursorWrapper {
+
+ public EnterprisePhoneCursorWrapper(Cursor cursor) {
+ super(cursor);
+ }
+
+ @Override
+ public int getInt(int column) {
+ return (int) getLong(column);
+ }
+
+ @Override
+ public long getLong(int column) {
+ long result = super.getLong(column);
+ String columnName = getColumnName(column);
+ // We change contactId only for now
+ switch (columnName) {
+ case Phone.CONTACT_ID:
+ return result + Contacts.ENTERPRISE_CONTACT_ID_BASE;
+ default:
+ return result;
+ }
+ }
+ }
+
+ /**
+ * Handles {@link Phone#ENTERPRISE_CONTENT_URI}.
+ */
+ // TODO test
+ private Cursor queryMergedDataPhones(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ final List<String> pathSegments = uri.getPathSegments();
+ final int pathSegmentsSize = pathSegments.size();
+ // Ignore the first 2 path segments: "/data_enterprise/phones"
+ final StringBuilder newPathBuilder = new StringBuilder(Phone.CONTENT_URI.getPath());
+ for (int i = 2; i < pathSegmentsSize; i++) {
+ newPathBuilder.append('/');
+ newPathBuilder.append(pathSegments.get(i));
+ }
+ // Change /data_enterprise/phones/... to /data/phones/...
+ final Uri localUri = uri.buildUpon().path(newPathBuilder.toString()).build();
+ final String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY);
+ final long directoryId =
+ (directory == null ? -1 :
+ (directory.equals("0") ? Directory.DEFAULT :
+ (directory.equals("1") ? Directory.LOCAL_INVISIBLE : Long.MIN_VALUE)));
+ final Cursor primaryCursor = queryLocal(localUri, projection, selection, selectionArgs,
+ sortOrder, directoryId, null);
+ try {
+ // TODO: Maybe we want to have a DPM policy for it
+ final int corpUserId = UserUtils.getCorpUserId(getContext());
+ if (corpUserId < 0) {
+ // No Corp user or policy not allowed
+ return primaryCursor;
+ }
+ final Uri remoteUri = maybeAddUserId(localUri, corpUserId);
+ final Cursor managedCursor = getContext().getContentResolver().query(remoteUri,
+ projection, selection, selectionArgs, sortOrder, null);
+ final Cursor[] cursorArray = new Cursor[] {
+ primaryCursor, new EnterprisePhoneCursorWrapper(managedCursor)
+ };
+ // Sort order is not supported yet, will be fixed in M when we have
+ // merged provider
+ // MergeCursor will copy all the contacts from two cursors, which may
+ // cause OOM if there's a lot of contacts. But it's only used by
+ // Bluetooth, and Bluetooth will loop through the Cursor and put all
+ // content in ArrayList anyway, so we ignore OOM issue here for now
+ final MergeCursor mergeCursor = new MergeCursor(cursorArray);
+ return mergeCursor;
+ } catch (Throwable th) {
+ if (primaryCursor != null) {
+ primaryCursor.close();
+ }
+ throw th;
+ }
+ }
+
/**
* Handles {@link PhoneLookup#ENTERPRISE_CONTENT_FILTER_URI}.
*/
@@ -8311,6 +8393,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return mContactsHelper.getDataMimeType(id);
}
case PHONES:
+ case PHONES_ENTERPRISE:
return Phone.CONTENT_TYPE;
case PHONES_ID:
return Phone.CONTENT_ITEM_TYPE;
@@ -8385,6 +8468,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case DATA_ID:
case PHONES:
+ case PHONES_ENTERPRISE:
case PHONES_ID:
case EMAILS:
case EMAILS_ID: