summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--InCallUI/src/com/android/incallui/CallerInfo.java13
-rw-r--r--InCallUI/src/com/android/incallui/CallerInfoAsyncQuery.java148
2 files changed, 145 insertions, 16 deletions
diff --git a/InCallUI/src/com/android/incallui/CallerInfo.java b/InCallUI/src/com/android/incallui/CallerInfo.java
index 2ed5722aa..f11ea850b 100644
--- a/InCallUI/src/com/android/incallui/CallerInfo.java
+++ b/InCallUI/src/com/android/incallui/CallerInfo.java
@@ -39,6 +39,19 @@ import com.android.dialer.calllog.ContactInfoHelper;
public class CallerInfo {
private static final String TAG = "CallerInfo";
+ public static final String[] DEFAULT_PHONELOOKUP_PROJECTION = new String[] {
+ PhoneLookup._ID,
+ PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.LOOKUP_KEY,
+ PhoneLookup.NUMBER,
+ PhoneLookup.NORMALIZED_NUMBER,
+ PhoneLookup.LABEL,
+ PhoneLookup.TYPE,
+ PhoneLookup.PHOTO_URI,
+ PhoneLookup.CUSTOM_RINGTONE,
+ PhoneLookup.SEND_TO_VOICEMAIL
+ };
+
/**
* Please note that, any one of these member variables can be null,
* and any accesses to them should be prepared to handle such a case.
diff --git a/InCallUI/src/com/android/incallui/CallerInfoAsyncQuery.java b/InCallUI/src/com/android/incallui/CallerInfoAsyncQuery.java
index ec2296f86..97a95ac50 100644
--- a/InCallUI/src/com/android/incallui/CallerInfoAsyncQuery.java
+++ b/InCallUI/src/com/android/incallui/CallerInfoAsyncQuery.java
@@ -16,23 +16,27 @@
package com.android.incallui;
+import com.google.common.primitives.Longs;
+
import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.ContactsContract;
-import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.Directory;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
-import com.android.dialer.calllog.ContactInfoHelper;
-import com.android.contacts.common.util.PhoneNumberHelper;
import com.android.contacts.common.util.TelephonyManagerUtils;
+import com.android.dialer.calllog.ContactInfoHelper;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
@@ -51,6 +55,8 @@ public class CallerInfoAsyncQuery {
private static final int EVENT_EMERGENCY_NUMBER = 4;
private static final int EVENT_VOICEMAIL_NUMBER = 5;
+ private static final boolean FLAG_N_FEATURE = false;
+
private CallerInfoAsyncQueryHandler mHandler;
// If the CallerInfo query finds no contacts, should we use the
@@ -81,7 +87,6 @@ public class CallerInfoAsyncQuery {
public String number;
}
-
/**
* Simple exception used to communicate problems with the query pool.
*/
@@ -158,7 +163,6 @@ public class CallerInfoAsyncQuery {
super.handleMessage(msg);
} else {
-
Log.d(this, "Processing event: " + cw.event + " token (arg1): " + msg.arg1 +
" command: " + msg.what + " query URI: " +
sanitizeUriToString(args.uri));
@@ -325,6 +329,37 @@ public class CallerInfoAsyncQuery {
private CallerInfoAsyncQuery() {
}
+ public static void startQuery(final int token, final Context context, final CallerInfo info,
+ final OnQueryCompleteListener listener, final Object cookie) {
+ Log.d(LOG_TAG, "##### CallerInfoAsyncQuery startContactProviderQuery()... #####");
+ Log.d(LOG_TAG, "- number: " + info.phoneNumber);
+ Log.d(LOG_TAG, "- cookie: " + cookie);
+ OnQueryCompleteListener contactsProviderQueryCompleteListener =
+ new OnQueryCompleteListener() {
+ @Override
+ public void onQueryComplete(int token, Object cookie, CallerInfo ci) {
+ Log.d(LOG_TAG, "contactsProviderQueryCompleteListener done");
+ if (ci != null && ci.contactExists) {
+ if (listener != null) {
+ listener.onQueryComplete(token, cookie, ci);
+ }
+ } else {
+ startOtherDirectoriesQuery(token, context, info, listener, cookie);
+ }
+ }
+ };
+ startDefaultDirectoryQuery(token, context, info, contactsProviderQueryCompleteListener,
+ cookie);
+ }
+
+ // Private methods
+ private static CallerInfoAsyncQuery startDefaultDirectoryQuery(int token, Context context,
+ CallerInfo info, OnQueryCompleteListener listener, Object cookie) {
+ // Construct the URI object and query params, and start the query.
+ Uri uri = ContactInfoHelper.getContactInfoLookupUri(info.phoneNumber);
+ return startQueryInternal(token, context, info, listener, cookie, uri);
+ }
+
/**
* Factory method to start the query based on a CallerInfo object.
*
@@ -336,16 +371,8 @@ public class CallerInfoAsyncQuery {
* PhoneUtils.startGetCallerInfo() decide which one to call based on
* the phone type of the incoming connection.
*/
- public static CallerInfoAsyncQuery startQuery(int token, Context context, CallerInfo info,
- OnQueryCompleteListener listener, Object cookie) {
- Log.d(LOG_TAG, "##### CallerInfoAsyncQuery startQuery()... #####");
- Log.d(LOG_TAG, "- number: " + info.phoneNumber);
- Log.d(LOG_TAG, "- cookie: " + cookie);
-
- // Construct the URI object and query params, and start the query.
-
- final Uri contactRef = ContactInfoHelper.getContactInfoLookupUri(info.phoneNumber);
-
+ private static CallerInfoAsyncQuery startQueryInternal(int token, Context context,
+ CallerInfo info, OnQueryCompleteListener listener, Object cookie, Uri contactRef) {
if (DBG) {
Log.d(LOG_TAG, "==> contactRef: " + sanitizeUriToString(contactRef));
}
@@ -371,13 +398,102 @@ public class CallerInfoAsyncQuery {
c.mHandler.startQuery(token,
cw, // cookie
contactRef, // uri
- null, // projection
+ CallerInfo.DEFAULT_PHONELOOKUP_PROJECTION, // projection
null, // selection
null, // selectionArgs
null); // orderBy
return c;
}
+ private static void startOtherDirectoriesQuery(int token, Context context, CallerInfo info,
+ OnQueryCompleteListener listener, Object cookie) {
+ long[] directoryIds = getDirectoryIds(context);
+ int size = directoryIds.length;
+ if (size == 0) {
+ return;
+ }
+
+ OnQueryCompleteListener intermediateListener =
+ new DirectoryQueryCompleteListener(size, listener);
+
+ // The current implementation of multiple async query runs in single handler thread
+ // in AsyncQueryHandler.
+ // intermediateListener.onQueryComplete is also called from the same caller thread.
+ // TODO(b/26019872): use thread pool instead of single thread.
+ for (int i = 0; i < size; i++) {
+ long directoryId = directoryIds[i];
+ Uri uri = ContactInfoHelper.getContactInfoLookupUri(info.phoneNumber, directoryId);
+ if (DBG) {
+ Log.d(LOG_TAG, "directoryId: " + directoryId + " uri: " + uri);
+ }
+ startQueryInternal(token, context, info, intermediateListener, cookie, uri);
+ }
+ }
+
+ /* Directory lookup related code - START */
+ private static final String[] DIRECTORY_PROJECTION = new String[] {Directory._ID};
+
+ private static long[] getDirectoryIds(Context context) {
+ ArrayList<Long> results = new ArrayList<>();
+
+ Uri uri = Directory.CONTENT_URI;
+ // TODO(b/26019967):
+ // replace VERSION.CODENAME.startsWith("N") by VERSION.SDK_INT >= VERSION_CODES.NYC
+ if (FLAG_N_FEATURE && Build.VERSION.CODENAME.startsWith("N")) {
+ uri = Uri.withAppendedPath(ContactsContract.AUTHORITY_URI, "directories_enterprise");
+ }
+
+ ContentResolver cr = context.getContentResolver();
+ Cursor cursor = cr.query(uri, DIRECTORY_PROJECTION, null, null, null);
+ addDirectoryIdsFromCursor(cursor, results);
+
+ return Longs.toArray(results);
+ }
+
+ private static void addDirectoryIdsFromCursor(Cursor cursor, ArrayList<Long> results) {
+ if (cursor != null) {
+ int idIndex = cursor.getColumnIndex(Directory._ID);
+ while (cursor.moveToNext()) {
+ long id = cursor.getLong(idIndex);
+ // TODO(b/26019967): in N SDK, use Directory.isRemoteDirectory
+ if (id != Directory.DEFAULT && id != Directory.LOCAL_INVISIBLE && id != 1000000000
+ && id != 1000000001) {
+ results.add(id);
+ }
+ }
+ cursor.close();
+ }
+ }
+
+ private static final class DirectoryQueryCompleteListener implements OnQueryCompleteListener {
+ int mCount;
+ boolean mIsListernerCalled;
+ OnQueryCompleteListener mListener;
+
+ DirectoryQueryCompleteListener(int size, OnQueryCompleteListener listener) {
+ mCount = size;
+ mListener = listener;
+ mIsListernerCalled = false;
+ }
+
+ @Override
+ public void onQueryComplete(int token, Object cookie, CallerInfo ci) {
+ boolean shouldCallListener = false;
+ synchronized (this) {
+ mCount = mCount - 1;
+ if (!mIsListernerCalled && (ci.contactExists || mCount == 0)) {
+ mIsListernerCalled = true;
+ shouldCallListener = true;
+ }
+ }
+
+ if (shouldCallListener) {
+ mListener.onQueryComplete(token, cookie, ci);
+ }
+ }
+ }
+ /* Directory lookup related code - END */
+
/**
* Method to create a new CallerInfoAsyncQueryHandler object, ensuring correct
* state of context and uri.