diff options
author | linyuh <linyuh@google.com> | 2018-01-19 13:15:16 -0800 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-01-19 13:17:54 -0800 |
commit | a6523ddb1db3d456ba4d16a120dea1ccd6c72d24 (patch) | |
tree | a90f1a29600bea4d937435fdd40424c7f0fece12 /java | |
parent | fdaa46618ce61344bc83a66590863d126c47b05f (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')
-rw-r--r-- | java/com/android/dialer/searchfragment/directories/AndroidManifest.xml | 16 | ||||
-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.java | 17 | ||||
-rw-r--r-- | java/com/android/dialer/searchfragment/nearbyplaces/NearbyPlacesCursorLoader.java | 5 | ||||
-rw-r--r-- | java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java | 7 | ||||
-rw-r--r-- | java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java | 26 |
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 |