diff options
author | calderwoodra <calderwoodra@google.com> | 2017-08-08 20:49:57 -0700 |
---|---|---|
committer | Eric Erfanian <erfanian@google.com> | 2017-08-09 17:34:10 -0700 |
commit | 0b2626e433091f8ca75ab7018289ea8ec0ec8bbe (patch) | |
tree | 0c9cabbccb92841f779cf03082b651f463d28a1a /java/com/android | |
parent | d021f7a61ae8debee8e2b3ca69a6aee99be41753 (diff) |
Added remote directories to the new search fragment.
When Dialer users search for contacts, if they have an enterprise account on
their device, they can also search for enterprise/remote contacts. This change
adds the directory queries/results to the new search fragment.
screenshot: http://screen/S9mpsvnwtCv
Bug: 37209462
Test: javatests/.../searchfragment/remote
PiperOrigin-RevId: 164681686
Change-Id: I88bc5bceb4c745d8f6f7d9651929d49100283756
Diffstat (limited to 'java/com/android')
11 files changed, 299 insertions, 43 deletions
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java b/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java index 2bd9cdd8a..1e8224ddb 100644 --- a/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java +++ b/java/com/android/dialer/searchfragment/cp2/SearchContactViewHolder.java @@ -110,6 +110,7 @@ public final class SearchContactViewHolder extends ViewHolder implements OnClick } } + // Show the contact photo next to only the first number if a contact has multiple numbers private boolean shouldShowPhoto(SearchCursor cursor) { int currentPosition = cursor.getPosition(); String currentLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY); diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index 1a489513c..2c0281536 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -40,11 +40,16 @@ import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.searchfragment.cp2.SearchContactsCursorLoader; 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.util.PermissionsUtil; import com.android.dialer.util.ViewUtil; import com.android.dialer.widget.EmptyContentView; import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** Fragment used for searching contacts. */ public final class NewSearchFragment extends Fragment @@ -57,15 +62,21 @@ public final class NewSearchFragment extends Fragment @VisibleForTesting public static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1; private static final int CONTACTS_LOADER_ID = 0; - private static final int NEARBY_PLACES_ID = 1; + private static final int NEARBY_PLACES_LOADER_ID = 1; + private static final int REMOTE_DIRECTORIES_LOADER_ID = 2; + private static final int REMOTE_CONTACTS_LOADER_ID = 3; private EmptyContentView emptyContentView; private RecyclerView recyclerView; private SearchAdapter adapter; private String query; + private boolean remoteDirectoriesDisabledForTesting; + private final List<Directory> directories = new ArrayList<>(); private final Runnable loadNearbyPlacesRunnable = - () -> getLoaderManager().restartLoader(NEARBY_PLACES_ID, null, this); + () -> getLoaderManager().restartLoader(NEARBY_PLACES_LOADER_ID, null, this); + private final Runnable loadRemoteContactsRunnable = + () -> getLoaderManager().restartLoader(REMOTE_CONTACTS_LOADER_ID, null, this); private Runnable updatePositionRunnable; @@ -99,6 +110,7 @@ public final class NewSearchFragment extends Fragment private void initLoaders() { getLoaderManager().initLoader(CONTACTS_LOADER_ID, null, this); loadNearbyPlacesCursor(); + loadRemoteDirectoriesCursor(); } @Override @@ -106,8 +118,12 @@ public final class NewSearchFragment extends Fragment // TODO(calderwoodra) add enterprise loader if (id == CONTACTS_LOADER_ID) { return new SearchContactsCursorLoader(getContext()); - } else if (id == NEARBY_PLACES_ID) { + } else if (id == NEARBY_PLACES_LOADER_ID) { return new NearbyPlacesCursorLoader(getContext(), query); + } else if (id == REMOTE_DIRECTORIES_LOADER_ID) { + return new RemoteDirectoriesCursorLoader(getContext()); + } else if (id == REMOTE_CONTACTS_LOADER_ID) { + return new RemoteContactsCursorLoader(getContext(), query, directories); } else { throw new IllegalStateException("Invalid loader id: " + id); } @@ -115,14 +131,29 @@ public final class NewSearchFragment extends Fragment @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { - if (!(cursor instanceof SearchCursor)) { + if (cursor != null + && !(loader instanceof RemoteDirectoriesCursorLoader) + && !(cursor instanceof SearchCursor)) { throw Assert.createIllegalStateFailException("Cursors must implement SearchCursor"); } if (loader instanceof SearchContactsCursorLoader) { adapter.setContactsCursor((SearchCursor) cursor); + } else if (loader instanceof NearbyPlacesCursorLoader) { adapter.setNearbyPlacesCursor((SearchCursor) cursor); + + } else if (loader instanceof RemoteContactsCursorLoader) { + adapter.setRemoteContactsCursor((SearchCursor) cursor); + + } else if (loader instanceof RemoteDirectoriesCursorLoader) { + directories.clear(); + cursor.moveToPosition(-1); + while (cursor.moveToNext()) { + directories.add(RemoteDirectoriesCursorLoader.readDirectory(cursor)); + } + loadRemoteContactsCursors(); + } else { throw new IllegalStateException("Invalid loader: " + loader); } @@ -139,6 +170,7 @@ public final class NewSearchFragment extends Fragment if (adapter != null) { adapter.setQuery(query); loadNearbyPlacesCursor(); + loadRemoteContactsCursors(); } } @@ -159,6 +191,7 @@ public final class NewSearchFragment extends Fragment public void onDestroy() { super.onDestroy(); ThreadUtil.getUiThreadHandler().removeCallbacks(loadNearbyPlacesRunnable); + ThreadUtil.getUiThreadHandler().removeCallbacks(loadRemoteContactsRunnable); } private void loadNearbyPlacesCursor() { @@ -198,4 +231,29 @@ public final class NewSearchFragment extends Fragment this, deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE); } } + + private void loadRemoteDirectoriesCursor() { + if (!remoteDirectoriesDisabledForTesting) { + getLoaderManager().initLoader(REMOTE_DIRECTORIES_LOADER_ID, null, this); + } + } + + private void loadRemoteContactsCursors() { + if (remoteDirectoriesDisabledForTesting) { + return; + } + + // Cancel existing load if one exists. + ThreadUtil.getUiThreadHandler().removeCallbacks(loadRemoteContactsRunnable); + ThreadUtil.getUiThreadHandler() + .postDelayed(loadRemoteContactsRunnable, NETWORK_SEARCH_DELAY_MILLIS); + } + + // Currently, setting up multiple FakeContentProviders doesn't work and results in this fragment + // being untestable while it can query multiple datasources. This is a temporary fix. + // TODO(b/64099602): Remove this method and test this fragment with multiple data sources + @VisibleForTesting + public void setRemoteDirectoriesDisabled(boolean disabled) { + remoteDirectoriesDisabledForTesting = disabled; + } } diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java index c8588fc7d..81e8e38f7 100644 --- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java +++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java @@ -26,6 +26,7 @@ import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.searchfragment.cp2.SearchContactViewHolder; import com.android.dialer.searchfragment.list.SearchCursorManager.RowType; import com.android.dialer.searchfragment.nearbyplaces.NearbyPlaceViewHolder; +import com.android.dialer.searchfragment.remote.RemoteContactViewHolder; /** RecyclerView adapter for {@link NewSearchFragment}. */ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> { @@ -54,7 +55,9 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> { case RowType.NEARBY_PLACES_HEADER: return new HeaderViewHolder( LayoutInflater.from(context).inflate(R.layout.header_layout, root, false)); - case RowType.DIRECTORY_ROW: // TODO(calderwoodra): add directory rows to search + case RowType.DIRECTORY_ROW: + return new RemoteContactViewHolder( + LayoutInflater.from(context).inflate(R.layout.search_contact_row, root, false)); case RowType.INVALID: default: throw Assert.createIllegalStateFailException("Invalid RowType: " + rowType); @@ -72,8 +75,12 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> { ((SearchContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query); } else if (holder instanceof NearbyPlaceViewHolder) { ((NearbyPlaceViewHolder) holder).bind(searchCursorManager.getCursor(position), query); + } else if (holder instanceof RemoteContactViewHolder) { + ((RemoteContactViewHolder) holder).bind(searchCursorManager.getCursor(position), query); } else if (holder instanceof HeaderViewHolder) { - ((HeaderViewHolder) holder).setHeader(searchCursorManager.getHeaderText(position)); + String header = + searchCursorManager.getCursor(position).getString(SearchCursor.HEADER_TEXT_POSITION); + ((HeaderViewHolder) holder).setHeader(header); } else { throw Assert.createIllegalStateFailException("Invalid ViewHolder: " + holder); } @@ -101,7 +108,14 @@ class SearchAdapter extends RecyclerView.Adapter<ViewHolder> { } public void setNearbyPlacesCursor(SearchCursor nearbyPlacesCursor) { - searchCursorManager.setNearbyPlacesCursor(nearbyPlacesCursor); - notifyDataSetChanged(); + if (searchCursorManager.setNearbyPlacesCursor(nearbyPlacesCursor)) { + notifyDataSetChanged(); + } + } + + public void setRemoteContactsCursor(SearchCursor remoteContactsCursor) { + if (searchCursorManager.setCorpDirectoryCursor(remoteContactsCursor)) { + notifyDataSetChanged(); + } } } diff --git a/java/com/android/dialer/searchfragment/list/SearchCursorManager.java b/java/com/android/dialer/searchfragment/list/SearchCursorManager.java index 68f770af9..b385aa392 100644 --- a/java/com/android/dialer/searchfragment/list/SearchCursorManager.java +++ b/java/com/android/dialer/searchfragment/list/SearchCursorManager.java @@ -57,6 +57,7 @@ final class SearchCursorManager { }) @interface RowType { int INVALID = 0; + // TODO(calderwoodra) add suggestions header and list /** Header to mark the start of contact rows. */ int CONTACT_HEADER = 1; /** A row containing contact information for contacts stored locally on device. */ @@ -75,9 +76,10 @@ final class SearchCursorManager { private SearchCursor nearbyPlacesCursor = null; private SearchCursor corpDirectoryCursor = null; - void setContactsCursor(SearchCursor cursor) { + /** Returns true if the cursor changed. */ + boolean setContactsCursor(SearchCursor cursor) { if (cursor == contactsCursor) { - return; + return false; } if (contactsCursor != null && !contactsCursor.isClosed()) { @@ -89,11 +91,13 @@ final class SearchCursorManager { } else { contactsCursor = null; } + return true; } - void setNearbyPlacesCursor(SearchCursor cursor) { + /** Returns true if the cursor changed. */ + boolean setNearbyPlacesCursor(SearchCursor cursor) { if (cursor == nearbyPlacesCursor) { - return; + return false; } if (nearbyPlacesCursor != null && !nearbyPlacesCursor.isClosed()) { @@ -105,11 +109,13 @@ final class SearchCursorManager { } else { nearbyPlacesCursor = null; } + return true; } - void setCorpDirectoryCursor(SearchCursor cursor) { + /** Returns true if a cursor changed. */ + boolean setCorpDirectoryCursor(SearchCursor cursor) { if (cursor == corpDirectoryCursor) { - return; + return false; } if (corpDirectoryCursor != null && !corpDirectoryCursor.isClosed()) { @@ -121,6 +127,7 @@ final class SearchCursorManager { } else { corpDirectoryCursor = null; } + return true; } boolean setQuery(String query) { @@ -216,10 +223,6 @@ final class SearchCursorManager { throw Assert.createIllegalStateFailException("No valid cursor."); } - String getHeaderText(int position) { - return getCursor(position).getString(SearchCursor.HEADER_TEXT_POSITION); - } - /** removes all cursors. */ void clear() { if (contactsCursor != null) { diff --git a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml index 36af42ed9..eef0dee94 100644 --- a/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml +++ b/java/com/android/dialer/searchfragment/list/res/layout/header_layout.xml @@ -18,5 +18,6 @@ android:id="@+id/header" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_marginTop="8dp" android:paddingStart="16dp" style="@style/SecondaryText"/> diff --git a/java/com/android/dialer/searchfragment/remote/AndroidManifest.xml b/java/com/android/dialer/searchfragment/remote/AndroidManifest.xml new file mode 100644 index 000000000..e52f5319e --- /dev/null +++ b/java/com/android/dialer/searchfragment/remote/AndroidManifest.xml @@ -0,0 +1,16 @@ +<!-- + ~ Copyright (C) 2017 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.remote"/>
\ No newline at end of file diff --git a/java/com/android/dialer/searchfragment/remote/RemoteContactViewHolder.java b/java/com/android/dialer/searchfragment/remote/RemoteContactViewHolder.java index 18a871814..5fb12d349 100644 --- a/java/com/android/dialer/searchfragment/remote/RemoteContactViewHolder.java +++ b/java/com/android/dialer/searchfragment/remote/RemoteContactViewHolder.java @@ -34,6 +34,7 @@ import com.android.dialer.lettertile.LetterTileDrawable; import com.android.dialer.searchfragment.common.Projections; import com.android.dialer.searchfragment.common.QueryBoldingUtil; import com.android.dialer.searchfragment.common.R; +import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.telecom.TelecomUtil; /** ViewHolder for a nearby place row. */ @@ -60,7 +61,7 @@ public final class RemoteContactViewHolder extends RecyclerView.ViewHolder * Binds the ViewHolder with a cursor from {@link RemoteContactsCursorLoader} with the data found * at the cursors current position. */ - public void bind(Cursor cursor, String query) { + public void bind(SearchCursor cursor, String query) { number = cursor.getString(Projections.PHONE_NUMBER); String name = cursor.getString(Projections.PHONE_DISPLAY_NAME); String label = getLabel(context.getResources(), cursor); @@ -91,17 +92,19 @@ public final class RemoteContactViewHolder extends RecyclerView.ViewHolder } } - private boolean shouldShowPhoto(Cursor cursor) { + // Show the contact photo next to only the first number if a contact has multiple numbers + private boolean shouldShowPhoto(SearchCursor cursor) { int currentPosition = cursor.getPosition(); - if (currentPosition == 0) { - return true; - } - String currentLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY); cursor.moveToPosition(currentPosition - 1); - String previousLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY); + + if (!cursor.isHeader() && !cursor.isBeforeFirst()) { + String previousLookupKey = cursor.getString(Projections.PHONE_LOOKUP_KEY); + cursor.moveToPosition(currentPosition); + return !currentLookupKey.equals(previousLookupKey); + } cursor.moveToPosition(currentPosition); - return !currentLookupKey.equals(previousLookupKey); + return true; } // TODO(calderwoodra): unify this into a utility method with CallLogAdapter#getNumberType diff --git a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java new file mode 100644 index 000000000..d7c4f3805 --- /dev/null +++ b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursor.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017 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.dialer.searchfragment.remote; + +import android.content.Context; +import android.database.Cursor; +import android.database.MatrixCursor; +import android.database.MergeCursor; +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 java.util.ArrayList; +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}. + * + * <p>This cursor merges them together with a header at the start of each cursor/list using {@link + * Directory#getDisplayName()} as the header text. + */ +@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) +public final class RemoteContactsCursor extends MergeCursor implements SearchCursor { + + /** + * Returns a single cursor with headers inserted between each non-empty cursor. If all cursors are + * empty, null or closed, this method returns null. + */ + @Nullable + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) + public static RemoteContactsCursor newInstance( + Context context, Cursor[] cursors, List<Directory> directories) { + Assert.checkArgument( + cursors.length == directories.size(), "Directories and cursors must be the same size."); + Cursor[] cursorsWithHeaders = insertHeaders(context, cursors, directories); + if (cursorsWithHeaders.length > 0) { + return new RemoteContactsCursor(cursorsWithHeaders); + } + return null; + } + + private RemoteContactsCursor(Cursor[] cursors) { + super(cursors); + } + + private static Cursor[] insertHeaders( + Context context, Cursor[] cursors, List<Directory> directories) { + List<Cursor> cursorList = new ArrayList<>(); + for (int i = 0; i < cursors.length; i++) { + Cursor cursor = cursors[i]; + + if (cursor == null || cursor.isClosed()) { + continue; + } + + Directory directory = directories.get(i); + if (cursor.getCount() == 0) { + // Since the cursor isn't being merged in, we need to close it here. + cursor.close(); + continue; + } + + cursorList.add(createHeaderCursor(context, directory.getDisplayName())); + cursorList.add(cursor); + } + return cursorList.toArray(new Cursor[cursorList.size()]); + } + + private static MatrixCursor createHeaderCursor(Context context, String name) { + MatrixCursor headerCursor = new MatrixCursor(HEADER_PROJECTION, 1); + headerCursor.addRow(new String[] {context.getString(R.string.directory, name)}); + return headerCursor; + } + + /** Returns true if the current position is a header row. */ + @Override + public boolean isHeader() { + return !isClosed() && getColumnIndex(HEADER_PROJECTION[HEADER_TEXT_POSITION]) != -1; + } + + @Override + public boolean updateQuery(@Nullable String query) { + // When the query changes, a new network request is made for nearby places. Meaning this cursor + // will be closed and another created, so return false. + return false; + } +} diff --git a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java index c9cd7655d..771b7f183 100644 --- a/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java +++ b/java/com/android/dialer/searchfragment/remote/RemoteContactsCursorLoader.java @@ -18,17 +18,26 @@ package com.android.dialer.searchfragment.remote; import android.content.Context; import android.content.CursorLoader; +import android.database.Cursor; import android.net.Uri; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Phone; 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 java.util.List; -/** Cursor loader to load extended contacts on device. */ -final class RemoteContactsCursorLoader extends CursorLoader { +/** + * Cursor loader to load extended contacts on device. + * + * <p>This loader performs several database queries in serial and merges the resulting cursors + * together into {@link RemoteContactsCursor}. If there are no results, the loader will return a + * null cursor. + */ +public final class RemoteContactsCursorLoader extends CursorLoader { private static final Uri ENTERPRISE_CONTENT_FILTER_URI = Uri.withAppendedPath(Phone.CONTENT_URI, "filter_enterprise"); @@ -36,25 +45,55 @@ final class RemoteContactsCursorLoader extends CursorLoader { private static final String IGNORE_NUMBER_TOO_LONG_CLAUSE = "length(" + Phone.NUMBER + ") < 1000"; private static final String MAX_RESULTS = "20"; - private final Directory directory; + private final String query; + private final List<Directory> directories; + private final Cursor[] cursors; - RemoteContactsCursorLoader(Context context, String query, Directory directory) { + public RemoteContactsCursorLoader(Context context, String query, List<Directory> directories) { super( context, - getContentFilterUri(query, directory.getId()), + null, Projections.PHONE_PROJECTION, IGNORE_NUMBER_TOO_LONG_CLAUSE, null, Phone.SORT_KEY_PRIMARY); - this.directory = directory; + this.query = query; + this.directories = directories; + cursors = new Cursor[directories.size()]; + } + + @Override + 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())) { + cursors[i] = null; + continue; + } + cursors[i] = + getContext() + .getContentResolver() + .query( + getContentFilterUri(query, directory.getId()), + getProjection(), + getSelection(), + getSelectionArgs(), + getSortOrder()); + } + return RemoteContactsCursor.newInstance(getContext(), cursors, directories); } @VisibleForTesting static Uri getContentFilterUri(String query, int directoryId) { - Uri baseUri = Phone.CONTENT_FILTER_URI; - if (VERSION.SDK_INT >= VERSION_CODES.N) { - baseUri = ENTERPRISE_CONTENT_FILTER_URI; - } + Uri baseUri = + VERSION.SDK_INT >= VERSION_CODES.N + ? ENTERPRISE_CONTENT_FILTER_URI + : Phone.CONTENT_FILTER_URI; return baseUri .buildUpon() @@ -64,8 +103,4 @@ final class RemoteContactsCursorLoader extends CursorLoader { .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY, MAX_RESULTS) .build(); } - - public Directory getDirectory() { - return directory; - } } diff --git a/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java b/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java index 630c73cd4..327a62c7b 100644 --- a/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java +++ b/java/com/android/dialer/searchfragment/remote/RemoteDirectoriesCursorLoader.java @@ -44,12 +44,12 @@ public final class RemoteDirectoriesCursorLoader extends CursorLoader { ContactsContract.Directory.PHOTO_SUPPORT, }; - RemoteDirectoriesCursorLoader(Context context) { + public RemoteDirectoriesCursorLoader(Context context) { super(context, getContentUri(), PROJECTION, null, null, ContactsContract.Directory._ID); } /** @return current cursor row represented as a {@link Directory}. */ - static Directory readDirectory(Cursor cursor) { + public static Directory readDirectory(Cursor cursor) { return Directory.create( cursor.getInt(ID), cursor.getString(DISPLAY_NAME), cursor.getInt(PHOTO_SUPPORT) != 0); } @@ -63,7 +63,7 @@ public final class RemoteDirectoriesCursorLoader extends CursorLoader { /** POJO representing the results returned from {@link RemoteDirectoriesCursorLoader}. */ @AutoValue public abstract static class Directory { - static Directory create(int id, @Nullable String displayName, boolean supportsPhotos) { + public static Directory create(int id, @Nullable String displayName, boolean supportsPhotos) { return new AutoValue_RemoteDirectoriesCursorLoader_Directory(id, displayName, supportsPhotos); } diff --git a/java/com/android/dialer/searchfragment/remote/res/values/strings.xml b/java/com/android/dialer/searchfragment/remote/res/values/strings.xml new file mode 100644 index 000000000..beabba135 --- /dev/null +++ b/java/com/android/dialer/searchfragment/remote/res/values/strings.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2017 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 + --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Label for a list of contacts stored in a seperate directory [CHAR LIMIT=30]--> + <string name="directory">Directory <xliff:g example="google.com" id="email">%1$s</xliff:g></string> +</resources>
\ No newline at end of file |