Merge "Showing recents in search"
diff --git a/res/layout/search_saved_query_item.xml b/res/layout/search_saved_query_item.xml
new file mode 100644
index 0000000..71c8482
--- /dev/null
+++ b/res/layout/search_saved_query_item.xml
@@ -0,0 +1,45 @@
+<?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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical"
+ android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
+ <TextView
+ android:id="@android:id/title"
+ android:textAppearance="?android:attr/textAppearanceListItem"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"/>
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/search_suggestion_item_image_size"
+ android:layout_height="@dimen/search_suggestion_item_image_size"
+ android:layout_marginStart="@dimen/search_suggestion_item_image_margin_start"
+ android:layout_marginEnd="@dimen/search_suggestion_item_image_margin_end"
+ android:scaleType="centerInside"
+ android:src="@drawable/ic_search_history"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index cd6e562..b79a7f4 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -266,7 +266,7 @@
StringBuilder sb = new StringBuilder();
sb.append("SELECT ");
- sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY);
+ sb.append(IndexDatabaseHelper.SavedQueriesColumns.QUERY);
sb.append(" FROM ");
sb.append(Tables.TABLE_SAVED_QUERIES);
@@ -274,7 +274,7 @@
sb.append(" ORDER BY rowId DESC");
} else {
sb.append(" WHERE ");
- sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY);
+ sb.append(IndexDatabaseHelper.SavedQueriesColumns.QUERY);
sb.append(" LIKE ");
sb.append("'");
sb.append(query);
@@ -1299,8 +1299,8 @@
final long now = new Date().getTime();
final ContentValues values = new ContentValues();
- values.put(IndexDatabaseHelper.SavedQueriesColums.QUERY, params[0]);
- values.put(IndexDatabaseHelper.SavedQueriesColums.TIME_STAMP, now);
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, params[0]);
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now);
final SQLiteDatabase database = getWritableDatabase();
if (database == null) {
@@ -1312,7 +1312,7 @@
try {
// First, delete all saved queries that are the same
database.delete(Tables.TABLE_SAVED_QUERIES,
- IndexDatabaseHelper.SavedQueriesColums.QUERY + " = ?",
+ IndexDatabaseHelper.SavedQueriesColumns.QUERY + " = ?",
new String[] { params[0] });
// Second, insert the saved query
diff --git a/src/com/android/settings/search/IndexDatabaseHelper.java b/src/com/android/settings/search/IndexDatabaseHelper.java
index ba53e94..8de6c54 100644
--- a/src/com/android/settings/search/IndexDatabaseHelper.java
+++ b/src/com/android/settings/search/IndexDatabaseHelper.java
@@ -67,7 +67,7 @@
String BUILD = "build";
}
- public interface SavedQueriesColums {
+ public interface SavedQueriesColumns {
String QUERY = "query";
String TIME_STAMP = "timestamp";
}
@@ -127,9 +127,9 @@
private static final String CREATE_SAVED_QUERIES_TABLE =
"CREATE TABLE " + Tables.TABLE_SAVED_QUERIES +
"(" +
- SavedQueriesColums.QUERY + " VARCHAR(64) NOT NULL" +
+ SavedQueriesColumns.QUERY + " VARCHAR(64) NOT NULL" +
", " +
- SavedQueriesColums.TIME_STAMP + " INTEGER" +
+ SavedQueriesColumns.TIME_STAMP + " INTEGER" +
")";
private static final String INSERT_BUILD_VERSION =
diff --git a/src/com/android/settings/search2/ResultPayload.java b/src/com/android/settings/search2/ResultPayload.java
index 3842def..4294234 100644
--- a/src/com/android/settings/search2/ResultPayload.java
+++ b/src/com/android/settings/search2/ResultPayload.java
@@ -29,7 +29,7 @@
public abstract class ResultPayload implements Parcelable {
@IntDef({PayloadType.INLINE_SLIDER, PayloadType.INLINE_SWITCH,
- PayloadType.INTENT})
+ PayloadType.INTENT, PayloadType.SAVED_QUERY})
@Retention(RetentionPolicy.SOURCE)
public @interface PayloadType {
/**
@@ -46,6 +46,11 @@
* Result is a inline widget, using a toggle widget as UI.
*/
int INLINE_SWITCH = 2;
+
+ /**
+ * Result is a recently saved query.
+ */
+ int SAVED_QUERY = 3;
}
@IntDef({SettingsSource.UNKNOWN, SettingsSource.SYSTEM, SettingsSource.SECURE,
@@ -59,5 +64,6 @@
}
- @ResultPayload.PayloadType public abstract int getType();
+ @ResultPayload.PayloadType
+ public abstract int getType();
}
diff --git a/src/com/android/settings/search2/SavedQueryLoader.java b/src/com/android/settings/search2/SavedQueryLoader.java
new file mode 100644
index 0000000..b034b44
--- /dev/null
+++ b/src/com/android/settings/search2/SavedQueryLoader.java
@@ -0,0 +1,77 @@
+/*
+ * 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.settings.search2;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.settings.search.IndexDatabaseHelper;
+import com.android.settings.search.IndexDatabaseHelper.SavedQueriesColumns;
+import com.android.settings.utils.AsyncLoader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Loader for recently searched queries.
+ */
+public class SavedQueryLoader extends AsyncLoader<List<SearchResult>> {
+
+ // Max number of proposed suggestions
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ static final int MAX_PROPOSED_SUGGESTIONS = 5;
+
+ private final SQLiteDatabase mDatabase;
+
+ public SavedQueryLoader(Context context) {
+ super(context);
+ mDatabase = IndexDatabaseHelper.getInstance(context).getReadableDatabase();
+ }
+
+ @Override
+ protected void onDiscardResult(List<SearchResult> result) {
+
+ }
+
+ @Override
+ public List<SearchResult> loadInBackground() {
+ Cursor cursor = mDatabase.query(IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES /* table */,
+ new String[]{SavedQueriesColumns.QUERY} /* columns */,
+ null /* selection */,
+ null /* selectionArgs */,
+ null /* groupBy */,
+ null /* having */,
+ "rowId DESC" /* orderBy */,
+ String.valueOf(MAX_PROPOSED_SUGGESTIONS) /* limit */);
+ return convertCursorToResult(cursor);
+ }
+
+ private List<SearchResult> convertCursorToResult(Cursor cursor) {
+ final List<SearchResult> results = new ArrayList<>();
+ while (cursor.moveToNext()) {
+ final SavedQueryPayload payload = new SavedQueryPayload(
+ cursor.getString(cursor.getColumnIndex(SavedQueriesColumns.QUERY)));
+ results.add(new SearchResult.Builder()
+ .addTitle(payload.query)
+ .addPayload(payload)
+ .build());
+ }
+ return results;
+ }
+}
diff --git a/src/com/android/settings/search2/SavedQueryPayload.java b/src/com/android/settings/search2/SavedQueryPayload.java
new file mode 100644
index 0000000..6316894
--- /dev/null
+++ b/src/com/android/settings/search2/SavedQueryPayload.java
@@ -0,0 +1,64 @@
+/*
+ * 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.settings.search2;
+
+import android.os.Parcel;
+import android.support.annotation.VisibleForTesting;
+
+/**
+ * {@link ResultPayload} for saved query.
+ */
+public class SavedQueryPayload extends ResultPayload {
+
+ public final String query;
+
+ public SavedQueryPayload(String query) {
+ this.query = query;
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ SavedQueryPayload(Parcel in) {
+ query = in.readString();
+ }
+
+ @Override
+ public int getType() {
+ return PayloadType.SAVED_QUERY;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(query);
+ }
+
+ public static final Creator<SavedQueryPayload> CREATOR = new Creator<SavedQueryPayload>() {
+ @Override
+ public SavedQueryPayload createFromParcel(Parcel in) {
+ return new SavedQueryPayload(in);
+ }
+
+ @Override
+ public SavedQueryPayload[] newArray(int size) {
+ return new SavedQueryPayload[size];
+ }
+ };
+}
diff --git a/src/com/android/settings/search2/SavedQueryRecorder.java b/src/com/android/settings/search2/SavedQueryRecorder.java
new file mode 100644
index 0000000..e2325e8
--- /dev/null
+++ b/src/com/android/settings/search2/SavedQueryRecorder.java
@@ -0,0 +1,97 @@
+/*
+ * 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.settings.search2;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.util.Log;
+
+import com.android.settings.search.IndexDatabaseHelper;
+import com.android.settings.utils.AsyncLoader;
+
+import static com.android.settings.search.IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES;
+
+/**
+ * A background task to update saved queries.
+ */
+public class SavedQueryRecorder extends AsyncLoader<Void> {
+
+ private static final String LOG_TAG = "SavedQueryRecorder";
+
+ // Max number of saved search queries (who will be used for proposing suggestions)
+ private static long MAX_SAVED_SEARCH_QUERY = 64;
+
+ private final String mQuery;
+
+ public SavedQueryRecorder(Context context, String query) {
+ super(context);
+ mQuery = query;
+ }
+
+ @Override
+ protected void onDiscardResult(Void result) {
+
+ }
+
+ @Override
+ public Void loadInBackground() {
+ final long now = System.currentTimeMillis();
+
+ final ContentValues values = new ContentValues();
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, mQuery);
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now);
+
+ final SQLiteDatabase database = getWritableDatabase();
+ if (database == null) {
+ return null;
+ }
+
+ long lastInsertedRowId;
+ try {
+ // First, delete all saved queries that are the same
+ database.delete(TABLE_SAVED_QUERIES,
+ IndexDatabaseHelper.SavedQueriesColumns.QUERY + " = ?",
+ new String[]{mQuery});
+
+ // Second, insert the saved query
+ lastInsertedRowId = database.insertOrThrow(TABLE_SAVED_QUERIES, null, values);
+
+ // Last, remove "old" saved queries
+ final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY;
+ if (delta > 0) {
+ int count = database.delete(TABLE_SAVED_QUERIES,
+ "rowId <= ?",
+ new String[]{Long.toString(delta)});
+ Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)");
+ }
+ } catch (Exception e) {
+ Log.d(LOG_TAG, "Cannot update saved Search queries", e);
+ }
+ return null;
+ }
+
+ private SQLiteDatabase getWritableDatabase() {
+ try {
+ return IndexDatabaseHelper.getInstance(getContext()).getWritableDatabase();
+ } catch (SQLiteException e) {
+ Log.e(LOG_TAG, "Cannot open writable database", e);
+ return null;
+ }
+ }
+}
diff --git a/src/com/android/settings/search2/SavedQueryViewHolder.java b/src/com/android/settings/search2/SavedQueryViewHolder.java
new file mode 100644
index 0000000..a32ed05
--- /dev/null
+++ b/src/com/android/settings/search2/SavedQueryViewHolder.java
@@ -0,0 +1,38 @@
+/*
+ * 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.settings.search2;
+
+import android.view.View;
+import android.widget.TextView;
+
+public class SavedQueryViewHolder extends SearchViewHolder {
+
+ public final TextView titleView;
+
+ public SavedQueryViewHolder(View view) {
+ super(view);
+ titleView = (TextView) view.findViewById(android.R.id.title);
+ }
+
+ @Override
+ public void onBind(SearchFragment fragment, SearchResult result) {
+ titleView.setText(result.title);
+ itemView.setOnClickListener(v -> {
+ fragment.onSavedQueryClicked(result.title);
+ });
+ }
+}
diff --git a/src/com/android/settings/search2/SearchFeatureProvider.java b/src/com/android/settings/search2/SearchFeatureProvider.java
index 8a616a7..91a1444 100644
--- a/src/com/android/settings/search2/SearchFeatureProvider.java
+++ b/src/com/android/settings/search2/SearchFeatureProvider.java
@@ -48,6 +48,11 @@
InstalledAppResultLoader getInstalledAppSearchLoader(Context context, String query);
/**
+ * Returns a new loader to get all recently saved queries search terms.
+ */
+ SavedQueryLoader getSavedQueryLoader(Context context);
+
+ /**
* Returns the manager for indexing Settings data.
*/
DatabaseIndexingManager getIndexingManager(Context context);
diff --git a/src/com/android/settings/search2/SearchFeatureProviderImpl.java b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
index a76d905..5d62412 100644
--- a/src/com/android/settings/search2/SearchFeatureProviderImpl.java
+++ b/src/com/android/settings/search2/SearchFeatureProviderImpl.java
@@ -73,6 +73,11 @@
}
@Override
+ public SavedQueryLoader getSavedQueryLoader(Context context) {
+ return new SavedQueryLoader(context);
+ }
+
+ @Override
public DatabaseIndexingManager getIndexingManager(Context context) {
if (mDatabaseIndexingManager == null) {
mDatabaseIndexingManager = new DatabaseIndexingManager(context.getApplicationContext(),
diff --git a/src/com/android/settings/search2/SearchFragment.java b/src/com/android/settings/search2/SearchFragment.java
index e26f5ed..b688a45 100644
--- a/src/com/android/settings/search2/SearchFragment.java
+++ b/src/com/android/settings/search2/SearchFragment.java
@@ -52,8 +52,9 @@
private static final String STATE_RESULT_CLICK_COUNT = "state_result_click_count";
// Loader IDs
- private static final int LOADER_ID_DATABASE = 0;
- private static final int LOADER_ID_INSTALLED_APPS = 1;
+ private static final int LOADER_ID_RECENTS = 0;
+ private static final int LOADER_ID_DATABASE = 1;
+ private static final int LOADER_ID_INSTALLED_APPS = 2;
// Logging
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
@@ -61,6 +62,10 @@
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
String mQuery;
+
+ private final SaveQueryRecorderCallback mSaveQueryRecorderCallback =
+ new SaveQueryRecorderCallback();
+
private boolean mNeverEnteredQuery = true;
private int mResultClickCount;
private MetricsFeatureProvider mMetricsFeatureProvider;
@@ -68,6 +73,7 @@
private SearchResultsAdapter mSearchAdapter;
private RecyclerView mResultsRecyclerView;
+ private SearchView mSearchView;
@Override
public int getMetricsCategory() {
@@ -86,18 +92,21 @@
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mSearchAdapter = new SearchResultsAdapter(this);
+ final LoaderManager loaderManager = getLoaderManager();
if (savedInstanceState != null) {
mQuery = savedInstanceState.getString(STATE_QUERY);
mNeverEnteredQuery = savedInstanceState.getBoolean(STATE_NEVER_ENTERED_QUERY);
mResultClickCount = savedInstanceState.getInt(STATE_RESULT_CLICK_COUNT);
- final LoaderManager loaderManager = getLoaderManager();
loaderManager.initLoader(LOADER_ID_DATABASE, null, this);
loaderManager.initLoader(LOADER_ID_INSTALLED_APPS, null, this);
+ } else {
+ loaderManager.initLoader(LOADER_ID_RECENTS, null, this);
}
final Activity activity = getActivity();
final ActionBar actionBar = activity.getActionBar();
- actionBar.setCustomView(makeSearchView(actionBar, mQuery));
+ mSearchView = makeSearchView(actionBar, mQuery);
+ actionBar.setCustomView(mSearchView);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
@@ -151,7 +160,10 @@
mSearchAdapter.clearResults();
if (TextUtils.isEmpty(mQuery)) {
- getLoaderManager().destroyLoader(LOADER_ID_DATABASE);
+ final LoaderManager loaderManager = getLoaderManager();
+ loaderManager.destroyLoader(LOADER_ID_DATABASE);
+ loaderManager.destroyLoader(LOADER_ID_INSTALLED_APPS);
+ loaderManager.restartLoader(LOADER_ID_RECENTS, null /* args */, this /* callback */);
} else {
restartLoaders();
}
@@ -161,6 +173,10 @@
@Override
public boolean onQueryTextSubmit(String query) {
+ // Save submitted query.
+ getLoaderManager().restartLoader(SaveQueryRecorderCallback.LOADER_ID_SAVE_QUERY_TASK, null,
+ mSaveQueryRecorderCallback);
+
return true;
}
@@ -173,6 +189,8 @@
return mSearchFeatureProvider.getDatabaseSearchLoader(activity, mQuery);
case LOADER_ID_INSTALLED_APPS:
return mSearchFeatureProvider.getInstalledAppSearchLoader(activity, mQuery);
+ case LOADER_ID_RECENTS:
+ return mSearchFeatureProvider.getSavedQueryLoader(activity);
default:
return null;
}
@@ -191,6 +209,12 @@
mResultClickCount++;
}
+ public void onSavedQueryClicked(CharSequence query) {
+ final String queryString = query.toString();
+ mSearchView.setQuery(queryString, false /* submit */);
+ onQueryTextChange(queryString);
+ }
+
private void restartLoaders() {
final LoaderManager loaderManager = getLoaderManager();
loaderManager.restartLoader(LOADER_ID_DATABASE, null /* args */, this /* callback */);
@@ -207,4 +231,25 @@
searchView.setLayoutParams(lp);
return searchView;
}
+
+ private class SaveQueryRecorderCallback implements LoaderManager.LoaderCallbacks<Void> {
+ // TODO: make a generic background task manager to handle one-off tasks like this one.
+
+ private static final int LOADER_ID_SAVE_QUERY_TASK = 0;
+
+ @Override
+ public Loader<Void> onCreateLoader(int id, Bundle args) {
+ return new SavedQueryRecorder(getActivity(), mQuery);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Void> loader, Void data) {
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Void> loader) {
+
+ }
+ }
}
diff --git a/src/com/android/settings/search2/SearchResultsAdapter.java b/src/com/android/settings/search2/SearchResultsAdapter.java
index c318b41..999a485 100644
--- a/src/com/android/settings/search2/SearchResultsAdapter.java
+++ b/src/com/android/settings/search2/SearchResultsAdapter.java
@@ -49,13 +49,16 @@
final Context context = parent.getContext();
final LayoutInflater inflater = LayoutInflater.from(context);
final View view;
- switch(viewType) {
+ switch (viewType) {
case PayloadType.INTENT:
view = inflater.inflate(R.layout.search_intent_item, parent, false);
return new IntentSearchViewHolder(view);
case PayloadType.INLINE_SWITCH:
view = inflater.inflate(R.layout.search_inline_switch_item, parent, false);
return new InlineSwitchViewHolder(view, context);
+ case PayloadType.SAVED_QUERY:
+ view = inflater.inflate(R.layout.search_saved_query_item, parent, false);
+ return new SavedQueryViewHolder(view);
default:
return null;
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index cd0822b..a178596 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -90,4 +90,4 @@
com.android.settings.applications.ConvertToFbe
com.android.settings.localepicker.LocaleListEditor
com.android.settings.qstile.DevelopmentTileConfigActivity$DevelopmentTileConfigFragment
-com.android.settings.applications.ExternalSourcesDetails
\ No newline at end of file
+com.android.settings.applications.ExternalSourcesDetails
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
index 8b363b0..3d469dd 100644
--- a/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
+++ b/tests/robotests/src/com/android/settings/search/DatabaseIndexingManagerTest.java
@@ -21,10 +21,12 @@
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.SearchIndexableResource;
+
import com.android.settings.R;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.search2.DatabaseIndexingManager;
+import com.android.settings.testutils.DatabaseTestUtils;
import org.junit.After;
import org.junit.Before;
@@ -33,7 +35,6 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
-import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -85,15 +86,7 @@
@After
public void cleanUp() {
- Field instance;
- Class clazz = IndexDatabaseHelper.class;
- try {
- instance = clazz.getDeclaredField("sSingleton");
- instance.setAccessible(true);
- instance.set(null, null);
- } catch (Exception e) {
- throw new RuntimeException();
- }
+ DatabaseTestUtils.clearDb();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java b/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
index c592aef..2b29a16 100644
--- a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java
@@ -20,10 +20,13 @@
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
+
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.search2.DatabaseIndexingUtils;
import com.android.settings.search2.DatabaseResultLoader;
+import com.android.settings.testutils.DatabaseTestUtils;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -31,8 +34,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import java.lang.reflect.Field;
-
import static com.google.common.truth.Truth.assertThat;
@RunWith(SettingsRobolectricTestRunner.class)
@@ -53,15 +54,7 @@
@After
public void cleanUp() {
- Field instance;
- Class clazz = IndexDatabaseHelper.class;
- try {
- instance = clazz.getDeclaredField("sSingleton");
- instance.setAccessible(true);
- instance.set(null, null);
- } catch (Exception e) {
- throw new RuntimeException();
- }
+ DatabaseTestUtils.clearDb();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/search2/SavedQueryLoaderTest.java b/tests/robotests/src/com/android/settings/search2/SavedQueryLoaderTest.java
new file mode 100644
index 0000000..d975f0c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search2/SavedQueryLoaderTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.settings.search2;
+
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.search.IndexDatabaseHelper;
+import com.android.settings.testutils.DatabaseTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SavedQueryLoaderTest {
+
+ private Context mContext;
+ private SQLiteDatabase mDb;
+ private SavedQueryLoader mLoader;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mDb = IndexDatabaseHelper.getInstance(mContext).getWritableDatabase();
+ mLoader = new SavedQueryLoader(mContext);
+ setUpDb();
+ }
+
+ @After
+ public void cleanUp() {
+ DatabaseTestUtils.clearDb();
+ }
+
+ @Test
+ public void loadInBackground_shouldReturnSavedQueries() {
+ final List<SearchResult> results = mLoader.loadInBackground();
+ assertThat(results.size()).isEqualTo(SavedQueryLoader.MAX_PROPOSED_SUGGESTIONS);
+ for (SearchResult result : results) {
+ assertThat(result.viewType).isEqualTo(ResultPayload.PayloadType.SAVED_QUERY);
+ }
+ }
+
+ private void setUpDb() {
+ final long now = System.currentTimeMillis();
+ for (int i = 0; i < SavedQueryLoader.MAX_PROPOSED_SUGGESTIONS + 2; i++) {
+ ContentValues values = new ContentValues();
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.QUERY, String.valueOf(i));
+ values.put(IndexDatabaseHelper.SavedQueriesColumns.TIME_STAMP, now);
+ mDb.replaceOrThrow(IndexDatabaseHelper.Tables.TABLE_SAVED_QUERIES, null, values);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search2/SavedQueryPayloadTest.java b/tests/robotests/src/com/android/settings/search2/SavedQueryPayloadTest.java
new file mode 100644
index 0000000..daa6d5e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search2/SavedQueryPayloadTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.settings.search2;
+
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SavedQueryPayloadTest {
+
+ private SavedQueryPayload mPayload;
+
+ @Test
+ public void getType_shouldBeSavedQueryType() {
+ mPayload = new SavedQueryPayload("Test");
+ assertThat(mPayload.getType()).isEqualTo(ResultPayload.PayloadType.SAVED_QUERY);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search2/SavedQueryRecorderTest.java b/tests/robotests/src/com/android/settings/search2/SavedQueryRecorderTest.java
new file mode 100644
index 0000000..c56ecce
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/search2/SavedQueryRecorderTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.settings.search2;
+
+
+import android.content.Context;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.DatabaseTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SavedQueryRecorderTest {
+
+ private Context mContext;
+ private SavedQueryRecorder mRecorder;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @After
+ public void cleanUp() {
+ DatabaseTestUtils.clearDb();
+ }
+
+ @Test
+ public void canSaveQueryToDb() {
+ final String query = "test";
+ mRecorder = new SavedQueryRecorder(mContext, query);
+
+ mRecorder.loadInBackground();
+
+ final SavedQueryLoader loader = new SavedQueryLoader(mContext);
+ List<SearchResult> results = loader.loadInBackground();
+
+ assertThat(results.size()).isEqualTo(1);
+ assertThat(results.get(0).title).isEqualTo(query);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
index d97360d..7a0bb54 100644
--- a/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/search2/SearchFragmentTest.java
@@ -39,6 +39,7 @@
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -52,6 +53,9 @@
private DatabaseResultLoader mDatabaseResultLoader;
@Mock
private InstalledAppResultLoader mInstalledAppResultLoader;
+ @Mock
+ private SavedQueryLoader mSavedQueryLoader;
+
private FakeFeatureFactory mFeatureFactory;
@Before
@@ -65,6 +69,8 @@
when(mFeatureFactory.searchFeatureProvider
.getInstalledAppSearchLoader(any(Context.class), anyString()))
.thenReturn(mInstalledAppResultLoader);
+ when(mFeatureFactory.searchFeatureProvider.getSavedQueryLoader(any(Context.class)))
+ .thenReturn(mSavedQueryLoader);
}
@Test
@@ -115,6 +121,27 @@
}
@Test
+ public void queryTextChangeToEmpty_shouldTriggerSavedQueryLoader() {
+ ActivityController<SearchActivity> activityController =
+ Robolectric.buildActivity(SearchActivity.class);
+ activityController.setup();
+ SearchFragment fragment = (SearchFragment) activityController.get().getFragmentManager()
+ .findFragmentById(R.id.main_content);
+
+ fragment.onQueryTextChange("");
+ activityController.get().onBackPressed();
+ activityController.pause().stop().destroy();
+
+ verify(mFeatureFactory.searchFeatureProvider, never())
+ .getDatabaseSearchLoader(any(Context.class), anyString());
+ verify(mFeatureFactory.searchFeatureProvider, never())
+ .getInstalledAppSearchLoader(any(Context.class), anyString());
+ // Saved query loaded 2 times: fragment start, and query change to empty.
+ verify(mFeatureFactory.searchFeatureProvider, times(2))
+ .getSavedQueryLoader(any(Context.class));
+ }
+
+ @Test
public void updateIndex_TriggerOnCreate() {
ActivityController<SearchActivity> activityController =
Robolectric.buildActivity(SearchActivity.class);
diff --git a/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java b/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java
new file mode 100644
index 0000000..8fbe1c9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/DatabaseTestUtils.java
@@ -0,0 +1,36 @@
+/*
+ * 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.settings.testutils;
+
+import com.android.settings.search.IndexDatabaseHelper;
+
+import java.lang.reflect.Field;
+
+public class DatabaseTestUtils {
+
+ public static void clearDb() {
+ Field instance;
+ Class clazz = IndexDatabaseHelper.class;
+ try {
+ instance = clazz.getDeclaredField("sSingleton");
+ instance.setAccessible(true);
+ instance.set(null, null);
+ } catch (Exception e) {
+ throw new RuntimeException();
+ }
+ }
+}