Add first inline switch result.
Adds gestures as Inline switch results to Settings Search. Change-Id: Ie9b69ac2a54756d5b756401e348cae0a02c907c9 Fixes: 33669037 Test: make RunSettingsRoboTests
This commit is contained in:
81
res/layout/search_inline_switch_item.xml
Normal file
81
res/layout/search_inline_switch_item.xml
Normal file
@@ -0,0 +1,81 @@
|
||||
<?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:gravity="center_vertical"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/icon_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="60dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
<com.android.internal.widget.PreferenceImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:maxLength="60"
|
||||
android:maxLines="10"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<Switch
|
||||
android:id="@+id/switchView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="end|center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:orientation="vertical"/>
|
||||
</LinearLayout>
|
@@ -14,50 +14,59 @@
|
||||
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
|
||||
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:gravity="center_vertical"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/icon_container"
|
||||
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" />
|
||||
|
||||
android:minWidth="60dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
<com.android.internal.widget.PreferenceImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||
android:ellipsize="marquee"/>
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/summary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@android:id/title"
|
||||
android:layout_alignStart="@android:id/title"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:maxLines="10"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
@@ -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<Integer, Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<Integer, Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<Integer, Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -167,21 +167,32 @@ public class GestureSettings extends DashboardFragment {
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
ArrayList<String> result = new ArrayList<String>();
|
||||
|
||||
List<PreferenceController> preferenceControllers =
|
||||
getPreferenceControllers(context);
|
||||
for(PreferenceController controller : preferenceControllers) {
|
||||
controller.updateNonIndexableKeys(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
List<PreferenceController> 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -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<Integer, Boolean> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<Integer, Boolean> valueMap = new ArrayMap<>();
|
||||
valueMap.put(1, true);
|
||||
valueMap.put(0, false);
|
||||
|
||||
return new InlineSwitchPayload(Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
|
||||
ResultPayload.SettingsSource.SECURE, valueMap);
|
||||
}
|
||||
}
|
||||
|
@@ -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<SearchResult> convertCursor(Cursor cursorResults) {
|
||||
if (cursorResults == null) {
|
||||
return null;
|
||||
}
|
||||
final Map<String, Context> contextMap = new HashMap<>();
|
||||
final ArrayList<SearchResult> 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<String, Context> 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<String, Context> 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;
|
||||
}
|
||||
}
|
@@ -66,6 +66,10 @@ public class DatabaseIndexingUtils {
|
||||
*/
|
||||
public static Map<String, PreferenceController> 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<PreferenceController> 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;
|
||||
}
|
||||
|
@@ -48,14 +48,36 @@ import java.util.Map;
|
||||
public class DatabaseResultLoader extends AsyncLoader<List<SearchResult>> {
|
||||
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<List<SearchResult>> {
|
||||
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<List<SearchResult>> {
|
||||
"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<SearchResult> parseCursorForSearch(Cursor cursorResults) {
|
||||
if (cursorResults == null) {
|
||||
return null;
|
||||
}
|
||||
final Map<String, Context> contextMap = new HashMap<>();
|
||||
final ArrayList<SearchResult> 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<String, Context> 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<String, Context> 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
43
src/com/android/settings/search2/InlinePayload.java
Normal file
43
src/com/android/settings/search2/InlinePayload.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
@@ -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<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];
|
||||
}
|
||||
};
|
||||
}
|
138
src/com/android/settings/search2/InlineSwitchPayload.java
Normal file
138
src/com/android/settings/search2/InlineSwitchPayload.java
Normal file
@@ -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<Integer, Boolean> valueMap;
|
||||
|
||||
public InlineSwitchPayload(String newUri, @SettingsSource int settingsSource,
|
||||
ArrayMap<Integer, Boolean> 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<InlineSwitchPayload> CREATOR =
|
||||
new Parcelable.Creator<InlineSwitchPayload>() {
|
||||
@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<Integer, Boolean> 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;
|
||||
}
|
||||
}
|
||||
}
|
73
src/com/android/settings/search2/InlineSwitchViewHolder.java
Normal file
73
src/com/android/settings/search2/InlineSwitchViewHolder.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
@@ -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();
|
||||
}
|
||||
|
@@ -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<SearchViewHolder> {
|
||||
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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<String,PreferenceController> map = new ArrayMap<>();
|
||||
map.put(key, prefController);
|
||||
|
||||
ResultPayload payload = DatabaseIndexingUtils.getPayloadFromUriMap(map, key);
|
||||
assertThat(payload).isInstanceOf(IntentPayload.class);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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<Integer, Boolean> 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<Integer, Boolean> 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<Integer, Boolean> 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -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<String>())
|
||||
.addIcon(mIcon)
|
||||
.addPayload(mPayload);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
@@ -93,7 +93,7 @@ public class IntentSearchViewHolderTest {
|
||||
.addSummary(SUMMARY)
|
||||
.addRank(1)
|
||||
.addPayload(new IntentPayload(null))
|
||||
.addBreadcrumbs(new ArrayList<>())
|
||||
.addBreadcrumbs(new ArrayList<String>())
|
||||
.addIcon(mIcon);
|
||||
|
||||
return builder.build();
|
||||
|
@@ -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<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||
assertThat(updatedResults).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleSourceMerge_ExactCopyReturned() {
|
||||
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
||||
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||
|
||||
List<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);
|
||||
|
||||
List<SearchResult> 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<SearchResult> getIntentSampleResults() {
|
||||
ArrayList<SearchResult> sampleResults = new ArrayList<>();
|
||||
ArrayList<String> breadcrumbs = new ArrayList<>();
|
||||
@@ -84,31 +132,4 @@ public class SearchAdapterTest {
|
||||
sampleResults.add(builder.build());
|
||||
return sampleResults;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoResultsAdded_EmptyListReturned() {
|
||||
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||
assertThat(updatedResults).isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSingleSourceMerge_ExactCopyReturned() {
|
||||
ArrayList<SearchResult> intentResults = getIntentSampleResults();
|
||||
mAdapter.mergeResults(intentResults, mLoaderClassName);
|
||||
|
||||
List<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);
|
||||
|
||||
List<SearchResult> updatedResults = mAdapter.getSearchResults();
|
||||
assertThat(updatedResults).containsAllIn(intentResults);
|
||||
}
|
||||
}
|
@@ -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<SearchResult> results = mLoader.parseCursorForSearch(null);
|
||||
List<SearchResult> results = mConverter.convertCursor(null);
|
||||
assertThat(results).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCursor_NotNull() {
|
||||
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> results = mConverter.convertCursor(getDummyCursor());
|
||||
assertThat(results).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseCursor_MatchesRank() {
|
||||
List<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(cursor);
|
||||
List<SearchResult> 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<SearchResult> results = mLoader.parseCursorForSearch(getDummyCursor());
|
||||
List<SearchResult> 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<Integer, Boolean> 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<SearchResult> 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);
|
||||
}
|
Reference in New Issue
Block a user