summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/searchfragment
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2018-01-19 13:15:16 -0800
committerCopybara-Service <copybara-piper@google.com>2018-01-19 13:17:54 -0800
commita6523ddb1db3d456ba4d16a120dea1ccd6c72d24 (patch)
treea90f1a29600bea4d937435fdd40424c7f0fece12 /java/com/android/dialer/searchfragment
parentfdaa46618ce61344bc83a66590863d126c47b05f (diff)
Improve & reorganize logic related to directories/remote contacts in the search fragment.
Test: DirectoriesCursorLoaderTest, RemoteContactsCursorLoaderTest PiperOrigin-RevId: 182578207 Change-Id: I03c81bd8581c8abbef1bbca1a960f3380d588d22
Diffstat (limited to 'java/com/android/dialer/searchfragment')
-rw-r--r--java/com/android/dialer/searchfragment/directories/AndroidManifest.xml16
-rw-r--r--java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java (renamed from java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java)59
-rw-r--r--java/com/android/dialer/searchfragment/list/NewSearchFragment.java17
-rw-r--r--java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java5
-rw-r--r--java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java7
-rw-r--r--java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java26
6 files changed, 82 insertions, 48 deletions
diff --git a/java/com/android/dialer/searchfragment/directories/AndroidManifest.xml b/java/com/android/dialer/searchfragment/directories/AndroidManifest.xml
new file mode 100644
index 000000000..a7294cd12
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/directories/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+<manifest package="com.android.dialer.searchfragment.directories"/> \ No newline at end of file
diff --git a/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java b/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java
index de71025cd..edf5f2403 100644
--- a/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/directories/DirectoriesCursorLoader.java
@@ -15,7 +15,7 @@
* limitations under the License
*/
-package com.android.dialer.searchfragment.remote;
+package com.android.dialer.searchfragment.directories;
import android.content.Context;
import android.content.CursorLoader;
@@ -25,33 +25,46 @@ import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.provider.ContactsContract;
import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
import com.google.auto.value.AutoValue;
+import java.util.ArrayList;
+import java.util.List;
-/** CursorLoader to load the list of remote directories on the device. */
-public final class RemoteDirectoriesCursorLoader extends CursorLoader {
+/** {@link CursorLoader} to load the list of all directories (local and remote). */
+public final class DirectoriesCursorLoader extends CursorLoader {
- /** Positions of columns in {@code PROJECTIONS}. */
- private static final int ID = 0;
-
- private static final int DISPLAY_NAME = 1;
- private static final int PHOTO_SUPPORT = 2;
-
- @VisibleForTesting
- static final String[] PROJECTION = {
+ public static final String[] PROJECTION = {
ContactsContract.Directory._ID,
ContactsContract.Directory.DISPLAY_NAME,
ContactsContract.Directory.PHOTO_SUPPORT,
};
- public RemoteDirectoriesCursorLoader(Context context) {
+ // Indices of columns in PROJECTION
+ private static final int ID = 0;
+ private static final int DISPLAY_NAME = 1;
+ private static final int PHOTO_SUPPORT = 2;
+
+ public DirectoriesCursorLoader(Context context) {
super(context, getContentUri(), PROJECTION, null, null, ContactsContract.Directory._ID);
}
- /** @return current cursor row represented as a {@link Directory}. */
- public static Directory readDirectory(Cursor cursor) {
- return Directory.create(
- cursor.getInt(ID), cursor.getString(DISPLAY_NAME), cursor.getInt(PHOTO_SUPPORT) != 0);
+ /**
+ * Creates a complete list of directories from the data set loaded by this loader.
+ *
+ * @param cursor A cursor pointing to the data set loaded by this loader. The caller must ensure
+ * the cursor is not null.
+ * @return A list of directories.
+ */
+ public static List<Directory> toDirectories(Cursor cursor) {
+ List<Directory> directories = new ArrayList<>();
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ directories.add(
+ Directory.create(
+ cursor.getInt(ID),
+ cursor.getString(DISPLAY_NAME),
+ /* supportsPhotos = */ cursor.getInt(PHOTO_SUPPORT) != 0));
+ }
+ return directories;
}
private static Uri getContentUri() {
@@ -60,18 +73,18 @@ public final class RemoteDirectoriesCursorLoader extends CursorLoader {
: ContactsContract.Directory.CONTENT_URI;
}
- /** POJO representing the results returned from {@link RemoteDirectoriesCursorLoader}. */
+ /** POJO representing the results returned from {@link DirectoriesCursorLoader}. */
@AutoValue
public abstract static class Directory {
- public static Directory create(int id, @Nullable String displayName, boolean supportsPhotos) {
- return new AutoValue_RemoteDirectoriesCursorLoader_Directory(id, displayName, supportsPhotos);
+ public static Directory create(long id, @Nullable String displayName, boolean supportsPhotos) {
+ return new AutoValue_DirectoriesCursorLoader_Directory(id, displayName, supportsPhotos);
}
- public abstract int getId();
+ public abstract long getId();
/** Returns a user facing display name of the directory. Null if none exists. */
- abstract @Nullable String getDisplayName();
+ public abstract @Nullable String getDisplayName();
- abstract boolean supportsPhotos();
+ public abstract boolean supportsPhotos();
}
}
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index 30949d38f..c62d40e59 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -63,11 +63,11 @@ import com.android.dialer.precall.PreCall;
import com.android.dialer.searchfragment.common.RowClickListener;
import com.android.dialer.searchfragment.common.SearchCursor;
import com.android.dialer.searchfragment.cp2.SearchContactsCursorLoader;
+import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader;
+import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader.Directory;
import com.android.dialer.searchfragment.list.SearchActionViewHolder.Action;
import com.android.dialer.searchfragment.nearbyplaces.NearbyPlacesCursorLoader;
import com.android.dialer.searchfragment.remote.RemoteContactsCursorLoader;
-import com.android.dialer.searchfragment.remote.RemoteDirectoriesCursorLoader;
-import com.android.dialer.searchfragment.remote.RemoteDirectoriesCursorLoader.Directory;
import com.android.dialer.storage.StorageComponent;
import com.android.dialer.util.CallUtil;
import com.android.dialer.util.DialerUtils;
@@ -196,13 +196,13 @@ public final class NewSearchFragment extends Fragment
// Directories represent contact data sources on the device, but since nearby places aren't
// stored on the device, they don't have a directory ID. We pass the list of all existing IDs
// so that we can find one that doesn't collide.
- List<Integer> directoryIds = new ArrayList<>();
+ List<Long> directoryIds = new ArrayList<>();
for (Directory directory : directories) {
directoryIds.add(directory.getId());
}
return new NearbyPlacesCursorLoader(getContext(), query, directoryIds);
} else if (id == REMOTE_DIRECTORIES_LOADER_ID) {
- return new RemoteDirectoriesCursorLoader(getContext());
+ return new DirectoriesCursorLoader(getContext());
} else if (id == REMOTE_CONTACTS_LOADER_ID) {
return new RemoteContactsCursorLoader(getContext(), query, directories);
} else {
@@ -214,7 +214,7 @@ public final class NewSearchFragment extends Fragment
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
LogUtil.i("NewSearchFragment.onLoadFinished", "Loader finished: " + loader);
if (cursor != null
- && !(loader instanceof RemoteDirectoriesCursorLoader)
+ && !(loader instanceof DirectoriesCursorLoader)
&& !(cursor instanceof SearchCursor)) {
throw Assert.createIllegalStateFailException("Cursors must implement SearchCursor");
}
@@ -228,12 +228,9 @@ public final class NewSearchFragment extends Fragment
} else if (loader instanceof RemoteContactsCursorLoader) {
adapter.setRemoteContactsCursor((SearchCursor) cursor);
- } else if (loader instanceof RemoteDirectoriesCursorLoader) {
+ } else if (loader instanceof DirectoriesCursorLoader) {
directories.clear();
- cursor.moveToPosition(-1);
- while (cursor.moveToNext()) {
- directories.add(RemoteDirectoriesCursorLoader.readDirectory(cursor));
- }
+ directories.addAll(DirectoriesCursorLoader.toDirectories(cursor));
loadNearbyPlacesCursor();
loadRemoteContactsCursors();
diff --git a/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
index 0d52c108e..9ba6d56ea 100644
--- a/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java
@@ -39,8 +39,7 @@ public final class NearbyPlacesCursorLoader extends CursorLoader {
* order to find a directory ID for the nearby places cursor that doesn't collide with
* existing directories.
*/
- public NearbyPlacesCursorLoader(
- Context context, String query, @NonNull List<Integer> directoryIds) {
+ public NearbyPlacesCursorLoader(Context context, String query, @NonNull List<Long> directoryIds) {
super(context, getContentUri(context, query), Projections.DATA_PROJECTION, null, null, null);
this.directoryId = getDirectoryId(directoryIds);
}
@@ -63,7 +62,7 @@ public final class NearbyPlacesCursorLoader extends CursorLoader {
.build();
}
- private static long getDirectoryId(List<Integer> directoryIds) {
+ private static long getDirectoryId(List<Long> directoryIds) {
if (directoryIds.isEmpty()) {
return INVALID_DIRECTORY_ID;
}
diff --git a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java
index e9e83c19b..9510443b9 100644
--- a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java
+++ b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java
@@ -24,7 +24,8 @@ import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import com.android.dialer.common.Assert;
import com.android.dialer.searchfragment.common.SearchCursor;
-import com.android.dialer.searchfragment.remote.RemoteDirectoriesCursorLoader.Directory;
+import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader;
+import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader.Directory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -33,7 +34,7 @@ import java.util.List;
* {@link MergeCursor} used for combining remote directory cursors into one cursor.
*
* <p>Usually a device with multiple Google accounts will have multiple remote directories returned
- * by {@link RemoteDirectoriesCursorLoader}, each represented as a {@link Directory}.
+ * by {@link DirectoriesCursorLoader}, each represented as a {@link Directory}.
*
* <p>This cursor merges them together with a header at the start of each cursor/list using {@link
* Directory#getDisplayName()} as the header text.
@@ -98,7 +99,7 @@ public final class RemoteContactsCursor extends MergeCursor implements SearchCur
return cursorList.toArray(new Cursor[cursorList.size()]);
}
- private static MatrixCursor createHeaderCursor(Context context, String name, int id) {
+ private static MatrixCursor createHeaderCursor(Context context, String name, long id) {
MatrixCursor headerCursor = new MatrixCursor(PROJECTION, 1);
headerCursor.addRow(new Object[] {context.getString(R.string.directory, name), id});
return headerCursor;
diff --git a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java
index 5f92c4902..9feeb7e99 100644
--- a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java
@@ -27,9 +27,8 @@ import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
-import android.text.TextUtils;
import com.android.dialer.searchfragment.common.Projections;
-import com.android.dialer.searchfragment.remote.RemoteDirectoriesCursorLoader.Directory;
+import com.android.dialer.searchfragment.directories.DirectoriesCursorLoader.Directory;
import java.util.ArrayList;
import java.util.List;
@@ -70,15 +69,13 @@ public final class RemoteContactsCursorLoader extends CursorLoader {
public Cursor loadInBackground() {
for (int i = 0; i < directories.size(); i++) {
Directory directory = directories.get(i);
- // Since the on device contacts could be queried as remote directories and we already query
- // them in SearchContactsCursorLoader, avoid querying them again.
- // TODO(calderwoodra): It's a happy coincidence that on device contacts don't have directory
- // names set, leaving this todo to investigate a better way to isolate them from other remote
- // directories.
- if (TextUtils.isEmpty(directory.getDisplayName())) {
+
+ // Filter out local directories
+ if (!isRemoteDirectory(directory.getId())) {
cursors[i] = null;
continue;
}
+
Cursor cursor =
getContext()
.getContentResolver()
@@ -96,6 +93,17 @@ public final class RemoteContactsCursorLoader extends CursorLoader {
return RemoteContactsCursor.newInstance(getContext(), cursors, directories);
}
+ private static boolean isRemoteDirectory(long directoryId) {
+ return VERSION.SDK_INT >= VERSION_CODES.N
+ ? ContactsContract.Directory.isRemoteDirectoryId(directoryId)
+ : (directoryId != ContactsContract.Directory.DEFAULT
+ && directoryId != ContactsContract.Directory.LOCAL_INVISIBLE
+ // Directory.ENTERPRISE_DEFAULT is the default work profile directory for locally stored
+ // contacts
+ && directoryId != ContactsContract.Directory.ENTERPRISE_DEFAULT
+ && directoryId != ContactsContract.Directory.ENTERPRISE_LOCAL_INVISIBLE);
+ }
+
private MatrixCursor createMatrixCursorFilteringNullNumbers(Cursor cursor) {
if (cursor == null) {
return null;
@@ -140,7 +148,7 @@ public final class RemoteContactsCursorLoader extends CursorLoader {
}
@VisibleForTesting
- static Uri getContentFilterUri(String query, int directoryId) {
+ static Uri getContentFilterUri(String query, long directoryId) {
Uri baseUri =
VERSION.SDK_INT >= VERSION_CODES.N
? ENTERPRISE_CONTENT_FILTER_URI