Merge "Fork Search code to independantly develop and test search."
This commit is contained in:
committed by
Android (Google) Code Review
commit
3b64ad983f
@@ -216,6 +216,11 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<activity android:name=".search2.SearchActivity"
|
||||||
|
android:label="@string/search_settings"
|
||||||
|
android:icon="@drawable/ic_search_history">
|
||||||
|
</activity>
|
||||||
|
|
||||||
<!-- Top-level settings -->
|
<!-- Top-level settings -->
|
||||||
|
|
||||||
<activity android:name="Settings$WifiSettingsActivity"
|
<activity android:name="Settings$WifiSettingsActivity"
|
||||||
|
|||||||
63
res/layout/search_intent_item.xml
Normal file
63
res/layout/search_intent_item.xml
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2016 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:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
|
android:paddingEnd="?android:attr/scrollbarSize"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="@dimen/search_result_item_image_size"
|
||||||
|
android:layout_height="@dimen/search_result_item_image_size"
|
||||||
|
android:layout_marginStart="@dimen/search_result_item_image_margin_start"
|
||||||
|
android:layout_marginEnd="@dimen/search_result_item_image_margin_end"
|
||||||
|
android:scaleType="centerInside"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView android:id="@+id/title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fadingEdge="horizontal" />
|
||||||
|
|
||||||
|
<TextView android:id="@+id/summary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:fadingEdge="horizontal" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
24
res/layout/search_main.xml
Normal file
24
res/layout/search_main.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
* Copyright 2016, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/main_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:background="@color/material_grey_300"/>
|
||||||
62
res/layout/search_panel_2.xml
Normal file
62
res/layout/search_panel_2.xml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2016 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:id="@+id/search_panel"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/layout_recent_searches"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- Padding is included in the background -->
|
||||||
|
<android.support.v7.widget.RecyclerView android:id="@+id/list_recent_searches"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="@dimen/dashboard_padding_start"
|
||||||
|
android:paddingEnd="@dimen/dashboard_padding_end"
|
||||||
|
android:paddingTop="@dimen/dashboard_padding_top"
|
||||||
|
android:paddingBottom="@dimen/dashboard_padding_bottom"
|
||||||
|
android:scrollbarStyle="outsideOverlay"
|
||||||
|
android:headerDividersEnabled="false"
|
||||||
|
android:background="@drawable/search_panel_list_background"
|
||||||
|
android:elevation="@dimen/search_panel_elevation"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout android:id="@+id/layout_results"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- Padding is included in the background -->
|
||||||
|
<android.support.v7.widget.RecyclerView android:id="@+id/list_results"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="@dimen/dashboard_padding_start"
|
||||||
|
android:paddingEnd="@dimen/dashboard_padding_end"
|
||||||
|
android:paddingTop="@dimen/dashboard_padding_top"
|
||||||
|
android:paddingBottom="@dimen/dashboard_padding_bottom"
|
||||||
|
android:scrollbarStyle="outsideOverlay"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:background="@drawable/search_panel_list_background"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
23
res/menu/search_options_menu.xml
Normal file
23
res/menu/search_options_menu.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2016 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.
|
||||||
|
-->
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/search"
|
||||||
|
android:title="@string/search_menu"
|
||||||
|
android:icon="@*android:drawable/ic_search_api_material"
|
||||||
|
android:showAsAction="collapseActionView|ifRoom"
|
||||||
|
android:actionViewClass="android.widget.SearchView"/>
|
||||||
|
</menu>
|
||||||
@@ -136,6 +136,8 @@ import com.android.settings.print.PrintSettingsFragment;
|
|||||||
import com.android.settings.qstile.DevelopmentTiles;
|
import com.android.settings.qstile.DevelopmentTiles;
|
||||||
import com.android.settings.search.DynamicIndexableContentMonitor;
|
import com.android.settings.search.DynamicIndexableContentMonitor;
|
||||||
import com.android.settings.search.Index;
|
import com.android.settings.search.Index;
|
||||||
|
import com.android.settings.search2.SearchFeatureProvider;
|
||||||
|
import com.android.settings.search2.SearchFragment;
|
||||||
import com.android.settings.sim.SimSettings;
|
import com.android.settings.sim.SimSettings;
|
||||||
import com.android.settings.system.SystemDashboardFragment;
|
import com.android.settings.system.SystemDashboardFragment;
|
||||||
import com.android.settings.tts.TextToSpeechSettings;
|
import com.android.settings.tts.TextToSpeechSettings;
|
||||||
@@ -477,6 +479,8 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
private SearchResultsSummary mSearchResultsFragment;
|
private SearchResultsSummary mSearchResultsFragment;
|
||||||
private String mSearchQuery;
|
private String mSearchQuery;
|
||||||
|
|
||||||
|
private SearchFeatureProvider mSearchFeatureProvider;
|
||||||
|
|
||||||
// Categories
|
// Categories
|
||||||
private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
|
private ArrayList<DashboardCategory> mCategories = new ArrayList<DashboardCategory>();
|
||||||
|
|
||||||
@@ -526,9 +530,14 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
MenuInflater inflater = getMenuInflater();
|
MenuInflater inflater = getMenuInflater();
|
||||||
|
if (mSearchFeatureProvider.isEnabled()) {
|
||||||
|
mSearchFeatureProvider.setUpSearchMenu(menu, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
inflater.inflate(R.menu.options_menu, menu);
|
inflater.inflate(R.menu.options_menu, menu);
|
||||||
|
|
||||||
// Cache the search query (can be overriden by the OnQueryTextListener)
|
|
||||||
|
// Cache the search query (can be overridden by the OnQueryTextListener)
|
||||||
final String query = mSearchQuery;
|
final String query = mSearchQuery;
|
||||||
|
|
||||||
mSearchMenuItem = menu.findItem(R.id.search);
|
mSearchMenuItem = menu.findItem(R.id.search);
|
||||||
@@ -551,7 +560,6 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
mSearchMenuItem.expandActionView();
|
mSearchMenuItem.expandActionView();
|
||||||
}
|
}
|
||||||
mSearchView.setQuery(query, true /* submit */);
|
mSearchView.setQuery(query, true /* submit */);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,8 +602,12 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
protected void onCreate(Bundle savedState) {
|
protected void onCreate(Bundle savedState) {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
mDashboardFeatureProvider =
|
|
||||||
FeatureFactory.getFactory(this).getDashboardFeatureProvider(this);
|
final FeatureFactory factory = FeatureFactory.getFactory(this);
|
||||||
|
|
||||||
|
mDashboardFeatureProvider = factory.getDashboardFeatureProvider(this);
|
||||||
|
mSearchFeatureProvider = factory.getSearchFeatureProvider(this);
|
||||||
|
|
||||||
// Should happen before any call to getIntent()
|
// Should happen before any call to getIntent()
|
||||||
getMetaData();
|
getMetaData();
|
||||||
|
|
||||||
@@ -1279,19 +1291,24 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
|
return super.shouldUpRecreateTask(new Intent(this, SettingsActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextSubmit(String query) {
|
public boolean onQueryTextSubmit(String query) {
|
||||||
switchToSearchResultsFragmentIfNeeded();
|
if (mSearchFeatureProvider.isEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
mSearchQuery = query;
|
mSearchQuery = query;
|
||||||
|
switchToSearchResultsFragmentIfNeeded();
|
||||||
return mSearchResultsFragment.onQueryTextSubmit(query);
|
return mSearchResultsFragment.onQueryTextSubmit(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) {
|
||||||
mSearchQuery = newText;
|
if (mSearchFeatureProvider.isEnabled() || mSearchResultsFragment == null) {
|
||||||
if (mSearchResultsFragment == null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
mSearchQuery = newText;
|
||||||
return mSearchResultsFragment.onQueryTextChange(newText);
|
return mSearchResultsFragment.onQueryTextChange(newText);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1335,6 +1352,7 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private void switchToSearchResultsFragmentIfNeeded() {
|
private void switchToSearchResultsFragmentIfNeeded() {
|
||||||
if (mSearchResultsFragment != null) {
|
if (mSearchResultsFragment != null) {
|
||||||
return;
|
return;
|
||||||
@@ -1352,10 +1370,12 @@ public class SettingsActivity extends SettingsDrawerActivity
|
|||||||
mSearchMenuItemExpanded = true;
|
mSearchMenuItemExpanded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void needToRevertToInitialFragment() {
|
public void needToRevertToInitialFragment() {
|
||||||
mNeedToRevertToInitialFragment = true;
|
mNeedToRevertToInitialFragment = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
private void revertToInitialFragment() {
|
private void revertToInitialFragment() {
|
||||||
mNeedToRevertToInitialFragment = false;
|
mNeedToRevertToInitialFragment = false;
|
||||||
mSearchResultsFragment = null;
|
mSearchResultsFragment = null;
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import com.android.settings.dashboard.DashboardFeatureProvider;
|
|||||||
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
||||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
|
import com.android.settings.search2.SearchFeatureProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for creating feature controllers. Allows OEM implementations to define their own
|
* Abstract class for creating feature controllers. Allows OEM implementations to define their own
|
||||||
@@ -80,6 +81,8 @@ public abstract class FeatureFactory {
|
|||||||
public abstract EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(
|
public abstract EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(
|
||||||
Context context);
|
Context context);
|
||||||
|
|
||||||
|
public abstract SearchFeatureProvider getSearchFeatureProvider(Context context);
|
||||||
|
|
||||||
public static final class FactoryNotFoundException extends RuntimeException {
|
public static final class FactoryNotFoundException extends RuntimeException {
|
||||||
public FactoryNotFoundException(Throwable throwable) {
|
public FactoryNotFoundException(Throwable throwable) {
|
||||||
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
|
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import com.android.settings.enterprise.EnterprisePrivacyFeatureProviderImpl;
|
|||||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
|
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
|
||||||
|
import com.android.settings.search2.SearchFeatureProvider;
|
||||||
|
import com.android.settings.search2.SearchFeatureProviderImpl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link FeatureFactory} implementation for AOSP Settings.
|
* {@link FeatureFactory} implementation for AOSP Settings.
|
||||||
@@ -44,6 +46,7 @@ public final class FeatureFactoryImpl extends FeatureFactory {
|
|||||||
private DashboardFeatureProviderImpl mDashboardFeatureProvider;
|
private DashboardFeatureProviderImpl mDashboardFeatureProvider;
|
||||||
private LocaleFeatureProvider mLocaleFeatureProvider;
|
private LocaleFeatureProvider mLocaleFeatureProvider;
|
||||||
private EnterprisePrivacyFeatureProvider mEnterprisePrivacyFeatureProvider;
|
private EnterprisePrivacyFeatureProvider mEnterprisePrivacyFeatureProvider;
|
||||||
|
private SearchFeatureProvider mSearchFeatureProvider;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
|
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
|
||||||
@@ -91,9 +94,17 @@ public final class FeatureFactoryImpl extends FeatureFactory {
|
|||||||
public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
|
public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
|
||||||
if (mEnterprisePrivacyFeatureProvider == null) {
|
if (mEnterprisePrivacyFeatureProvider == null) {
|
||||||
mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context,
|
mEnterprisePrivacyFeatureProvider = new EnterprisePrivacyFeatureProviderImpl(context,
|
||||||
new DevicePolicyManagerWrapperImpl((DevicePolicyManager)context
|
new DevicePolicyManagerWrapperImpl((DevicePolicyManager) context
|
||||||
.getSystemService(Context.DEVICE_POLICY_SERVICE)));
|
.getSystemService(Context.DEVICE_POLICY_SERVICE)));
|
||||||
}
|
}
|
||||||
return mEnterprisePrivacyFeatureProvider;
|
return mEnterprisePrivacyFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchFeatureProvider getSearchFeatureProvider(Context context) {
|
||||||
|
if (mSearchFeatureProvider == null) {
|
||||||
|
mSearchFeatureProvider = new SearchFeatureProviderImpl(context);
|
||||||
|
}
|
||||||
|
return mSearchFeatureProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
124
src/com/android/settings/search2/DatabaseResultLoader.java
Normal file
124
src/com/android/settings/search2/DatabaseResultLoader.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.content.Intent;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.support.annotation.VisibleForTesting;
|
||||||
|
import com.android.settings.search.Index;
|
||||||
|
import com.android.settings.search.IndexDatabaseHelper;
|
||||||
|
import com.android.settings.utils.AsyncLoader;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_ICON_RESID;
|
||||||
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_RAW_SUMMARY_ON;
|
||||||
|
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AsyncTask to retrieve Settings, First party app and any intent based results.
|
||||||
|
*/
|
||||||
|
public class DatabaseResultLoader extends AsyncLoader<List<SearchResult>> {
|
||||||
|
private final String mQueryText;
|
||||||
|
private final Context mContext;
|
||||||
|
protected final SQLiteDatabase mDatabase;
|
||||||
|
|
||||||
|
public DatabaseResultLoader(Context context, String queryText) {
|
||||||
|
super(context);
|
||||||
|
mDatabase = IndexDatabaseHelper.getInstance(context).getReadableDatabase();
|
||||||
|
mQueryText = queryText;
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDiscardResult(List<SearchResult> result) {
|
||||||
|
// TODO Search
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SearchResult> loadInBackground() {
|
||||||
|
if (mQueryText == null || mQueryText.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String query = getSQLQuery();
|
||||||
|
Cursor result = mDatabase.rawQuery(query, null);
|
||||||
|
|
||||||
|
return parseCursorForSearch(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean onCancelLoad() {
|
||||||
|
// TODO
|
||||||
|
return super.onCancelLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getSQLQuery() {
|
||||||
|
return String.format("SELECT data_rank, data_title, data_summary_on, " +
|
||||||
|
"data_summary_off, data_entries, data_keywords, class_name, screen_title, icon, " +
|
||||||
|
"intent_action, intent_target_package, intent_target_class, enabled, " +
|
||||||
|
"data_key_reference FROM prefs_index WHERE prefs_index MATCH 'data_title:%s* " +
|
||||||
|
"OR data_title_normalized:%s* OR data_keywords:%s*' AND locale = 'en_US'",
|
||||||
|
mQueryText, mQueryText, mQueryText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||||
|
public ArrayList<SearchResult> parseCursorForSearch(Cursor cursorResults) {
|
||||||
|
if (cursorResults == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final ArrayList<SearchResult> results = new ArrayList<>();
|
||||||
|
|
||||||
|
while (cursorResults.moveToNext()) {
|
||||||
|
final String title = cursorResults.getString(Index.COLUMN_INDEX_TITLE);
|
||||||
|
final String summaryOn = cursorResults.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
|
||||||
|
final ArrayList<String> breadcrumbs = new ArrayList<>();
|
||||||
|
final int rank = cursorResults.getInt(COLUMN_INDEX_XML_RES_RANK);
|
||||||
|
|
||||||
|
final String intentString = cursorResults.getString(Index.COLUMN_INDEX_INTENT_ACTION);
|
||||||
|
final IntentPayload intentPayload = new IntentPayload(new Intent(intentString));
|
||||||
|
final int iconID = cursorResults.getInt(COLUMN_INDEX_RAW_ICON_RESID);
|
||||||
|
Drawable icon;
|
||||||
|
try {
|
||||||
|
icon = mContext.getDrawable(iconID);
|
||||||
|
} catch (Resources.NotFoundException nfe) {
|
||||||
|
icon = mContext.getDrawable(R.drawable.ic_search_history);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SearchResult.Builder builder = new SearchResult.Builder();
|
||||||
|
builder.addTitle(title)
|
||||||
|
.addSummary(summaryOn)
|
||||||
|
.addBreadcrumbs(breadcrumbs)
|
||||||
|
.addRank(rank)
|
||||||
|
.addIcon(icon)
|
||||||
|
.addPayload(intentPayload);
|
||||||
|
results.add(builder.build());
|
||||||
|
}
|
||||||
|
Collections.sort(results);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
62
src/com/android/settings/search2/InlineSliderPayload.java
Normal file
62
src/com/android/settings/search2/InlineSliderPayload.java
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.net.Uri;
|
||||||
|
import android.os.Parcel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payload for Inline Settings results represented by a Slider.
|
||||||
|
*/
|
||||||
|
public class InlineSliderPayload extends ResultPayload {
|
||||||
|
public final Uri uri;
|
||||||
|
|
||||||
|
private InlineSliderPayload(Parcel in) {
|
||||||
|
uri = in.readParcelable(InlineSliderPayload.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public InlineSliderPayload(Uri newUri) {
|
||||||
|
uri = newUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return PayloadType.INLINE_SLIDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeParcelable(uri, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<InlineSliderPayload> CREATOR = new Creator<InlineSliderPayload>() {
|
||||||
|
@Override
|
||||||
|
public InlineSliderPayload createFromParcel(Parcel in) {
|
||||||
|
return new InlineSliderPayload(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InlineSliderPayload[] newArray(int size) {
|
||||||
|
return new InlineSliderPayload[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
63
src/com/android/settings/search2/IntentPayload.java
Normal file
63
src/com/android/settings/search2/IntentPayload.java
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.Intent;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates the standard intent based results as seen in first party apps and Settings results.
|
||||||
|
*/
|
||||||
|
public class IntentPayload extends ResultPayload {
|
||||||
|
public final Intent intent;
|
||||||
|
|
||||||
|
private IntentPayload(Parcel in) {
|
||||||
|
intent = in.readParcelable(IntentPayload.class.getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntentPayload(Intent newIntent) {
|
||||||
|
intent = newIntent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResultPayload.PayloadType public int getType() {
|
||||||
|
return PayloadType.INTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeParcelable(intent, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<IntentPayload> CREATOR = new Creator<IntentPayload>() {
|
||||||
|
@Override
|
||||||
|
public IntentPayload createFromParcel(Parcel in) {
|
||||||
|
return new IntentPayload(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntentPayload[] newArray(int size) {
|
||||||
|
return new IntentPayload[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
44
src/com/android/settings/search2/IntentSearchViewHolder.java
Normal file
44
src/com/android/settings/search2/IntentSearchViewHolder.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ViewHolder for intent based search results.
|
||||||
|
* The DatabaseResultLoader is the primary use case for this ViewHolder.
|
||||||
|
*/
|
||||||
|
public class IntentSearchViewHolder extends SearchViewHolder {
|
||||||
|
public final TextView titleView;
|
||||||
|
public final TextView summaryView;
|
||||||
|
public final ImageView iconView;
|
||||||
|
|
||||||
|
public IntentSearchViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
titleView = (TextView) view.findViewById(R.id.title);
|
||||||
|
summaryView = (TextView) view.findViewById(R.id.summary);
|
||||||
|
iconView= (ImageView) view.findViewById(R.id.icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBind(SearchResult result) {
|
||||||
|
titleView.setText(result.title);
|
||||||
|
summaryView.setText(result.summary);
|
||||||
|
iconView.setImageDrawable(result.icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/com/android/settings/search2/ResultPayload.java
Normal file
40
src/com/android/settings/search2/ResultPayload.java
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.annotation.IntDef;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A interface for search results types. Examples include Inline results, third party apps
|
||||||
|
* or any future possibilities.
|
||||||
|
*/
|
||||||
|
public abstract class ResultPayload implements Parcelable {
|
||||||
|
|
||||||
|
@IntDef({PayloadType.INLINE_SLIDER, PayloadType.INLINE_SWITCH, PayloadType.INTENT})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
public @interface PayloadType {
|
||||||
|
int INTENT = 0;
|
||||||
|
int INLINE_SLIDER = 1;
|
||||||
|
int INLINE_SWITCH = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResultPayload.PayloadType public abstract int getType();
|
||||||
|
}
|
||||||
41
src/com/android/settings/search2/SearchActivity.java
Normal file
41
src/com/android/settings/search2/SearchActivity.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.app.Activity;
|
||||||
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
public class SearchActivity extends Activity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.search_main);
|
||||||
|
|
||||||
|
FragmentManager fragmentManager = getFragmentManager();
|
||||||
|
Fragment fragment = fragmentManager.findFragmentById(R.id.main_content);
|
||||||
|
if (fragment == null) {
|
||||||
|
fragmentManager.beginTransaction()
|
||||||
|
.add(R.id.main_content, new SearchFragment())
|
||||||
|
.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/com/android/settings/search2/SearchFeatureProvider.java
Normal file
38
src/com/android/settings/search2/SearchFeatureProvider.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.app.Activity;
|
||||||
|
import android.widget.SearchView;
|
||||||
|
import android.view.Menu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FeatureProvider for Settings Search
|
||||||
|
*/
|
||||||
|
public interface SearchFeatureProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true to use the new version of search
|
||||||
|
*/
|
||||||
|
boolean isEnabled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts the Menu items into Settings activity.
|
||||||
|
* @param menu Items will be inserted into this menu.
|
||||||
|
* @param activity The activity that precedes SearchActivity.
|
||||||
|
*/
|
||||||
|
void setUpSearchMenu(Menu menu, Activity activity);
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.widget.SearchView;
|
||||||
|
import android.view.Menu;
|
||||||
|
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FeatureProvider for the refactored search code.
|
||||||
|
*/
|
||||||
|
public class SearchFeatureProviderImpl implements SearchFeatureProvider {
|
||||||
|
protected Context mContext;
|
||||||
|
|
||||||
|
|
||||||
|
public SearchFeatureProviderImpl(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUpSearchMenu(Menu menu, final Activity activity) {
|
||||||
|
if (menu == null || activity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String menuTitle = mContext.getString(R.string.search_menu);
|
||||||
|
MenuItem menuItem = menu.add(Menu.NONE, Menu.NONE, Menu.NONE, menuTitle)
|
||||||
|
.setIcon(R.drawable.abc_ic_search_api_material)
|
||||||
|
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
Intent intent = new Intent(activity, SearchActivity.class);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||||
|
}
|
||||||
|
}
|
||||||
158
src/com/android/settings/search2/SearchFragment.java
Normal file
158
src/com/android/settings/search2/SearchFragment.java
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.app.Activity;
|
||||||
|
import android.content.Loader;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.app.LoaderManager;
|
||||||
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.widget.SearchView;
|
||||||
|
|
||||||
|
import com.android.internal.logging.nano.MetricsProto;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.core.InstrumentedFragment;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SearchFragment extends InstrumentedFragment implements
|
||||||
|
SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener,
|
||||||
|
LoaderManager.LoaderCallbacks<List<SearchResult>> {
|
||||||
|
|
||||||
|
private static final int DATABASE_LOADER_ID = 0;
|
||||||
|
|
||||||
|
private SearchResultsAdapter mSearchAdapter;
|
||||||
|
|
||||||
|
private DatabaseResultLoader mSearchLoader;
|
||||||
|
|
||||||
|
private RecyclerView mResultsRecyclerView;
|
||||||
|
private SearchView mSearchView;
|
||||||
|
private MenuItem mSearchMenuItem;
|
||||||
|
|
||||||
|
private String mQuery;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
|
mSearchAdapter = new SearchResultsAdapter();
|
||||||
|
|
||||||
|
final LoaderManager loaderManager = getLoaderManager();
|
||||||
|
loaderManager.initLoader(DATABASE_LOADER_ID, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
final View view = inflater.inflate(R.layout.search_panel_2, container, false);
|
||||||
|
mResultsRecyclerView = (RecyclerView) view.findViewById(R.id.list_results);
|
||||||
|
|
||||||
|
mResultsRecyclerView.setAdapter(mSearchAdapter);
|
||||||
|
mResultsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
inflater.inflate(R.menu.search_options_menu, menu);
|
||||||
|
|
||||||
|
|
||||||
|
mSearchMenuItem = menu.findItem(R.id.search);
|
||||||
|
|
||||||
|
mSearchView = (SearchView) mSearchMenuItem.getActionView();
|
||||||
|
mSearchView.setOnQueryTextListener(this);
|
||||||
|
mSearchView.setMaxWidth(Integer.MAX_VALUE);
|
||||||
|
mSearchMenuItem.expandActionView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||||
|
// Return false to prevent the search box from collapsing.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextChange(String query) {
|
||||||
|
if (query == null || query.equals(mQuery)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mQuery = query;
|
||||||
|
clearLoaders();
|
||||||
|
|
||||||
|
final LoaderManager loaderManager = getLoaderManager();
|
||||||
|
loaderManager.restartLoader(DATABASE_LOADER_ID, null, this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onQueryTextSubmit(String query) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Loader<List<SearchResult>> onCreateLoader(int id, Bundle args) {
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case DATABASE_LOADER_ID:
|
||||||
|
mSearchLoader = new DatabaseResultLoader(activity, mQuery);
|
||||||
|
return mSearchLoader;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<List<SearchResult>> loader, List<SearchResult> data) {
|
||||||
|
if (data == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSearchAdapter.mergeResults(data, loader.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(Loader<List<SearchResult>> loader) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return MetricsProto.MetricsEvent.DASHBOARD_SEARCH_RESULTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearLoaders() {
|
||||||
|
if (mSearchLoader != null) {
|
||||||
|
mSearchLoader.cancelLoad();
|
||||||
|
mSearchLoader = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
146
src/com/android/settings/search2/SearchResult.java
Normal file
146
src/com/android/settings/search2/SearchResult.java
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dataclass as an interface for all Search Results.
|
||||||
|
*/
|
||||||
|
public class SearchResult implements Comparable<SearchResult> {
|
||||||
|
@Override
|
||||||
|
public int compareTo(SearchResult searchResult) {
|
||||||
|
if (searchResult == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return this.rank - searchResult.rank;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
protected String mTitle;
|
||||||
|
protected String mSummary;
|
||||||
|
protected ArrayList<String> mBreadcrumbs;
|
||||||
|
protected int mRank = -1;
|
||||||
|
protected ResultPayload mResultPayload;
|
||||||
|
protected Drawable mIcon;
|
||||||
|
|
||||||
|
public Builder addTitle(String title) {
|
||||||
|
mTitle = title;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addSummary(String summary) {
|
||||||
|
mSummary = summary;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addBreadcrumbs(ArrayList<String> breadcrumbs) {
|
||||||
|
mBreadcrumbs = breadcrumbs;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addRank(int rank) {
|
||||||
|
if (rank < 0 || rank > 9) {
|
||||||
|
rank = 42;
|
||||||
|
}
|
||||||
|
mRank = rank;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addIcon(Drawable icon) {
|
||||||
|
mIcon = icon;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder addPayload(ResultPayload payload) {
|
||||||
|
mResultPayload = payload;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SearchResult build() {
|
||||||
|
// Check that all of the mandatory fields are set.
|
||||||
|
if (mTitle == null) {
|
||||||
|
throw new IllegalArgumentException("SearchResult missing title argument");
|
||||||
|
} else if (mSummary == null ) {
|
||||||
|
throw new IllegalArgumentException("SearchResult missing summary argument");
|
||||||
|
} else if (mBreadcrumbs == null){
|
||||||
|
throw new IllegalArgumentException("SearchResult missing breadcrumbs argument");
|
||||||
|
} else if (mRank == -1) {
|
||||||
|
throw new IllegalArgumentException("SearchResult missing rank argument");
|
||||||
|
} else if (mIcon == null) {
|
||||||
|
throw new IllegalArgumentException("SearchResult missing icon argument");
|
||||||
|
} else if (mResultPayload == null) {
|
||||||
|
throw new IllegalArgumentException("SearchResult missing Payload argument");
|
||||||
|
}
|
||||||
|
return new SearchResult(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The title of the result and main text displayed.
|
||||||
|
* Intent Results: Displays as the primary
|
||||||
|
*/
|
||||||
|
public final String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Summary / subtitle text
|
||||||
|
* Intent Results: Displays the text underneath the title
|
||||||
|
*/
|
||||||
|
final public String summary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ordered list of the information hierarchy.
|
||||||
|
* Intent Results: Displayed a hierarchy of selections to reach the setting from the home screen
|
||||||
|
*/
|
||||||
|
public final ArrayList<String> breadcrumbs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A suggestion for the ranking of the result.
|
||||||
|
* Based on Settings Rank:
|
||||||
|
* 1 is a near perfect match
|
||||||
|
* 9 is the weakest match
|
||||||
|
* TODO subject to change
|
||||||
|
*/
|
||||||
|
public final int rank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier for the recycler view adapter.
|
||||||
|
*/
|
||||||
|
@ResultPayload.PayloadType public final int viewType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata for the specific result types.
|
||||||
|
*/
|
||||||
|
public final ResultPayload payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result's icon.
|
||||||
|
*/
|
||||||
|
public final Drawable icon;
|
||||||
|
|
||||||
|
private SearchResult(Builder builder) {
|
||||||
|
title = builder.mTitle;
|
||||||
|
summary = builder.mSummary;
|
||||||
|
breadcrumbs = builder.mBreadcrumbs;
|
||||||
|
rank = builder.mRank;
|
||||||
|
icon = builder.mIcon;
|
||||||
|
payload = builder.mResultPayload;
|
||||||
|
viewType = payload.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/com/android/settings/search2/SearchResultsAdapter.java
Normal file
101
src/com/android/settings/search2/SearchResultsAdapter.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.support.annotation.VisibleForTesting;
|
||||||
|
import android.support.v7.widget.RecyclerView.Adapter;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.search2.ResultPayload.PayloadType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SearchResultsAdapter extends Adapter<SearchViewHolder> {
|
||||||
|
private ArrayList<SearchResult> mSearchResults;
|
||||||
|
private HashMap<String, List<SearchResult>> mResultsMap;
|
||||||
|
|
||||||
|
public SearchResultsAdapter() {
|
||||||
|
mSearchResults = new ArrayList<>();
|
||||||
|
mResultsMap = new HashMap<>();
|
||||||
|
|
||||||
|
setHasStableIds(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mergeResults(List<SearchResult> freshResults, String loaderClassName) {
|
||||||
|
if (freshResults == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mResultsMap.put(loaderClassName, freshResults);
|
||||||
|
mSearchResults = mergeMappedResults();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<SearchResult> mergeMappedResults() {
|
||||||
|
ArrayList<SearchResult> mergedResults = new ArrayList<>();
|
||||||
|
for(String key : mResultsMap.keySet()) {
|
||||||
|
mergedResults.addAll(mResultsMap.get(key));
|
||||||
|
}
|
||||||
|
return mergedResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
|
||||||
|
switch(viewType) {
|
||||||
|
case PayloadType.INTENT:
|
||||||
|
View view = inflater.inflate(R.layout.search_intent_item, parent, false);
|
||||||
|
return new IntentSearchViewHolder(view);
|
||||||
|
case PayloadType.INLINE_SLIDER:
|
||||||
|
return null;
|
||||||
|
case PayloadType.INLINE_SWITCH:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(SearchViewHolder holder, int position) {
|
||||||
|
SearchResult result = mSearchResults.get(position);
|
||||||
|
holder.onBind(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return super.getItemId(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
return mSearchResults.get(position).viewType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mSearchResults.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public ArrayList<SearchResult> getSearchResults() {
|
||||||
|
return mSearchResults;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/com/android/settings/search2/SearchViewHolder.java
Normal file
33
src/com/android/settings/search2/SearchViewHolder.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ViewHolder for the Search RecyclerView.
|
||||||
|
* There are multiple search result types in the same Recycler view with different UI requirements.
|
||||||
|
* Some examples include Intent results, Inline results, and Help articles.
|
||||||
|
*/
|
||||||
|
public abstract class SearchViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
public SearchViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void onBind(SearchResult result);
|
||||||
|
}
|
||||||
@@ -64,6 +64,10 @@ public class SettingsRobolectricTestRunner extends RobolectricTestRunner {
|
|||||||
getPackageName(),
|
getPackageName(),
|
||||||
Fs.fileFromPath("./frameworks/base/packages/SettingsLib/res"),
|
Fs.fileFromPath("./frameworks/base/packages/SettingsLib/res"),
|
||||||
null));
|
null));
|
||||||
|
paths.add(new ResourcePath(
|
||||||
|
getPackageName(),
|
||||||
|
Fs.fileFromPath("./frameworks/base/core/res/res"),
|
||||||
|
null));
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.DatabaseResultLoader;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.ResultPayload;
|
||||||
|
import com.android.settings.search2.ResultPayload.PayloadType;
|
||||||
|
import com.android.settings.search2.SearchResult;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.Robolectric;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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 DatabaseResultLoaderTest {
|
||||||
|
private DatabaseResultLoader mLoader;
|
||||||
|
|
||||||
|
private static final String[] TITLES = new String[] {"title1", "title2", "title3"};
|
||||||
|
private static final String SUMMARY = "SUMMARY";
|
||||||
|
private static final int EXAMPLES = 3;
|
||||||
|
private static final Intent mIntent = new Intent("com.android.settings");
|
||||||
|
private static final int mIcon = R.drawable.ic_search_history;
|
||||||
|
|
||||||
|
private Drawable mDrawable;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
Context context = Robolectric.buildActivity(Activity.class).get();
|
||||||
|
mDrawable = context.getDrawable(mIcon);
|
||||||
|
mLoader = new DatabaseResultLoader(context, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseNullResults_ReturnsNull() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(null);
|
||||||
|
assertThat(results).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_NotNull() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
assertThat(results).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesRank() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
assertThat(results.get(i).rank).isEqualTo(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesTitle() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
assertThat(results.get(i).title).isEqualTo(TITLES[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesSummary() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
assertThat(results.get(i).summary).isEqualTo(SUMMARY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesIcon() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
Drawable resultDrawable = results.get(i).icon;
|
||||||
|
assertThat(resultDrawable.toString()).isEqualTo(mDrawable.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesPayloadType() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
ResultPayload payload;
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
payload = results.get(i).payload;
|
||||||
|
assertThat(payload.getType()).isEqualTo(PayloadType.INTENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseCursor_MatchesIntentPayload() {
|
||||||
|
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||||
|
IntentPayload payload;
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
payload = (IntentPayload) results.get(i).payload;
|
||||||
|
Intent intent = payload.intent;
|
||||||
|
assertThat(intent.getAction()).isEqualTo(mIntent.getAction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MatrixCursor getDummyCursor() {
|
||||||
|
String[] columns = new String[] {"rank", "title", "summary_on", "summary off", "entries",
|
||||||
|
"keywords", "class name", "screen title", "icon", "intent action",
|
||||||
|
"target package", "target class", "enabled", "key", "user id"};
|
||||||
|
MatrixCursor cursor = new MatrixCursor(columns);
|
||||||
|
final String BLANK = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < EXAMPLES; i++) {
|
||||||
|
ArrayList<String> item = new ArrayList<>(columns.length);
|
||||||
|
item.add(Integer.toString(i));
|
||||||
|
item.add(TITLES[i]);
|
||||||
|
item.add(SUMMARY);
|
||||||
|
item.add(BLANK); // summary off
|
||||||
|
item.add(BLANK); // entries
|
||||||
|
item.add(BLANK); // keywords
|
||||||
|
item.add(BLANK); // classname
|
||||||
|
item.add(BLANK); // screen title
|
||||||
|
item.add(Integer.toString(mIcon));
|
||||||
|
item.add(mIntent.getAction());
|
||||||
|
item.add(BLANK); // target package
|
||||||
|
item.add(BLANK); // target class
|
||||||
|
item.add(BLANK); // enabled
|
||||||
|
item.add(BLANK); // key
|
||||||
|
item.add(BLANK); // user id
|
||||||
|
|
||||||
|
cursor.addRow(item);
|
||||||
|
}
|
||||||
|
return cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.InlineSliderPayload;
|
||||||
|
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 InlineSliderPayloadTest {
|
||||||
|
private InlineSliderPayload mPayload;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParcelOrdering_StaysValid() {
|
||||||
|
Uri uri = Uri.parse("http://www.TESTURI.com");
|
||||||
|
Parcel parcel = Parcel.obtain();
|
||||||
|
|
||||||
|
mPayload = new InlineSliderPayload(uri);
|
||||||
|
mPayload.writeToParcel(parcel, 0);
|
||||||
|
// Reset parcel for reading
|
||||||
|
parcel.setDataPosition(0);
|
||||||
|
InlineSliderPayload newPayload = InlineSliderPayload.CREATOR.createFromParcel(parcel);
|
||||||
|
|
||||||
|
String originalUri = mPayload.uri.toString();
|
||||||
|
String copiedUri = newPayload.uri.toString();
|
||||||
|
assertThat(originalUri).isEqualTo(copiedUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
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 IntentPayloadTest {
|
||||||
|
private IntentPayload mPayload;
|
||||||
|
|
||||||
|
private final String EXTRA_KEY = "key";
|
||||||
|
private final String EXTRA_VALUE = "value";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParcelOrdering_StaysValid() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_KEY, EXTRA_VALUE);
|
||||||
|
Parcel parcel = Parcel.obtain();
|
||||||
|
|
||||||
|
mPayload = new IntentPayload(intent);
|
||||||
|
mPayload.writeToParcel(parcel, 0);
|
||||||
|
// Reset parcel for reading
|
||||||
|
parcel.setDataPosition(0);
|
||||||
|
IntentPayload newPayload = IntentPayload.CREATOR.createFromParcel(parcel);
|
||||||
|
|
||||||
|
String originalIntentExtra = mPayload.intent.getStringExtra(EXTRA_KEY);
|
||||||
|
String copiedIntentExtra = newPayload.intent.getStringExtra(EXTRA_KEY);
|
||||||
|
assertThat(originalIntentExtra).isEqualTo(copiedIntentExtra);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.IntentSearchViewHolder;
|
||||||
|
import com.android.settings.search2.SearchResult.Builder;
|
||||||
|
import com.android.settings.search2.SearchResult;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class IntentSearchViewHolderTest {
|
||||||
|
private IntentSearchViewHolder mHolder;
|
||||||
|
private static Drawable mIcon;
|
||||||
|
|
||||||
|
private static final String TITLE = "title";
|
||||||
|
private static final String SUMMARY = "summary";
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
final Context context = ShadowApplication.getInstance().getApplicationContext();
|
||||||
|
View view = LayoutInflater.from(context).inflate(R.layout.search_intent_item, null);
|
||||||
|
mHolder = new IntentSearchViewHolder(view);
|
||||||
|
|
||||||
|
mIcon = context.getDrawable(R.drawable.ic_search_history);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConstructor_MembersNotNull() {
|
||||||
|
assertThat(mHolder.titleView).isNotNull();
|
||||||
|
assertThat(mHolder.summaryView).isNotNull();
|
||||||
|
assertThat(mHolder.iconView).isNotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBindViewElements_AllUpdated() {
|
||||||
|
SearchResult result = getSearchResult();
|
||||||
|
mHolder.onBind(result);
|
||||||
|
|
||||||
|
assertThat(mHolder.titleView.getText()).isEqualTo(TITLE);
|
||||||
|
assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY);
|
||||||
|
assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SearchResult getSearchResult() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.addTitle(TITLE)
|
||||||
|
.addSummary(SUMMARY)
|
||||||
|
.addRank(1)
|
||||||
|
.addPayload(new IntentPayload(null))
|
||||||
|
.addBreadcrumbs(new ArrayList<String>())
|
||||||
|
.addIcon(mIcon);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.*;
|
||||||
|
import com.android.settings.search2.SearchResult.Builder;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.Robolectric;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class SearchAdapterTest {
|
||||||
|
|
||||||
|
private SearchResultsAdapter mAdapter;
|
||||||
|
private Context mContext;
|
||||||
|
private String mLoaderClassName;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = Robolectric.buildActivity(Activity.class).get();
|
||||||
|
mAdapter = new SearchResultsAdapter();
|
||||||
|
mLoaderClassName = DatabaseResultLoader.class.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<SearchResult> getIntentSampleResults() {
|
||||||
|
ArrayList<SearchResult> sampleResults = new ArrayList<>();
|
||||||
|
ArrayList<String> breadcrumbs = new ArrayList<>();
|
||||||
|
final Drawable icon = mContext.getDrawable(R.drawable.ic_search_history);
|
||||||
|
final ResultPayload payload = new IntentPayload(null);
|
||||||
|
|
||||||
|
SearchResult.Builder builder = new Builder();
|
||||||
|
builder.addTitle("title")
|
||||||
|
.addSummary("summary")
|
||||||
|
.addRank(1)
|
||||||
|
.addBreadcrumbs(breadcrumbs)
|
||||||
|
.addIcon(icon)
|
||||||
|
.addPayload(payload);
|
||||||
|
sampleResults.add(builder.build());
|
||||||
|
|
||||||
|
builder.addRank(2);
|
||||||
|
sampleResults.add(builder.build());
|
||||||
|
|
||||||
|
builder.addRank(3);
|
||||||
|
sampleResults.add(builder.build());
|
||||||
|
return sampleResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoResultsAdded_EmptyListReturned() {
|
||||||
|
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
|
assertThat(updatedResults).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleSourceMerge_ExactCopyReturned() {
|
||||||
|
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
||||||
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
|
|
||||||
|
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
|
assertThat(updatedResults).containsAllIn(intentResults);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDuplicateSourceMerge_ExactCopyReturned() {
|
||||||
|
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
||||||
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
|
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||||
|
|
||||||
|
ArrayList<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||||
|
assertThat(updatedResults).containsAllIn(intentResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.view.Menu;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settings.search2.SearchFeatureProviderImpl;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.Robolectric;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class SearchFeatureProviderImplTest {
|
||||||
|
private SearchFeatureProviderImpl mProvider;
|
||||||
|
private Activity mActivity;
|
||||||
|
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private Menu menu;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mActivity = Robolectric.buildActivity(Activity.class).create().visible().get();
|
||||||
|
mProvider = (SearchFeatureProviderImpl) FeatureFactory.getFactory(mActivity)
|
||||||
|
.getSearchFeatureProvider(mActivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPassNull_NoError() {
|
||||||
|
mProvider.setUpSearchMenu(null,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetUpMenu_HasItemAdded() {
|
||||||
|
mProvider.setUpSearchMenu(menu, mActivity);
|
||||||
|
|
||||||
|
verify(menu).add(anyInt(),anyInt(), anyInt(), anyString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.search;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settings.search2.IntentPayload;
|
||||||
|
import com.android.settings.search2.ResultPayload;
|
||||||
|
import com.android.settings.search2.SearchResult;
|
||||||
|
import com.android.settings.search2.SearchResult.Builder;
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadows.ShadowApplication;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class SearchResultBuilderTest {
|
||||||
|
|
||||||
|
private Builder mBuilder;
|
||||||
|
private String mTitle;
|
||||||
|
private String mSummary;
|
||||||
|
private ArrayList<String> mBreadcrumbs;
|
||||||
|
private int mRank;
|
||||||
|
private ResultPayload mResultPayload;
|
||||||
|
private Drawable mIcon;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mBuilder = new Builder();
|
||||||
|
mTitle = "title";
|
||||||
|
mSummary = "summary";
|
||||||
|
mBreadcrumbs = new ArrayList<>();
|
||||||
|
mRank = 3;
|
||||||
|
mResultPayload = new IntentPayload(null);
|
||||||
|
|
||||||
|
final Context context = ShadowApplication.getInstance().getApplicationContext();
|
||||||
|
mIcon = context.getDrawable(R.drawable.ic_search_history);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAllInfo_BuildSearchResult() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addSummary(mSummary)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addIcon(mIcon)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
SearchResult result = mBuilder.build();
|
||||||
|
|
||||||
|
assertThat(result).isNotNull();
|
||||||
|
assertThat(result.title).isEqualTo(mTitle);
|
||||||
|
assertThat(result.summary).isEqualTo(mSummary);
|
||||||
|
assertThat(result.rank).isEqualTo(mRank);
|
||||||
|
assertThat(result.breadcrumbs).isEqualTo(mBreadcrumbs);
|
||||||
|
assertThat(result.icon).isEqualTo(mIcon);
|
||||||
|
assertThat(result.payload).isEqualTo(mResultPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoTitle_BuildSearchResultException() {
|
||||||
|
mBuilder.addSummary(mSummary)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addIcon(mIcon)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoSummary_BuildSearchResultException() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addIcon(mIcon)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoRank_BuildSearchResultException() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addSummary(mSummary)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addIcon(mIcon)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoBreadcrumbs_BuildSearchResultException() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addSummary(mSummary)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addIcon(mIcon)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoIcon_BuildSearchResultException() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addSummary(mSummary)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addPayload(mResultPayload);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoPayload_BuildSearchResultException() {
|
||||||
|
mBuilder.addTitle(mTitle)
|
||||||
|
.addSummary(mSummary)
|
||||||
|
.addRank(mRank)
|
||||||
|
.addBreadcrumbs(mBreadcrumbs)
|
||||||
|
.addIcon(mIcon);
|
||||||
|
|
||||||
|
SearchResult result = null;
|
||||||
|
try {
|
||||||
|
result = mBuilder.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// passes.
|
||||||
|
}
|
||||||
|
assertThat(result).isNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
|||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settings.overlay.SupportFeatureProvider;
|
import com.android.settings.overlay.SupportFeatureProvider;
|
||||||
|
import com.android.settings.search2.SearchFeatureProvider;
|
||||||
|
|
||||||
import static org.mockito.Matchers.anyString;
|
import static org.mockito.Matchers.anyString;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -43,6 +44,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public final LocaleFeatureProvider localeFeatureProvider;
|
public final LocaleFeatureProvider localeFeatureProvider;
|
||||||
public final ApplicationFeatureProvider applicationFeatureProvider;
|
public final ApplicationFeatureProvider applicationFeatureProvider;
|
||||||
public final EnterprisePrivacyFeatureProvider enterprisePrivacyFeatureProvider;
|
public final EnterprisePrivacyFeatureProvider enterprisePrivacyFeatureProvider;
|
||||||
|
public final SearchFeatureProvider searchFeatureProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this in {@code @Before} method of the test class to use fake factory.
|
* Call this in {@code @Before} method of the test class to use fake factory.
|
||||||
@@ -72,6 +74,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
localeFeatureProvider = mock(LocaleFeatureProvider.class);
|
localeFeatureProvider = mock(LocaleFeatureProvider.class);
|
||||||
applicationFeatureProvider = mock(ApplicationFeatureProvider.class);
|
applicationFeatureProvider = mock(ApplicationFeatureProvider.class);
|
||||||
enterprisePrivacyFeatureProvider = mock(EnterprisePrivacyFeatureProvider.class);
|
enterprisePrivacyFeatureProvider = mock(EnterprisePrivacyFeatureProvider.class);
|
||||||
|
searchFeatureProvider = mock(SearchFeatureProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -108,4 +111,9 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
|
public EnterprisePrivacyFeatureProvider getEnterprisePrivacyFeatureProvider(Context context) {
|
||||||
return enterprisePrivacyFeatureProvider;
|
return enterprisePrivacyFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SearchFeatureProvider getSearchFeatureProvider(Context context) {
|
||||||
|
return searchFeatureProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user