diff --git a/res/layout/search_inline_switch_item.xml b/res/layout/search_inline_switch_item.xml new file mode 100644 index 00000000000..998c09c30d9 --- /dev/null +++ b/res/layout/search_inline_switch_item.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/search_intent_item.xml b/res/layout/search_intent_item.xml index b68f65b23c6..fcb5532460f 100644 --- a/res/layout/search_intent_item.xml +++ b/res/layout/search_intent_item.xml @@ -14,50 +14,59 @@ limitations under the License. --> - - - - - - + - - - - - + android:minWidth="60dp" + android:gravity="start|center_vertical" + android:orientation="horizontal" + android:paddingEnd="12dp" + android:paddingTop="4dp" + android:paddingBottom="4dp"> + + + + + + + + diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java index cb368790b4a..213259be012 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java @@ -20,7 +20,10 @@ import android.content.Context; import android.provider.Settings; import android.support.v7.preference.Preference; +import android.util.ArrayMap; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; public class DoubleTapPowerPreferenceController extends GesturePreferenceController { @@ -61,4 +64,14 @@ public class DoubleTapPowerPreferenceController extends GesturePreferenceControl Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0); return cameraDisabled == 0; } + + @Override + public ResultPayload getResultPayload() { + ArrayMap valueMap = new ArrayMap<>(); + valueMap.put(0, true); + valueMap.put(1, false); + + return new InlineSwitchPayload(Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + ResultPayload.SettingsSource.SECURE, valueMap); + } } diff --git a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java index 722d66aaaa2..02d8dd73b01 100644 --- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java @@ -21,8 +21,11 @@ import android.content.Context; import android.provider.Settings; import android.support.v7.preference.Preference; +import android.util.ArrayMap; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; public class DoubleTapScreenPreferenceController extends GesturePreferenceController { @@ -67,4 +70,14 @@ public class DoubleTapScreenPreferenceController extends GesturePreferenceContro protected boolean isSwitchPrefEnabled() { return mAmbientConfig.pulseOnDoubleTapEnabled(mUserId); } + + @Override + public ResultPayload getResultPayload() { + ArrayMap valueMap = new ArrayMap<>(); + valueMap.put(1, true); + valueMap.put(0, false); + + return new InlineSwitchPayload(Settings.Secure.DOZE_PULSE_ON_DOUBLE_TAP, + ResultPayload.SettingsSource.SECURE, valueMap); + } } diff --git a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java index 5192484cd2e..fea1c9dab18 100644 --- a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java @@ -24,8 +24,11 @@ import android.provider.Settings; import android.support.v7.preference.Preference; import android.text.TextUtils; +import android.util.ArrayMap; import com.android.settings.R; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; public class DoubleTwistPreferenceController extends GesturePreferenceController { @@ -82,4 +85,14 @@ public class DoubleTwistPreferenceController extends GesturePreferenceController } return false; } + + @Override + public ResultPayload getResultPayload() { + ArrayMap valueMap = new ArrayMap<>(); + valueMap.put(1, true); + valueMap.put(0, false); + + return new InlineSwitchPayload(Settings.Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, + ResultPayload.SettingsSource.SECURE, valueMap); + } } diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java index 98ed5fb5ff4..9b71b96fea0 100644 --- a/src/com/android/settings/gestures/GestureSettings.java +++ b/src/com/android/settings/gestures/GestureSettings.java @@ -167,21 +167,32 @@ public class GestureSettings extends DashboardFragment { @Override public List getNonIndexableKeys(Context context) { ArrayList result = new ArrayList(); + + List preferenceControllers = + getPreferenceControllers(context); + for(PreferenceController controller : preferenceControllers) { + controller.updateNonIndexableKeys(result); + } + return result; + } + + @Override + public List getPreferenceControllers(Context context) { + List controllers = new ArrayList<>(); AmbientDisplayConfiguration ambientConfig = new AmbientDisplayConfiguration(context); - new DoubleTapPowerPreferenceController(context, null /* lifecycle */) - .updateNonIndexableKeys(result); - new PickupGesturePreferenceController( - context, null /* lifecycle */, ambientConfig, UserHandle.myUserId()) - .updateNonIndexableKeys(result); - new DoubleTapScreenPreferenceController( - context, null /* lifecycle */, ambientConfig, UserHandle.myUserId()) - .updateNonIndexableKeys(result); - new SwipeToNotificationPreferenceController(context, null /* lifecycle */) - .updateNonIndexableKeys(result); - new DoubleTwistPreferenceController(context, null /* lifecycle */) - .updateNonIndexableKeys(result); - return result; + + controllers.add(new DoubleTapPowerPreferenceController(context, + null /* lifecycle */)); + controllers.add(new PickupGesturePreferenceController(context, + null /* lifecycle */, ambientConfig, UserHandle.myUserId())); + controllers.add(new DoubleTapScreenPreferenceController(context, + null /* lifecycle */, ambientConfig, UserHandle.myUserId())); + controllers.add(new SwipeToNotificationPreferenceController(context, + null /* lifecycle */)); + controllers.add(new DoubleTwistPreferenceController(context, + null /* lifecycle */)); + return controllers; } }; } diff --git a/src/com/android/settings/gestures/PickupGesturePreferenceController.java b/src/com/android/settings/gestures/PickupGesturePreferenceController.java index 225e1d06932..f48551e7c8b 100644 --- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java +++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java @@ -21,8 +21,11 @@ import android.content.Context; import android.provider.Settings; import android.support.v7.preference.Preference; +import android.util.ArrayMap; import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; public class PickupGesturePreferenceController extends GesturePreferenceController { @@ -68,4 +71,13 @@ public class PickupGesturePreferenceController extends GesturePreferenceControll return true; } + @Override + public ResultPayload getResultPayload() { + ArrayMap valueMap = new ArrayMap<>(); + valueMap.put(1, true); + valueMap.put(0, false); + + return new InlineSwitchPayload(Settings.Secure.DOZE_PULSE_ON_PICK_UP, + ResultPayload.SettingsSource.SECURE, valueMap); + } } diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java index 08dc614f2c6..67c8e142ad6 100644 --- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java +++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java @@ -20,7 +20,10 @@ import android.content.Context; import android.provider.Settings; import android.support.v7.preference.Preference; +import android.util.ArrayMap; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; public class SwipeToNotificationPreferenceController extends GesturePreferenceController { @@ -60,4 +63,14 @@ public class SwipeToNotificationPreferenceController extends GesturePreferenceCo Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1; } + + @Override + public ResultPayload getResultPayload() { + ArrayMap valueMap = new ArrayMap<>(); + valueMap.put(1, true); + valueMap.put(0, false); + + return new InlineSwitchPayload(Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, + ResultPayload.SettingsSource.SECURE, valueMap); + } } diff --git a/src/com/android/settings/search2/CursorToSearchResultConverter.java b/src/com/android/settings/search2/CursorToSearchResultConverter.java new file mode 100644 index 00000000000..3d293233007 --- /dev/null +++ b/src/com/android/settings/search2/CursorToSearchResultConverter.java @@ -0,0 +1,190 @@ +/* + * 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.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.drawable.Drawable; +import android.os.BadParcelableException; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import com.android.settings.SettingsActivity; +import com.android.settings.Utils; +import com.android.settings.search.Index; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_RANK; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_TITLE; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_SUMMARY_ON; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_CLASS_NAME; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_ICON; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_INTENT_ACTION; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_KEY; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD_TYPE; +import static com.android.settings.search2.DatabaseResultLoader.COLUMN_INDEX_PAYLOAD; + +/** + * Controller to Build search results from {@link Cursor} Objects. + * + * Each converted {@link Cursor} has the following fields: + * - String Title + * - String Summary + * - int rank + * - {@link Drawable} icon + * - {@link ResultPayload} payload + */ +class CursorToSearchResultConverter { + + private final String TAG = "CursorConverter"; + + private final Context mContext; + + public CursorToSearchResultConverter(Context context) { + mContext = context; + } + + public List convertCursor(Cursor cursorResults) { + if (cursorResults == null) { + return null; + } + final Map contextMap = new HashMap<>(); + final ArrayList results = new ArrayList<>(); + + while (cursorResults.moveToNext()) { + SearchResult result = buildSingleSearchResultFromCursor(contextMap, cursorResults); + if (result != null) { + results.add(result); + } + } + Collections.sort(results); + return results; + } + + private SearchResult buildSingleSearchResultFromCursor(Map contextMap, + Cursor cursor) { + final String pkgName = cursor.getString(COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE); + final String action = cursor.getString(COLUMN_INDEX_INTENT_ACTION); + final String title = cursor.getString(COLUMN_INDEX_TITLE); + final String summaryOn = cursor.getString(COLUMN_INDEX_SUMMARY_ON); + final String className = cursor.getString(COLUMN_INDEX_CLASS_NAME); + final int rank = cursor.getInt(COLUMN_INDEX_RANK); + final String key = cursor.getString(COLUMN_INDEX_KEY); + final String iconResStr = cursor.getString(COLUMN_INDEX_ICON); + final int payloadType = cursor.getInt(COLUMN_INDEX_PAYLOAD_TYPE); + final byte[] marshalledPayload = cursor.getBlob(COLUMN_INDEX_PAYLOAD); + final ResultPayload payload; + + if (marshalledPayload != null) { + payload = getUnmarshalledPayload(marshalledPayload, payloadType); + } else if (payloadType == ResultPayload.PayloadType.INTENT) { + payload = getIntentPayload(cursor, action, key, className, pkgName); + } else { + Log.w(TAG, "Error creating payload - bad marshalling data or mismatched types"); + return null; + } + + final SearchResult.Builder builder = new SearchResult.Builder(); + builder.addTitle(title) + .addSummary(summaryOn) + .addRank(rank) + .addIcon(getIconForPackage(contextMap, pkgName, className, iconResStr)) + .addPayload(payload); + return builder.build(); + } + + private Drawable getIconForPackage(Map contextMap, String pkgName, + String className, String iconResStr) { + final int iconId = TextUtils.isEmpty(iconResStr) + ? 0 : Integer.parseInt(iconResStr); + Drawable icon; + Context packageContext; + if (iconId == 0) { + icon = null; + } else { + if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(pkgName)) { + packageContext = contextMap.get(pkgName); + if (packageContext == null) { + try { + packageContext = mContext.createPackageContext(pkgName, 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Cannot create Context for package: " + pkgName); + return null; + } + contextMap.put(pkgName, packageContext); + } + } else { + packageContext = mContext; + } + try { + icon = packageContext.getDrawable(iconId); + } catch (Resources.NotFoundException nfe) { + icon = null; + } + } + return icon; + } + + private IntentPayload getIntentPayload(Cursor cursor, String action, String key, + String className, String pkgName ) { + IntentPayload payload; + if (TextUtils.isEmpty(action)) { + final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE); + // Action is null, we will launch it as a sub-setting + final Bundle args = new Bundle(); + args.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key); + final Intent intent = Utils.onBuildStartFragmentIntent(mContext, + className, args, null, 0, screenTitle, false); + payload = new IntentPayload(intent); + } else { + final Intent intent = new Intent(action); + final String targetClass = cursor.getString( + Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS); + if (!TextUtils.isEmpty(pkgName) && !TextUtils.isEmpty(targetClass)) { + final ComponentName component = new ComponentName(pkgName, targetClass); + intent.setComponent(component); + } + intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key); + payload = new IntentPayload(intent); + } + return payload; + } + + private ResultPayload getUnmarshalledPayload(byte[] unmarshalledPayload, int payloadType) { + try { + switch (payloadType) { + case ResultPayload.PayloadType.INLINE_SWITCH: + return ResultPayloadUtils.unmarshall(unmarshalledPayload, + InlineSwitchPayload.CREATOR); + } + } catch (BadParcelableException e) { + Log.w(TAG, "Error creating parcelable: " + e); + } + return null; + } +} diff --git a/src/com/android/settings/search2/DatabaseIndexingUtils.java b/src/com/android/settings/search2/DatabaseIndexingUtils.java index c7a7f921f55..9fdf73218bc 100644 --- a/src/com/android/settings/search2/DatabaseIndexingUtils.java +++ b/src/com/android/settings/search2/DatabaseIndexingUtils.java @@ -66,6 +66,10 @@ public class DatabaseIndexingUtils { */ public static Map getPreferenceControllerUriMap( String className, Context context) { + if (context == null) { + return null; + } + final Class clazz = getIndexableClass(className); if (clazz == null) { @@ -77,6 +81,7 @@ public class DatabaseIndexingUtils { // Will be non null only for a Local provider implementing a // SEARCH_INDEX_DATA_PROVIDER field final Indexable.SearchIndexProvider provider = getSearchIndexProvider(clazz); + List controllers = provider.getPreferenceControllers(context); @@ -94,8 +99,9 @@ public class DatabaseIndexingUtils { } /** - * @param uriMap Map between the {@link PreferenceController} keys and the controllers themselves. - * @param key The look up key + * @param uriMap Map between the {@link PreferenceController} keys + * and the controllers themselves. + * @param key The look-up key * @return The Payload from the {@link PreferenceController} specified by the key, if it exists. * Otherwise null. */ @@ -135,15 +141,13 @@ public class DatabaseIndexingUtils { } catch (NoSuchFieldException e) { Log.d(TAG, "Cannot find field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); } catch (SecurityException se) { - Log.d(TAG, - "Security exception for field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); + Log.d(TAG, "Security exception for field '" + + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); } catch (IllegalAccessException e) { - Log.d(TAG, - "Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); + Log.d(TAG, "Illegal access to field '" + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); } catch (IllegalArgumentException e) { - Log.d(TAG, - "Illegal argument when accessing field '" + - FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); + Log.d(TAG, "Illegal argument when accessing field '" + + FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER + "'"); } return null; } diff --git a/src/com/android/settings/search2/DatabaseResultLoader.java b/src/com/android/settings/search2/DatabaseResultLoader.java index b268f6a1b6e..201d76f7440 100644 --- a/src/com/android/settings/search2/DatabaseResultLoader.java +++ b/src/com/android/settings/search2/DatabaseResultLoader.java @@ -48,14 +48,36 @@ import java.util.Map; public class DatabaseResultLoader extends AsyncLoader> { private static final String LOG = "DatabaseResultLoader"; private final String mQueryText; - private final Context mContext; + protected final SQLiteDatabase mDatabase; + private final CursorToSearchResultConverter mConverter; + + /* These indices are used to match the columns of the this loader's SELECT statement. + These are not necessarily the same order or coverage as the schema defined in + IndexDatabaseHelper */ + public static final int COLUMN_INDEX_RANK = 0; + public static final int COLUMN_INDEX_TITLE = 1; + public static final int COLUMN_INDEX_SUMMARY_ON = 2; + public static final int COLUMN_INDEX_SUMMARY_OFF = 3; + public static final int COLUMN_INDEX_ENTRIES = 4; + public static final int COLUMN_INDEX_KEYWORDS = 5; + public static final int COLUMN_INDEX_CLASS_NAME = 6; + public static final int COLUMN_INDEX_SCREEN_TITLE = 7; + public static final int COLUMN_INDEX_ICON = 8; + public static final int COLUMN_INDEX_INTENT_ACTION = 9; + public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE = 10; + public static final int COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS = 11; + public static final int COLUMN_INDEX_ENABLED = 12; + public static final int COLUMN_INDEX_KEY = 13; + public static final int COLUMN_INDEX_PAYLOAD_TYPE = 14; + public static final int COLUMN_INDEX_PAYLOAD = 15; + public DatabaseResultLoader(Context context, String queryText) { super(context); mDatabase = IndexDatabaseHelper.getInstance(context).getReadableDatabase(); mQueryText = queryText; - mContext = context; + mConverter = new CursorToSearchResultConverter(context); } @Override @@ -72,7 +94,7 @@ public class DatabaseResultLoader extends AsyncLoader> { String query = getSQLQuery(); Cursor result = mDatabase.rawQuery(query, null); - return parseCursorForSearch(result); + return mConverter.convertCursor(result); } @Override @@ -86,100 +108,12 @@ public class DatabaseResultLoader extends AsyncLoader> { "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_key_reference, payload_type, payload 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 parseCursorForSearch(Cursor cursorResults) { - if (cursorResults == null) { - return null; - } - final Map contextMap = new HashMap<>(); - final ArrayList results = new ArrayList<>(); - while (cursorResults.moveToNext()) { - SearchResult result = buildSingleSearchResultFromCursor(contextMap, cursorResults); - if (result != null) { - results.add(result); - } - } - Collections.sort(results); - return results; - } - - private SearchResult buildSingleSearchResultFromCursor(Map contextMap, - Cursor cursor) { - final String pkgName = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION_TARGET_PACKAGE); - final String action = cursor.getString(Index.COLUMN_INDEX_INTENT_ACTION); - final String title = cursor.getString(Index.COLUMN_INDEX_TITLE); - final String summaryOn = cursor.getString(Index.COLUMN_INDEX_SUMMARY_ON); - final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME); - final int rank = cursor.getInt(Index.COLUMN_INDEX_RANK); - final String key = cursor.getString(Index.COLUMN_INDEX_KEY); - final String iconResStr = cursor.getString(Index.COLUMN_INDEX_ICON); - - final ResultPayload payload; - if (TextUtils.isEmpty(action)) { - final String screenTitle = cursor.getString(Index.COLUMN_INDEX_SCREEN_TITLE); - // Action is null, we will launch it as a sub-setting - final Bundle args = new Bundle(); - args.putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key); - final Intent intent = Utils.onBuildStartFragmentIntent(mContext, - className, args, null, 0, screenTitle, false); - payload = new IntentPayload(intent); - } else { - final Intent intent = new Intent(action); - final String targetClass = cursor.getString( - Index.COLUMN_INDEX_INTENT_ACTION_TARGET_CLASS); - if (!TextUtils.isEmpty(pkgName) && !TextUtils.isEmpty(targetClass)) { - final ComponentName component = new ComponentName(pkgName, targetClass); - intent.setComponent(component); - } - intent.putExtra(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY, key); - payload = new IntentPayload(intent); - } - SearchResult.Builder builder = new SearchResult.Builder(); - builder.addTitle(title) - .addSummary(summaryOn) - .addRank(rank) - .addIcon(getIconForPackage(contextMap, pkgName, className, iconResStr)) - .addPayload(payload); - return builder.build(); - } - - private Drawable getIconForPackage(Map contextMap, String pkgName, - String className, String iconResStr) { - final int iconId = TextUtils.isEmpty(iconResStr) - ? 0 : Integer.parseInt(iconResStr); - Drawable icon; - Context packageContext; - if (iconId == 0) { - icon = null; - } else { - if (TextUtils.isEmpty(className) && !TextUtils.isEmpty(pkgName)) { - packageContext = contextMap.get(pkgName); - if (packageContext == null) { - try { - packageContext = mContext.createPackageContext(pkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(LOG, "Cannot create Context for package: " + pkgName); - return null; - } - contextMap.put(pkgName, packageContext); - } - } else { - packageContext = mContext; - } - try { - icon = packageContext.getDrawable(iconId); - } catch (Resources.NotFoundException nfe) { - icon = null; - } - } - return icon; - } } diff --git a/src/com/android/settings/search2/InlinePayload.java b/src/com/android/settings/search2/InlinePayload.java new file mode 100644 index 00000000000..4b1c168d4c6 --- /dev/null +++ b/src/com/android/settings/search2/InlinePayload.java @@ -0,0 +1,43 @@ +/* + * 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; + +/** + * Abstract Payload for inline settings results. + */ +public abstract class InlinePayload extends ResultPayload { + /** + * Defines the URI to access and store the Setting the inline result represents + */ + public String settingsUri; + + /** + * The UI type for the inline result. + */ + @PayloadType public int inlineType; + + /** + * Defines where the Setting is stored. + */ + @SettingsSource public int settingSource; + + public InlinePayload(String uri, @PayloadType int type, @SettingsSource int source) { + settingsUri = uri; + inlineType = type; + settingSource = source; + } +} diff --git a/src/com/android/settings/search2/InlineSliderPayload.java b/src/com/android/settings/search2/InlineSliderPayload.java deleted file mode 100644 index 8f08d5992bf..00000000000 --- a/src/com/android/settings/search2/InlineSliderPayload.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 CREATOR = new Creator() { - @Override - public InlineSliderPayload createFromParcel(Parcel in) { - return new InlineSliderPayload(in); - } - - @Override - public InlineSliderPayload[] newArray(int size) { - return new InlineSliderPayload[size]; - } - }; -} \ No newline at end of file diff --git a/src/com/android/settings/search2/InlineSwitchPayload.java b/src/com/android/settings/search2/InlineSwitchPayload.java new file mode 100644 index 00000000000..76fb0487290 --- /dev/null +++ b/src/com/android/settings/search2/InlineSwitchPayload.java @@ -0,0 +1,138 @@ +/* + * 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.os.Parcel; +import android.os.Parcelable; +import android.provider.Settings; +import android.util.ArrayMap; + +import java.util.Map; + +/** + * Payload for inline Switch results. Mappings from integer to boolean. + */ +public class InlineSwitchPayload extends InlinePayload { + /** + * Maps Inline values to UI-consumable Values. + * For example, if you have a switch preference whose values are stored as ints, the two valid + * list of mappings would be: + * < (0,True), (1, false) > + * < (1,True), (0, false) > + */ + public final Map valueMap; + + public InlineSwitchPayload(String newUri, @SettingsSource int settingsSource, + ArrayMap map) { + super(newUri, PayloadType.INLINE_SWITCH, settingsSource); + valueMap = map; + } + + private InlineSwitchPayload(Parcel in) { + super(in.readString() /* Uri */ , in.readInt() /* Payload Type */, + in.readInt() /* Settings Source */); + valueMap = in.readHashMap(Integer.class.getClassLoader()); + } + + @Override + public int getType() { + return inlineType; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(settingsUri); + dest.writeInt(inlineType); + dest.writeInt(settingSource); + dest.writeMap(valueMap); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public InlineSwitchPayload createFromParcel(Parcel in) { + return new InlineSwitchPayload(in); + } + + @Override + public InlineSwitchPayload[] newArray(int size) { + return new InlineSwitchPayload[size]; + } + }; + + public boolean getSwitchValue(Context context) { + if (valueMap == null) { + throw new IllegalStateException("Value map is null"); + } + + int settingsValue = -1; + switch(settingSource) { + case SettingsSource.SECURE: + settingsValue = Settings.Secure.getInt(context.getContentResolver(), + settingsUri, 0); + } + + if (settingsValue == -1) { + throw new IllegalStateException("Unable to find setting from uri: " + + settingsUri.toString()); + } + + for (Integer key : valueMap.keySet()) { + if ((key == settingsValue)) { + return valueMap.get(key); + } + } + + throw new IllegalStateException("No results matched the key: " + settingsValue); + } + + public void setSwitchValue(Context context, boolean isChecked) { + if (valueMap == null) { + throw new IllegalStateException("Value map is null"); + } + int switchValue = -1; + + for (Map.Entry pair : valueMap.entrySet()) { + if (pair.getValue() == isChecked) { + switchValue = pair.getKey(); + break; + } + } + + if (switchValue == -1) { + throw new IllegalStateException("Switch value is not set"); + } + + switch(settingSource) { + case SettingsSource.GLOBAL: + return; + case SettingsSource.SECURE: + Settings.Secure.putInt(context.getContentResolver(), settingsUri, switchValue); + case SettingsSource.SYSTEM: + return; + case SettingsSource.UNKNOWN: + return; + } + } +} diff --git a/src/com/android/settings/search2/InlineSwitchViewHolder.java b/src/com/android/settings/search2/InlineSwitchViewHolder.java new file mode 100644 index 00000000000..54d352353ac --- /dev/null +++ b/src/com/android/settings/search2/InlineSwitchViewHolder.java @@ -0,0 +1,73 @@ +/* + * 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.Fragment; +import android.util.Log; +import android.view.View; +import android.view.ViewParent; +import android.widget.CompoundButton; +import android.widget.Switch; +import android.widget.TextView; +import android.content.Context; + +import com.android.internal.widget.PreferenceImageView; +import com.android.settings.R; + +/** + * ViewHolder for Settings represented as SwitchPreferences. + */ +public class InlineSwitchViewHolder extends SearchViewHolder { + public final TextView titleView; + public final TextView summaryView; + public final PreferenceImageView iconView; + public final Switch switchView; + + private final Context mContext; + + private final String TAG = "SwitchViewHolder"; + + public InlineSwitchViewHolder(View view, Context context) { + super(view); + mContext = context; + titleView = (TextView) view.findViewById(android.R.id.title); + summaryView = (TextView) view.findViewById(android.R.id.summary); + iconView = (PreferenceImageView) view.findViewById(android.R.id.icon); + switchView = (Switch) view.findViewById(R.id.switchView); + } + + @Override + public void onBind(Fragment fragment, SearchResult result) { + if (mContext == null) { + return; + } + final InlineSwitchPayload payload = (InlineSwitchPayload) result.payload; + switchView.setChecked(payload.getSwitchValue(mContext)); + + switchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + payload.setSwitchValue(mContext, isChecked); + } + }); + + titleView.setText(result.title); + summaryView.setText(result.summary); + iconView.setImageDrawable(result.icon); + } +} diff --git a/src/com/android/settings/search2/IntentSearchViewHolder.java b/src/com/android/settings/search2/IntentSearchViewHolder.java index 0ef27d01f7b..da3f7240d8a 100644 --- a/src/com/android/settings/search2/IntentSearchViewHolder.java +++ b/src/com/android/settings/search2/IntentSearchViewHolder.java @@ -34,13 +34,13 @@ public class IntentSearchViewHolder extends SearchViewHolder { 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); + titleView = (TextView) view.findViewById(android.R.id.title); + summaryView = (TextView) view.findViewById(android.R.id.summary); + iconView = (ImageView) view.findViewById(android.R.id.icon); } @Override - public void onBind(Fragment fragment, SearchResult result) { + public void onBind(final Fragment fragment, final SearchResult result) { titleView.setText(result.title); summaryView.setText(result.summary); iconView.setImageDrawable(result.icon); diff --git a/src/com/android/settings/search2/ResultPayload.java b/src/com/android/settings/search2/ResultPayload.java index 84df7b6f65b..3842def2acd 100644 --- a/src/com/android/settings/search2/ResultPayload.java +++ b/src/com/android/settings/search2/ResultPayload.java @@ -28,7 +28,8 @@ import java.lang.annotation.RetentionPolicy; */ public abstract class ResultPayload implements Parcelable { - @IntDef({PayloadType.INLINE_SLIDER, PayloadType.INLINE_SWITCH, PayloadType.INTENT}) + @IntDef({PayloadType.INLINE_SLIDER, PayloadType.INLINE_SWITCH, + PayloadType.INTENT}) @Retention(RetentionPolicy.SOURCE) public @interface PayloadType { /** @@ -47,5 +48,16 @@ public abstract class ResultPayload implements Parcelable { int INLINE_SWITCH = 2; } + @IntDef({SettingsSource.UNKNOWN, SettingsSource.SYSTEM, SettingsSource.SECURE, + SettingsSource.GLOBAL}) + @Retention(RetentionPolicy.SOURCE) + public @interface SettingsSource { + int UNKNOWN = 0; + int SYSTEM = 1; + int SECURE = 2; + int GLOBAL = 3; + } + + @ResultPayload.PayloadType public abstract int getType(); } diff --git a/src/com/android/settings/search2/SearchResultsAdapter.java b/src/com/android/settings/search2/SearchResultsAdapter.java index b5884968747..c318b410a99 100644 --- a/src/com/android/settings/search2/SearchResultsAdapter.java +++ b/src/com/android/settings/search2/SearchResultsAdapter.java @@ -16,8 +16,10 @@ package com.android.settings.search2; +import android.content.Context; import android.support.annotation.VisibleForTesting; import android.support.v7.widget.RecyclerView.Adapter; +import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -26,7 +28,6 @@ import com.android.settings.R; import com.android.settings.search2.ResultPayload.PayloadType; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -38,22 +39,23 @@ public class SearchResultsAdapter extends Adapter { public SearchResultsAdapter(SearchFragment fragment) { mFragment = fragment; mSearchResults = new ArrayList<>(); - mResultsMap = new HashMap<>(); + mResultsMap = new ArrayMap<>(); setHasStableIds(true); } @Override public SearchViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); - switch (viewType) { + final Context context = parent.getContext(); + final LayoutInflater inflater = LayoutInflater.from(context); + final View view; + switch(viewType) { case PayloadType.INTENT: - View view = inflater.inflate(R.layout.search_intent_item, parent, false); + 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; + view = inflater.inflate(R.layout.search_inline_switch_item, parent, false); + return new InlineSwitchViewHolder(view, context); default: return null; } diff --git a/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java b/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java index bea9358cff4..ffa6d96f6ac 100644 --- a/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java +++ b/tests/robotests/src/com/android/internal/hardware/AmbientDisplayConfiguration.java @@ -17,6 +17,7 @@ package com.android.internal.hardware; import android.provider.Settings; +import android.content.Context; /** * Fake controller to make robolectric test compile. Should be removed when Robolectric supports @@ -24,6 +25,8 @@ import android.provider.Settings; */ public class AmbientDisplayConfiguration { + public AmbientDisplayConfiguration(Context context) {} + public boolean pulseOnPickupAvailable() { return false; } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java index 6a2e4ea0466..5f7d8b506e3 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java @@ -23,6 +23,8 @@ import android.support.v7.preference.PreferenceScreen; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -91,4 +93,23 @@ public class DoubleTapPowerPreferenceControllerTest { assertThat(mController.isSwitchPrefEnabled()).isFalse(); } + + @Test + public void testPreferenceController_ProperResultPayloadType() { + final Context context = ShadowApplication.getInstance().getApplicationContext(); + mController = new DoubleTapPowerPreferenceController(context, null); + ResultPayload payload = mController.getResultPayload(); + assertThat(payload).isInstanceOf(InlineSwitchPayload.class); + } + + @Test + public void testPreferenceController_CorrectPayload() { + final Context context = ShadowApplication.getInstance().getApplicationContext(); + mController = new DoubleTapPowerPreferenceController(context, null); + InlineSwitchPayload payload = (InlineSwitchPayload) mController.getResultPayload(); + assertThat(payload.settingsUri).isEqualTo("camera_double_tap_power_gesture_disabled"); + assertThat(payload.settingSource).isEqualTo(ResultPayload.SettingsSource.SECURE); + assertThat(payload.valueMap.get(0)).isEqualTo(true); + assertThat(payload.valueMap.get(1)).isEqualTo(false); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java index a25d34bd048..2f922d56d90 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapScreenPreferenceControllerTest.java @@ -22,6 +22,8 @@ import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -79,4 +81,19 @@ public class DoubleTapScreenPreferenceControllerTest { assertThat(mController.isSwitchPrefEnabled()).isFalse(); } + + @Test + public void testPreferenceController_ProperResultPayloadType() { + ResultPayload payload = mController.getResultPayload(); + assertThat(payload).isInstanceOf(InlineSwitchPayload.class); + } + + @Test + public void testPreferenceController_CorrectPayload() { + InlineSwitchPayload payload = (InlineSwitchPayload) mController.getResultPayload(); + assertThat(payload.settingsUri).isEqualTo("doze_pulse_on_double_tap"); + assertThat(payload.settingSource).isEqualTo(ResultPayload.SettingsSource.SECURE); + assertThat(payload.valueMap.get(1)).isEqualTo(true); + assertThat(payload.valueMap.get(0)).isEqualTo(false); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java index 5b021827487..ad682b2521b 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTwistPreferenceControllerTest.java @@ -24,6 +24,8 @@ import android.provider.Settings; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -111,4 +113,19 @@ public class DoubleTwistPreferenceControllerTest { assertThat(mController.isSwitchPrefEnabled()).isFalse(); } + + @Test + public void testPreferenceController_ProperResultPayloadType() { + ResultPayload payload = mController.getResultPayload(); + assertThat(payload).isInstanceOf(InlineSwitchPayload.class); + } + + @Test + public void testPreferenceController_CorrectPayload() { + InlineSwitchPayload payload = (InlineSwitchPayload) mController.getResultPayload(); + assertThat(payload.settingsUri).isEqualTo("camera_double_twist_to_flip_enabled"); + assertThat(payload.settingSource).isEqualTo(ResultPayload.SettingsSource.SECURE); + assertThat(payload.valueMap.get(1)).isEqualTo(true); + assertThat(payload.valueMap.get(0)).isEqualTo(false); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java index 66ae679147c..f112b9ef27a 100644 --- a/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/PIckupGesturePreferenceControllerTest.java @@ -22,6 +22,8 @@ import com.android.internal.hardware.AmbientDisplayConfiguration; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -82,4 +84,18 @@ public class PIckupGesturePreferenceControllerTest { assertThat(mController.isSwitchPrefEnabled()).isFalse(); } + @Test + public void testPreferenceController_ProperResultPayloadType() { + ResultPayload payload = mController.getResultPayload(); + assertThat(payload).isInstanceOf(InlineSwitchPayload.class); + } + + @Test + public void testPreferenceController_CorrectPayload() { + InlineSwitchPayload payload = (InlineSwitchPayload) mController.getResultPayload(); + assertThat(payload.settingsUri).isEqualTo("doze_pulse_on_pick_up"); + assertThat(payload.settingSource).isEqualTo(ResultPayload.SettingsSource.SECURE); + assertThat(payload.valueMap.get(1)).isEqualTo(true); + assertThat(payload.valueMap.get(0)).isEqualTo(false); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java index 7b34666c941..49d73ea8371 100644 --- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java @@ -22,6 +22,8 @@ import android.provider.Settings; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -87,4 +89,19 @@ public class SwipeToNotificationPreferenceControllerTest { assertThat(mController.isSwitchPrefEnabled()).isFalse(); } + + @Test + public void testPreferenceController_ProperResultPayloadType() { + ResultPayload payload = mController.getResultPayload(); + assertThat(payload).isInstanceOf(InlineSwitchPayload.class); + } + + @Test + public void testPreferenceController_CorrectPayload() { + InlineSwitchPayload payload = (InlineSwitchPayload) mController.getResultPayload(); + assertThat(payload.settingsUri).isEqualTo("system_navigation_keys_enabled"); + assertThat(payload.settingSource).isEqualTo(ResultPayload.SettingsSource.SECURE); + assertThat(payload.valueMap.get(1)).isEqualTo(true); + assertThat(payload.valueMap.get(0)).isEqualTo(false); + } } diff --git a/tests/robotests/src/com/android/settings/search/DatabaseIndexingUtilsTest.java b/tests/robotests/src/com/android/settings/search/DatabaseIndexingUtilsTest.java new file mode 100644 index 00000000000..5b6824d8565 --- /dev/null +++ b/tests/robotests/src/com/android/settings/search/DatabaseIndexingUtilsTest.java @@ -0,0 +1,130 @@ +/* + * 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.util.ArrayMap; +import com.android.internal.hardware.AmbientDisplayConfiguration; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.core.PreferenceController; +import com.android.settings.gestures.DoubleTapPowerPreferenceController; +import com.android.settings.gestures.DoubleTapScreenPreferenceController; +import com.android.settings.gestures.DoubleTwistPreferenceController; +import com.android.settings.gestures.PickupGesturePreferenceController; +import com.android.settings.gestures.SwipeToNotificationPreferenceController; +import com.android.settings.search2.DatabaseIndexingUtils; + +import com.android.settings.search2.IntentPayload; +import com.android.settings.search2.ResultPayload; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.Map; + +import static com.google.common.truth.Truth.assertThat; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class DatabaseIndexingUtilsTest { + + private Context mContext; + @Mock + private AmbientDisplayConfiguration mAmbientDisplayConfiguration; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + } + + @Test + public void testGetPreferenceControllerUriMap_BadClassName_ReturnsNull() { + Map map = DatabaseIndexingUtils.getPreferenceControllerUriMap("dummy", mContext); + assertThat(map).isNull(); + } + + @Test + public void testGetPreferenceControllerUriMap_NullContext_ReturnsNull() { + Map map = DatabaseIndexingUtils.getPreferenceControllerUriMap("dummy", null); + assertThat(map).isNull(); + } + + @Test + public void testGetPreferenceControllerUriMap_CompatibleClass_ReturnsNotNull() { + String className = "com.android.settings.gestures.GestureSettings"; + + Map map = DatabaseIndexingUtils.getPreferenceControllerUriMap(className, mContext); + assertThat(map).isNotNull(); + } + + @Test + public void testGetPreferenceControllerUriMap_CompatibleClass_ReturnsValidMap() { + String className = "com.android.settings.gestures.GestureSettings"; + + Map map = DatabaseIndexingUtils.getPreferenceControllerUriMap(className, mContext); + assertThat(map.get("gesture_double_twist")) + .isInstanceOf(DoubleTwistPreferenceController.class); + assertThat(map.get("gesture_swipe_down_fingerprint")) + .isInstanceOf(SwipeToNotificationPreferenceController.class); + assertThat(map.get("gesture_double_tap_screen")) + .isInstanceOf(DoubleTapScreenPreferenceController.class); + assertThat(map.get("gesture_pick_up")) + .isInstanceOf(PickupGesturePreferenceController.class); + assertThat(map.get("gesture_double_tap_power")) + .isInstanceOf(DoubleTapPowerPreferenceController.class); + } + + @Test + public void testGetPayloadFromMap_NullMap_ReturnsNull() { + ResultPayload payload = DatabaseIndexingUtils.getPayloadFromUriMap(null, ""); + assertThat(payload).isNull(); + } + + @Test + public void testGetPayloadFromMap_MatchingKey_ReturnsPayloa() { + final String key = "key"; + PreferenceController prefController = new PreferenceController(mContext) { + @Override + public boolean isAvailable() { + return false; + } + + @Override + public String getPreferenceKey() { + return key; + } + + @Override + public ResultPayload getResultPayload() { + return new IntentPayload(null); + } + }; + ArrayMap map = new ArrayMap<>(); + map.put(key, prefController); + + ResultPayload payload = DatabaseIndexingUtils.getPayloadFromUriMap(map, key); + assertThat(payload).isInstanceOf(IntentPayload.class); + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/search/InlineSliderPayloadTest.java b/tests/robotests/src/com/android/settings/search/InlineSliderPayloadTest.java deleted file mode 100644 index d52eb94653b..00000000000 --- a/tests/robotests/src/com/android/settings/search/InlineSliderPayloadTest.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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); - } -} diff --git a/tests/robotests/src/com/android/settings/search/InlineSwitchPayloadTest.java b/tests/robotests/src/com/android/settings/search/InlineSwitchPayloadTest.java new file mode 100644 index 00000000000..701679cca5c --- /dev/null +++ b/tests/robotests/src/com/android/settings/search/InlineSwitchPayloadTest.java @@ -0,0 +1,113 @@ +/* + * 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.os.Parcel; +import android.util.ArrayMap; +import android.content.Context; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; +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; +import static org.junit.Assert.fail; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class InlineSwitchPayloadTest { + + @Test + public void testGetSwitch_EmptyMap_ExceptionThrown() { + final String uri = "test.com"; + final int source = ResultPayload.SettingsSource.SECURE; + + final Context context = ShadowApplication.getInstance().getApplicationContext(); + InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, null); + try { + payload.getSwitchValue(context); + fail("Should have thrown exception for null map"); + } catch (IllegalStateException e) { + assertThat(e).isNotNull(); + } + } + + @Test + public void testGetSwitch_BadMap_ExceptionThrown() { + final String uri = "test.com"; + final int source = ResultPayload.SettingsSource.SECURE; + final ArrayMap map = new ArrayMap<>(); + + final Context context = ShadowApplication.getInstance().getApplicationContext(); + InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, map); + try { + payload.getSwitchValue(context); + fail("Should have thrown exception for bad map"); + } catch (IllegalStateException e) { + assertThat(e).isNotNull(); + } + } + + @Test + public void testConstructor_DataRetained() { + final String uri = "test.com"; + final int type = ResultPayload.PayloadType.INLINE_SWITCH; + final int source = ResultPayload.SettingsSource.SECURE; + final ArrayMap map = new ArrayMap<>(); + map.put(1, true); + map.put(0, false); + + InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, map); + assertThat(payload.settingsUri).isEqualTo(uri); + assertThat(payload.inlineType).isEqualTo(type); + assertThat(payload.settingSource).isEqualTo(source); + assertThat(payload.valueMap.get(1)).isTrue(); + assertThat(payload.valueMap.get(0)).isFalse(); + } + + @Test + public void testParcelConstructor_DataRetained() { + String uri = "test.com"; + int type = ResultPayload.PayloadType.INLINE_SWITCH; + int source = ResultPayload.SettingsSource.SECURE; + final ArrayMap map = new ArrayMap<>(); + map.put(1, true); + map.put(0, false); + + Parcel parcel = Parcel.obtain(); + parcel.writeString(uri); + parcel.writeInt(type); + parcel.writeInt(source); + parcel.writeMap(map); + parcel.setDataPosition(0); + + InlineSwitchPayload payload = InlineSwitchPayload.CREATOR.createFromParcel(parcel); + assertThat(payload.settingsUri).isEqualTo(uri); + assertThat(payload.inlineType).isEqualTo(type); + assertThat(payload.settingSource).isEqualTo(source); + assertThat(payload.valueMap.get(1)).isTrue(); + assertThat(payload.valueMap.get(0)).isFalse(); + } + + +} diff --git a/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java new file mode 100644 index 00000000000..efbad2fad6d --- /dev/null +++ b/tests/robotests/src/com/android/settings/search/InlineSwitchViewHolderTest.java @@ -0,0 +1,106 @@ +/* + * 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.Fragment; +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.InlineSwitchPayload; +import com.android.settings.search2.InlineSwitchViewHolder; +import com.android.settings.search2.IntentPayload; +import com.android.settings.search2.SearchResult; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.ArrayList; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class InlineSwitchViewHolderTest { + + private static final String TITLE = "title"; + private static final String SUMMARY = "summary"; + + @Mock + private Fragment mFragment; + + @Mock + private InlineSwitchPayload mPayload; + private InlineSwitchViewHolder mHolder; + private Drawable mIcon; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + final Context context = ShadowApplication.getInstance().getApplicationContext(); + View view = LayoutInflater.from(context).inflate(R.layout.search_inline_switch_item, null); + mHolder = new InlineSwitchViewHolder(view, context); + + 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(); + assertThat(mHolder.switchView).isNotNull(); + } + + @Test + public void testBindViewElements_AllUpdated() { + when(mPayload.getSwitchValue(any(Context.class))).thenReturn(true); + SearchResult result = getSearchResult(); + mHolder.onBind(mFragment, result); + mHolder.switchView.setChecked(true); + + assertThat(mHolder.titleView.getText()).isEqualTo(TITLE); + assertThat(mHolder.summaryView.getText()).isEqualTo(SUMMARY); + assertThat(mHolder.iconView.getDrawable()).isEqualTo(mIcon); + assertThat(mHolder.switchView.isChecked()).isTrue(); + } + + private SearchResult getSearchResult() { + SearchResult.Builder builder = new SearchResult.Builder(); + builder.addTitle(TITLE) + .addSummary(SUMMARY) + .addRank(1) + .addPayload(new InlineSwitchPayload("", 0, null)) + .addBreadcrumbs(new ArrayList()) + .addIcon(mIcon) + .addPayload(mPayload); + + return builder.build(); + } +} diff --git a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java index 805c7cb1c15..ed503d8f6ff 100644 --- a/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java +++ b/tests/robotests/src/com/android/settings/search/IntentSearchViewHolderTest.java @@ -93,7 +93,7 @@ public class IntentSearchViewHolderTest { .addSummary(SUMMARY) .addRank(1) .addPayload(new IntentPayload(null)) - .addBreadcrumbs(new ArrayList<>()) + .addBreadcrumbs(new ArrayList()) .addIcon(mIcon); return builder.build(); diff --git a/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java b/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java index 0756d3f218a..3627898bbeb 100644 --- a/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchAdapterTest.java @@ -21,17 +21,22 @@ import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; +import android.view.ViewGroup; +import android.widget.FrameLayout; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import com.android.settings.search2.DatabaseResultLoader; +import com.android.settings.search2.InlineSwitchViewHolder; import com.android.settings.search2.IntentPayload; +import com.android.settings.search2.IntentSearchViewHolder; import com.android.settings.search2.ResultPayload; import com.android.settings.search2.SearchFragment; import com.android.settings.search2.SearchResult; import com.android.settings.search2.SearchResult.Builder; import com.android.settings.search2.SearchResultsAdapter; +import com.android.settings.search2.SearchViewHolder; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -39,6 +44,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; +import org.robolectric.shadows.ShadowViewGroup; import java.util.ArrayList; import java.util.List; @@ -63,6 +70,47 @@ public class SearchAdapterTest { mLoaderClassName = DatabaseResultLoader.class.getName(); } + @Test + public void testNoResultsAdded_EmptyListReturned() { + List updatedResults = mAdapter.getSearchResults(); + assertThat(updatedResults).isEmpty(); + } + + @Test + public void testSingleSourceMerge_ExactCopyReturned() { + ArrayList intentResults = getIntentSampleResults(); + mAdapter.mergeResults(intentResults, mLoaderClassName); + + List updatedResults = mAdapter.getSearchResults(); + assertThat(updatedResults).containsAllIn(intentResults); + } + + @Test + public void testDuplicateSourceMerge_ExactCopyReturned() { + ArrayList intentResults = getIntentSampleResults(); + mAdapter.mergeResults(intentResults, mLoaderClassName); + mAdapter.mergeResults(intentResults, mLoaderClassName); + + List updatedResults = mAdapter.getSearchResults(); + assertThat(updatedResults).containsAllIn(intentResults); + } + + @Test + public void testCreatViewHolder_ReturnsIntentResult() { + ViewGroup group = new FrameLayout(mContext); + SearchViewHolder view = mAdapter.onCreateViewHolder(group, + ResultPayload.PayloadType.INTENT); + assertThat(view).isInstanceOf(IntentSearchViewHolder.class); + } + + @Test + public void testCreatViewHolder_ReturnsInlineSwitchResult() { + ViewGroup group = new FrameLayout(mContext); + SearchViewHolder view = mAdapter.onCreateViewHolder(group, + ResultPayload.PayloadType.INLINE_SWITCH); + assertThat(view).isInstanceOf(InlineSwitchViewHolder.class); + } + private ArrayList getIntentSampleResults() { ArrayList sampleResults = new ArrayList<>(); ArrayList breadcrumbs = new ArrayList<>(); @@ -84,31 +132,4 @@ public class SearchAdapterTest { sampleResults.add(builder.build()); return sampleResults; } - - - @Test - public void testNoResultsAdded_EmptyListReturned() { - List updatedResults = mAdapter.getSearchResults(); - assertThat(updatedResults).isEmpty(); - } - - - @Test - public void testSingleSourceMerge_ExactCopyReturned() { - ArrayList intentResults = getIntentSampleResults(); - mAdapter.mergeResults(intentResults, mLoaderClassName); - - List updatedResults = mAdapter.getSearchResults(); - assertThat(updatedResults).containsAllIn(intentResults); - } - - @Test - public void testDuplicateSourceMerge_ExactCopyReturned() { - ArrayList intentResults = getIntentSampleResults(); - mAdapter.mergeResults(intentResults, mLoaderClassName); - mAdapter.mergeResults(intentResults, mLoaderClassName); - - List updatedResults = mAdapter.getSearchResults(); - assertThat(updatedResults).containsAllIn(intentResults); - } } \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java b/tests/robotests/src/com/android/settings/search2/CursorToSearchResultConverterTest.java similarity index 66% rename from tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java rename to tests/robotests/src/com/android/settings/search2/CursorToSearchResultConverterTest.java index 1df7b1f09ef..98b250d192a 100644 --- a/tests/robotests/src/com/android/settings/search/DatabaseResultLoaderTest.java +++ b/tests/robotests/src/com/android/settings/search2/CursorToSearchResultConverterTest.java @@ -15,7 +15,7 @@ * */ -package com.android.settings.search; +package com.android.settings.search2; import android.app.Activity; import android.content.Context; @@ -23,16 +23,13 @@ import android.content.Intent; import android.database.MatrixCursor; import android.graphics.drawable.Drawable; +import android.util.ArrayMap; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SubSettings; import com.android.settings.TestConfig; import com.android.settings.gestures.GestureSettings; -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 org.junit.Before; import org.junit.Test; @@ -47,12 +44,14 @@ 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; +public class CursorToSearchResultConverterTest { + + private CursorToSearchResultConverter mConverter; private static final 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"}; + "intent action", "target package", "target class", "enabled", "key", + "payload_type", "payload"}; private static final String[] TITLES = new String[]{"title1", "title2", "title3"}; private static final String SUMMARY = "SUMMARY"; @@ -66,24 +65,24 @@ public class DatabaseResultLoaderTest { public void setUp() { Context context = Robolectric.buildActivity(Activity.class).get(); mDrawable = context.getDrawable(mIcon); - mLoader = new DatabaseResultLoader(context, ""); + mConverter = new CursorToSearchResultConverter(context); } @Test public void testParseNullResults_ReturnsNull() { - List results = mLoader.parseCursorForSearch(null); + List results = mConverter.convertCursor(null); assertThat(results).isNull(); } @Test public void testParseCursor_NotNull() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); assertThat(results).isNotNull(); } @Test public void testParseCursor_MatchesRank() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); for (int i = 0; i < EXAMPLES; i++) { assertThat(results.get(i).rank).isEqualTo(i); } @@ -91,7 +90,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_MatchesTitle() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); for (int i = 0; i < EXAMPLES; i++) { assertThat(results.get(i).title).isEqualTo(TITLES[i]); } @@ -99,7 +98,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_MatchesSummary() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); for (int i = 0; i < EXAMPLES; i++) { assertThat(results.get(i).summary).isEqualTo(SUMMARY); } @@ -107,7 +106,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_MatchesIcon() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); for (int i = 0; i < EXAMPLES; i++) { Drawable resultDrawable = results.get(i).icon; assertThat(resultDrawable.toString()).isEqualTo(mDrawable.toString()); @@ -116,7 +115,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_NoIcon() { - List results = mLoader.parseCursorForSearch( + List results = mConverter.convertCursor( getDummyCursor(false /* hasIcon */)); for (int i = 0; i < EXAMPLES; i++) { Drawable resultDrawable = results.get(i).icon; @@ -126,7 +125,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_MatchesPayloadType() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); ResultPayload payload; for (int i = 0; i < EXAMPLES; i++) { payload = results.get(i).payload; @@ -153,9 +152,10 @@ public class DatabaseResultLoaderTest { BLANK, // target class BLANK, // enabled BLANK, // key - BLANK // user id + 0, // Payload Type + null // Payload }); - List results = mLoader.parseCursorForSearch(cursor); + List results = mConverter.convertCursor(cursor); IntentPayload payload = (IntentPayload) results.get(0).payload; Intent intent = payload.intent; assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName()); @@ -163,7 +163,7 @@ public class DatabaseResultLoaderTest { @Test public void testParseCursor_MatchesIntentPayload() { - List results = mLoader.parseCursorForSearch(getDummyCursor()); + List results = mConverter.convertCursor(getDummyCursor()); IntentPayload payload; for (int i = 0; i < EXAMPLES; i++) { payload = (IntentPayload) results.get(i).payload; @@ -172,6 +172,46 @@ public class DatabaseResultLoaderTest { } } + @Test + public void testParseCursor_MatchesInlineSwitchPayload() { + MatrixCursor cursor = new MatrixCursor(COLUMNS); + final String BLANK = ""; + final String uri = "test.com"; + final int type = ResultPayload.PayloadType.INLINE_SWITCH; + final int source = ResultPayload.SettingsSource.SECURE; + final ArrayMap map = new ArrayMap<>(); + map.put(1, true); + map.put(0, false); + final InlineSwitchPayload payload = new InlineSwitchPayload(uri, source, map); + + cursor.addRow(new Object[]{ + 0, // rank + TITLES[0], + SUMMARY, + SUMMARY, // summary off + BLANK, // entries + BLANK, // Keywords + GestureSettings.class.getName(), + BLANK, // screen title + null, // icon + BLANK, // action + null, // target package + BLANK, // target class + BLANK, // enabled + BLANK, // key + type, // Payload Type + ResultPayloadUtils.marshall(payload) // Payload + }); + List results = mConverter.convertCursor(cursor); + InlineSwitchPayload newPayload = (InlineSwitchPayload) results.get(0).payload; + + assertThat(newPayload.settingsUri).isEqualTo(uri); + assertThat(newPayload.inlineType).isEqualTo(type); + assertThat(newPayload.settingSource).isEqualTo(source); + assertThat(newPayload.valueMap.get(1)).isTrue(); + assertThat(newPayload.valueMap.get(0)).isFalse(); + } + private MatrixCursor getDummyCursor() { return getDummyCursor(true /* hasIcon */); } @@ -196,7 +236,10 @@ public class DatabaseResultLoaderTest { item.add(BLANK); // target class item.add(BLANK); // enabled item.add(BLANK); // key - item.add(BLANK); // user id + // Note there is no user id. This is omitted because it is not being + // queried. Should the queries change, so should this method. + item.add(Integer.toString(0)); // Payload Type + item.add(null); // Payload cursor.addRow(item); }