Merge "Don't persist device index job across reboot"
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
new file mode 100644
index 0000000..b947d65
--- /dev/null
+++ b/res/layout/homepage_slice_tile.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+
+<androidx.cardview.widget.CardView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/homepage_card_top_margin"
+ android:layout_marginBottom="@dimen/homepage_card_bottom_margin"
+ android:layout_marginStart="@dimen/homepage_card_side_margin"
+ android:layout_marginEnd="@dimen/homepage_card_side_margin"
+ app:cardCornerRadius="@dimen/homepage_card_corner_radius"
+ app:cardElevation="@dimen/homepage_card_elevation">
+
+ <androidx.slice.widget.SliceView
+ android:id="@+id/slice_view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="@dimen/homepage_card_padding_start"
+ android:paddingEnd="@dimen/homepage_card_padding_end"
+ android:paddingTop="@dimen/homepage_card_padding_top"
+ android:paddingBottom="@dimen/homepage_card_padding_bottom"/>
+
+</androidx.cardview.widget.CardView>
diff --git a/res/layout/switch_bar.xml b/res/layout/switch_bar.xml
index e305f9d..8cb6f51 100644
--- a/res/layout/switch_bar.xml
+++ b/res/layout/switch_bar.xml
@@ -38,7 +38,8 @@
android:tint="?android:attr/colorAccent"
android:theme="@android:style/Theme.Material"
android:layout_gravity="center_vertical"
- android:layout_marginEnd="@dimen/restricted_icon_margin_end"/>
+ android:layout_marginEnd="@dimen/restricted_icon_margin_end"
+ android:visibility="gone" />
<com.android.settings.widget.ToggleSwitch
android:id="@+id/switch_widget"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 70672ca..37b3c4b 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -340,4 +340,15 @@
<dimen name="homepage_bottombar_top_margin">34dp</dimen>
<dimen name="homepage_bottombar_fab_cradle">68dp</dimen>
+ <!-- Homepage cards size and padding -->
+ <dimen name="homepage_card_corner_radius">8dp</dimen>
+ <dimen name="homepage_card_elevation">2dp</dimen>
+ <dimen name="homepage_card_top_margin">6dp</dimen>
+ <dimen name="homepage_card_bottom_margin">6dp</dimen>
+ <dimen name="homepage_card_side_margin">16dp</dimen>
+ <dimen name="homepage_card_padding_start">16dp</dimen>
+ <dimen name="homepage_card_padding_end">16dp</dimen>
+ <dimen name="homepage_card_padding_top">6dp</dimen>
+ <dimen name="homepage_card_padding_bottom">6dp</dimen>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c99d7ad..0c3caf6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -10068,4 +10068,10 @@
<!-- Homepage bottom menu. Title for display personalized Settings [CHAR LIMIT=30] -->
<string name="homepage_personal_settings">Your Settings</string>
+ <!-- Setting Checkbox title whether to enable CBRS data. [CHAR LIMIT=40] -->
+ <string name="cbrs_data_switch">CBRS Data</string>
+
+ <!-- Title of implications of enabling CBRS Data -->
+ <string name="cbrs_data_switch_summary">CBRS Data</string>
+
</resources>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 8cc8001..5b6d215 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -234,6 +234,11 @@
android:title="@string/usb_default_label"/>
<SwitchPreference
+ android:key="cbrs_data_switch"
+ android:title="@string/cbrs_data_switch"
+ android:summary="@string/cbrs_data_switch" />
+
+ <SwitchPreference
android:key="bluetooth_show_devices_without_names"
android:title="@string/bluetooth_show_devices_without_names"
android:summary="@string/bluetooth_show_devices_without_names_summary" />
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index eb258ac..35c6d1c 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -1335,7 +1335,8 @@
private void updateSummary(ApplicationViewHolder holder, AppEntry entry) {
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
- if (entry.extraInfo != null) {
+ if (entry.extraInfo != null
+ && entry.extraInfo instanceof NotificationsSentState) {
holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
(NotificationsSentState) entry.extraInfo,
(mLastSortMode == R.id.sort_order_recent_notification)));
@@ -1384,7 +1385,8 @@
.getSwitchOnClickListener(entry),
AppStateNotificationBridge.enableSwitch(entry),
AppStateNotificationBridge.checkSwitch(entry));
- if (entry.extraInfo != null) {
+ if (entry.extraInfo != null
+ && entry.extraInfo instanceof NotificationsSentState) {
holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
(NotificationsSentState) entry.extraInfo,
(mLastSortMode == R.id.sort_order_recent_notification)));
diff --git a/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java b/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java
new file mode 100644
index 0000000..ec1f8e0
--- /dev/null
+++ b/src/com/android/settings/development/CbrsDataSwitchPreferenceController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 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.development;
+
+import android.content.Context;
+import android.util.Log;
+import android.telephony.TelephonyManager;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.SwitchPreference;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class CbrsDataSwitchPreferenceController extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+ private static final String CBRS_DATA_SWITCH_KEY = "cbrs_data_switch";
+ private static final String TAG = "CbrsDataSwitchPreferenceController";
+ private Context mContext;
+
+ private TelephonyManager mTelephonyManager;
+
+ public CbrsDataSwitchPreferenceController(Context context) {
+ super(context);
+ mContext = context;
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return CBRS_DATA_SWITCH_KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mTelephonyManager != null;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean state = (Boolean)newValue;
+ return mTelephonyManager.setAlternativeNetworkAccessState(state);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ boolean state = mTelephonyManager.isAlternativeNetworkAccessEnabled();
+ ((SwitchPreference) mPreference).setChecked(state);
+ }
+
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 937de20..873cec4 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -460,6 +460,7 @@
controllers.add(new FreeformWindowsPreferenceController(context));
controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context));
+ controllers.add(new CbrsDataSwitchPreferenceController(context));
controllers.add(new DefaultLaunchPreferenceController(context, "running_apps"));
controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode"));
controllers.add(new DefaultLaunchPreferenceController(context, "quick_settings_tiles"));
diff --git a/src/com/android/settings/homepage/ContextualCardLookupTable.java b/src/com/android/settings/homepage/ContextualCardLookupTable.java
index e70b700..1acd812 100644
--- a/src/com/android/settings/homepage/ContextualCardLookupTable.java
+++ b/src/com/android/settings/homepage/ContextualCardLookupTable.java
@@ -19,6 +19,8 @@
import com.android.settings.homepage.ContextualCard.CardType;
import com.android.settings.homepage.conditional.ConditionContextualCardController;
import com.android.settings.homepage.conditional.ConditionContextualCardRenderer;
+import com.android.settings.homepage.slices.SliceContextualCardController;
+import com.android.settings.homepage.slices.SliceContextualCardRenderer;
import java.util.Set;
import java.util.TreeSet;
@@ -50,6 +52,9 @@
add(new ControllerRendererMapping(CardType.CONDITIONAL,
ConditionContextualCardController.class,
ConditionContextualCardRenderer.class));
+ add(new ControllerRendererMapping(CardType.SLICE,
+ SliceContextualCardController.class,
+ SliceContextualCardRenderer.class));
}};
public static Class<? extends ContextualCardController> getCardControllerClass(
diff --git a/src/com/android/settings/homepage/ContextualCardsAdapter.java b/src/com/android/settings/homepage/ContextualCardsAdapter.java
index 9ab8893..81cae39 100644
--- a/src/com/android/settings/homepage/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/ContextualCardsAdapter.java
@@ -21,6 +21,7 @@
import android.view.View;
import android.view.ViewGroup;
+import androidx.lifecycle.LifecycleOwner;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -39,11 +40,14 @@
private final Context mContext;
private final ControllerRendererPool mControllerRendererPool;
private final List<ContextualCard> mContextualCards;
+ private final LifecycleOwner mLifecycleOwner;
- public ContextualCardsAdapter(Context context, ContextualCardManager manager) {
+ public ContextualCardsAdapter(Context context, LifecycleOwner lifecycleOwner,
+ ContextualCardManager manager) {
mContext = context;
mContextualCards = new ArrayList<>();
mControllerRendererPool = manager.getControllerRendererPool();
+ mLifecycleOwner = lifecycleOwner;
setHasStableIds(true);
}
@@ -60,7 +64,7 @@
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int cardType) {
final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
- cardType);
+ mLifecycleOwner, cardType);
final int viewType = renderer.getViewType();
final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
@@ -71,7 +75,7 @@
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final int cardType = mContextualCards.get(position).getCardType();
final ContextualCardRenderer renderer = mControllerRendererPool.getRenderer(mContext,
- cardType);
+ mLifecycleOwner, cardType);
renderer.bindView(holder, mContextualCards.get(position));
}
diff --git a/src/com/android/settings/homepage/ControllerRendererPool.java b/src/com/android/settings/homepage/ControllerRendererPool.java
index 1e4b37c..73f73a5 100644
--- a/src/com/android/settings/homepage/ControllerRendererPool.java
+++ b/src/com/android/settings/homepage/ControllerRendererPool.java
@@ -20,9 +20,12 @@
import android.util.Log;
import androidx.collection.ArraySet;
+import androidx.lifecycle.LifecycleOwner;
import com.android.settings.homepage.conditional.ConditionContextualCardController;
import com.android.settings.homepage.conditional.ConditionContextualCardRenderer;
+import com.android.settings.homepage.slices.SliceContextualCardController;
+import com.android.settings.homepage.slices.SliceContextualCardRenderer;
import java.util.Set;
@@ -64,7 +67,8 @@
return mControllers;
}
- public ContextualCardRenderer getRenderer(Context context, @ContextualCard.CardType int cardType) {
+ public ContextualCardRenderer getRenderer(Context context, LifecycleOwner lifecycleOwner,
+ @ContextualCard.CardType int cardType) {
final Class<? extends ContextualCardRenderer> clz =
ContextualCardLookupTable.getCardRendererClasses(cardType);
for (ContextualCardRenderer renderer : mRenderers) {
@@ -74,7 +78,7 @@
}
}
- final ContextualCardRenderer renderer = createCardRenderer(context, clz);
+ final ContextualCardRenderer renderer = createCardRenderer(context, lifecycleOwner, clz);
if (renderer != null) {
mRenderers.add(renderer);
}
@@ -85,15 +89,19 @@
Class<? extends ContextualCardController> clz) {
if (ConditionContextualCardController.class == clz) {
return new ConditionContextualCardController(context);
+ } else if (SliceContextualCardController.class == clz) {
+ return new SliceContextualCardController();
}
return null;
}
- private ContextualCardRenderer createCardRenderer(Context context, Class<?> clz) {
+ private ContextualCardRenderer createCardRenderer(Context context,
+ LifecycleOwner lifecycleOwner, Class<?> clz) {
if (ConditionContextualCardRenderer.class == clz) {
return new ConditionContextualCardRenderer(context, this /*controllerRendererPool*/);
+ } else if (SliceContextualCardRenderer.class == clz) {
+ return new SliceContextualCardRenderer(context, lifecycleOwner);
}
return null;
}
-
}
diff --git a/src/com/android/settings/homepage/PersonalSettingsFragment.java b/src/com/android/settings/homepage/PersonalSettingsFragment.java
index 4a0041e..93c723b 100644
--- a/src/com/android/settings/homepage/PersonalSettingsFragment.java
+++ b/src/com/android/settings/homepage/PersonalSettingsFragment.java
@@ -54,7 +54,8 @@
mLayoutManager = new GridLayoutManager(getActivity(), SPAN_COUNT,
GridLayoutManager.VERTICAL, false /* reverseLayout */);
mCardsContainer.setLayoutManager(mLayoutManager);
- mContextualCardsAdapter = new ContextualCardsAdapter(getContext(), mContextualCardManager);
+ mContextualCardsAdapter = new ContextualCardsAdapter(getContext(),
+ this /* lifecycleOwner */, mContextualCardManager);
mCardsContainer.setAdapter(mContextualCardsAdapter);
mContextualCardManager.setListener(mContextualCardsAdapter);
diff --git a/src/com/android/settings/homepage/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/slices/SliceContextualCardController.java
new file mode 100644
index 0000000..e6fc283
--- /dev/null
+++ b/src/com/android/settings/homepage/slices/SliceContextualCardController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 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.homepage.slices;
+
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.ContextualCardController;
+import com.android.settings.homepage.ContextualCardUpdateListener;
+
+import java.util.List;
+
+/**
+ * Card controller for {@link ContextualCard} built as slices.
+ */
+public class SliceContextualCardController implements ContextualCardController {
+
+ @Override
+ public int getCardType() {
+ return ContextualCard.CardType.SLICE;
+ }
+
+ @Override
+ public void onPrimaryClick(ContextualCard card) {
+
+ }
+
+ @Override
+ public void onActionClick(ContextualCard card) {
+
+ }
+
+ @Override
+ public void setCardUpdateListener(ContextualCardUpdateListener listener) {
+
+ }
+}
diff --git a/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java
new file mode 100644
index 0000000..983b4aa
--- /dev/null
+++ b/src/com/android/settings/homepage/slices/SliceContextualCardRenderer.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 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.homepage.slices;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.widget.EventInfo;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
+
+import com.android.settings.R;
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.ContextualCardRenderer;
+
+import java.util.Map;
+
+/**
+ * Card renderer for {@link ContextualCard} built as slices.
+ */
+public class SliceContextualCardRenderer implements ContextualCardRenderer,
+ SliceView.OnSliceActionListener {
+
+ private static final String TAG = "SliceCardRenderer";
+
+ @VisibleForTesting
+ final Map<String, LiveData<Slice>> mSliceLiveDataMap;
+
+ private final Context mContext;
+ private final LifecycleOwner mLifecycleOwner;
+
+ public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner) {
+ mContext = context;
+ mLifecycleOwner = lifecycleOwner;
+ mSliceLiveDataMap = new ArrayMap<>();
+ }
+
+ @Override
+ public int getViewType() {
+ return R.layout.homepage_slice_tile;
+ }
+
+ @Override
+ public RecyclerView.ViewHolder createViewHolder(View view) {
+ return new SliceViewHolder(view);
+ }
+
+ @Override
+ public void bindView(RecyclerView.ViewHolder holder, ContextualCard card) {
+ final SliceViewHolder cardHolder = (SliceViewHolder) holder;
+ final Uri uri = card.getSliceUri();
+
+ //TODO(b/116063073): The URI check should be done earlier when we are performing final
+ // filtering after having the full list.
+ if (!ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ Log.w(TAG, "Invalid uri, skipping slice: " + uri);
+ return;
+ }
+
+ cardHolder.sliceView.setTag(uri);
+ //TODO(b/114009676): We will soon have a field to decide what slice mode we should set.
+ cardHolder.sliceView.setMode(SliceView.MODE_SHORTCUT);
+ LiveData<Slice> sliceLiveData = mSliceLiveDataMap.get(uri.toString());
+
+ if (sliceLiveData == null) {
+ sliceLiveData = SliceLiveData.fromUri(mContext, uri);
+ mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
+ sliceLiveData.observe(mLifecycleOwner, slice -> {
+ if (slice == null) {
+ Log.w(TAG, "Slice is null");
+ }
+ cardHolder.sliceView.setSlice(slice);
+ });
+ }
+
+ // Set this listener so we can log the interaction users make on the slice
+ cardHolder.sliceView.setOnSliceActionListener(this);
+ }
+
+ @Override
+ public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
+ //TODO(b/79698338): Log user interaction
+ }
+
+ public static class SliceViewHolder extends RecyclerView.ViewHolder {
+ public final SliceView sliceView;
+
+ public SliceViewHolder(View view) {
+ super(view);
+ sliceView = view.findViewById(R.id.slice_view);
+ }
+ }
+}
diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
index 0b50f5f..a02c0b2 100644
--- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
+++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
@@ -93,12 +93,9 @@
if (hapProfile != null && hfpProfile != null && device == null) {
hfpProfile.setActiveDevice(null);
hapProfile.setActiveDevice(null);
- return;
- }
- if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
+ } else if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
hapProfile.setActiveDevice(device);
- }
- if (hfpProfile != null) {
+ } else if (hfpProfile != null) {
hfpProfile.setActiveDevice(device);
}
}
diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java
index 8704243..2ac460c 100644
--- a/src/com/android/settings/sound/MediaOutputPreferenceController.java
+++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java
@@ -106,12 +106,9 @@
if (hapProfile != null && a2dpProfile != null && device == null) {
hapProfile.setActiveDevice(null);
a2dpProfile.setActiveDevice(null);
- return;
- }
- if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
+ } else if (hapProfile != null && hapProfile.getHiSyncId(device) != HI_SYNC_ID_INVALID) {
hapProfile.setActiveDevice(device);
- }
- if (a2dpProfile != null) {
+ } else if (a2dpProfile != null) {
a2dpProfile.setActiveDevice(device);
}
}
diff --git a/src/com/android/settings/support/SupportDashboardActivity.java b/src/com/android/settings/support/SupportDashboardActivity.java
index 245810a..8703ec7 100644
--- a/src/com/android/settings/support/SupportDashboardActivity.java
+++ b/src/com/android/settings/support/SupportDashboardActivity.java
@@ -68,7 +68,6 @@
data.title = context.getString(R.string.page_tab_title_support);
data.screenTitle = context.getString(R.string.settings_label);
data.summaryOn = context.getString(R.string.support_summary);
- data.iconResId = R.drawable.ic_homepage_support;
data.intentTargetPackage = context.getPackageName();
data.intentTargetClass = SupportDashboardActivity.class.getName();
data.intentAction = Intent.ACTION_MAIN;
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index da88e54..c9ab7c0 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -282,6 +282,28 @@
}
@Test
+ public void applicationsAdapter_onBindViewHolder_notifications_wrongExtraInfo() {
+ when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
+ ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
+ mFragment.mListType = LIST_TYPE_NOTIFICATION;
+ ApplicationViewHolder holder = mock(ApplicationViewHolder.class);
+ ReflectionHelpers.setField(holder, "itemView", mock(View.class));
+ ManageApplications.ApplicationsAdapter adapter =
+ new ManageApplications.ApplicationsAdapter(mState,
+ mFragment, mock(AppFilterItem.class),
+ mock(Bundle.class));
+ final ArrayList<ApplicationsState.AppEntry> appList = new ArrayList<>();
+ final ApplicationsState.AppEntry appEntry = mock(ApplicationsState.AppEntry.class);
+ appEntry.info = mock(ApplicationInfo.class);
+ appEntry.extraInfo = mock(AppFilterItem.class);
+ appList.add(appEntry);
+ ReflectionHelpers.setField(adapter, "mEntries", appList);
+
+ adapter.onBindViewHolder(holder, 0);
+ // no crash? yay!
+ }
+
+ @Test
public void applicationsAdapter_onBindViewHolder_updateSwitch_notifications() {
when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
ReflectionHelpers.setField(mFragment, "mUserManager", mUserManager);
diff --git a/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java
new file mode 100644
index 0000000..be9b123
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/CbrsDataSwitchPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 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.development;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public final class CbrsDataSwitchPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private Context mContext;
+ private TelephonyManager mTelephonyManager;
+ private SwitchPreference mPreference;
+ private CbrsDataSwitchPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new CbrsDataSwitchPreferenceController(mContext);
+ mPreference = new SwitchPreference(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChanged_settingEnabled_shouldEnableANAS() {
+ mController.onPreferenceChange(mPreference, true);
+
+ assertThat(mTelephonyManager.isAlternativeNetworkAccessEnabled()).isTrue();
+ }
+
+ @Test
+ public void onPreferenceChanged_settingDisabled_shouldDisableANAS() {
+ mController.onPreferenceChange(mPreference, false);
+
+ assertThat(mTelephonyManager.isAlternativeNetworkAccessEnabled()).isFalse();
+ }
+
+ @Test
+ public void updateState_settingEnabled_shouldEnablePreference() {
+ mTelephonyManager.setAlternativeNetworkAccessState(true);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void updateState_settingDisabled_shouldDisablePreference() {
+ mTelephonyManager.setAlternativeNetworkAccessState(false);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java
new file mode 100644
index 0000000..3239971
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/slices/SliceContextualCardRendererTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2018 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.homepage.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import androidx.lifecycle.LifecycleOwner;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.homepage.ContextualCard;
+import com.android.settings.homepage.PersonalSettingsFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SliceContextualCardRendererTest {
+
+ private Context mContext;
+ private SliceContextualCardRenderer mRenderer;
+ private LifecycleOwner mLifecycleOwner;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mLifecycleOwner = new PersonalSettingsFragment();
+ mRenderer = new SliceContextualCardRenderer(mContext, mLifecycleOwner);
+ }
+
+ @Test
+ public void bindView_invalidScheme_sliceShouldBeNull() {
+ final String sliceUri = "contet://com.android.settings.slices/action/flashlight";
+ RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
+
+ mRenderer.bindView(viewHolder, buildContextualCard(sliceUri));
+
+ assertThat(
+ ((SliceContextualCardRenderer.SliceViewHolder) viewHolder).sliceView.getSlice())
+ .isNull();
+ }
+
+ @Test
+ public void bindView_newSliceLiveData_shouldAddDataToMap() {
+ final String sliceUri = "content://com.android.settings.slices/action/flashlight";
+
+ mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
+
+ assertThat(mRenderer.mSliceLiveDataMap.size()).isEqualTo(1);
+ }
+
+ @Test
+ public void bindView_sliceLiveDataShouldObserveSliceView() {
+ final String sliceUri = "content://com.android.settings.slices/action/flashlight";
+
+ mRenderer.bindView(getSliceViewHolder(), buildContextualCard(sliceUri));
+
+ assertThat(mRenderer.mSliceLiveDataMap.get(sliceUri).hasObservers()).isTrue();
+ }
+
+ private RecyclerView.ViewHolder getSliceViewHolder() {
+ final int viewType = mRenderer.getViewType();
+ final RecyclerView recyclerView = new RecyclerView(mContext);
+ recyclerView.setLayoutManager(new LinearLayoutManager(mContext));
+ final View view = LayoutInflater.from(mContext).inflate(viewType, recyclerView, false);
+ final RecyclerView.ViewHolder viewHolder = mRenderer.createViewHolder(view);
+
+ return viewHolder;
+ }
+
+ private ContextualCard buildContextualCard(String sliceUri) {
+ return new ContextualCard.Builder()
+ .setName("test_name")
+ .setSliceUri(sliceUri)
+ .build();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
index e2fc779..58df2d2 100644
--- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -179,6 +180,7 @@
mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice);
verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice);
+ verify(mHeadsetProfile, never()).setActiveDevice(mLeftBluetoothHapDevice);
}
/**
@@ -192,6 +194,7 @@
mController.setActiveBluetoothDevice(mBluetoothDevice);
verify(mHeadsetProfile).setActiveDevice(mBluetoothDevice);
+ verify(mHearingAidProfile, never()).setActiveDevice(mBluetoothDevice);
}
/**
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index d2f5f1a..9e1ac3d 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -180,6 +181,7 @@
mController.setActiveBluetoothDevice(mLeftBluetoothHapDevice);
verify(mHearingAidProfile).setActiveDevice(mLeftBluetoothHapDevice);
+ verify(mA2dpProfile, never()).setActiveDevice(mLeftBluetoothHapDevice);
}
/**
@@ -193,6 +195,7 @@
mController.setActiveBluetoothDevice(mBluetoothDevice);
verify(mA2dpProfile).setActiveDevice(mBluetoothDevice);
+ verify(mHearingAidProfile, never()).setActiveDevice(mBluetoothDevice);
}
/**
diff --git a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
index 14d5c75..2e3a140 100644
--- a/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
+++ b/tests/robotests/src/com/android/settings/testutils/SettingsRobolectricTestRunner.java
@@ -93,6 +93,8 @@
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/extras/material-design-x/com.google.android.material_material-nodeps/android_common/aar/res/")), null));
paths.add(new ResourcePath(null,
Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.cardview_cardview-nodeps/android_common/aar/res")), null));
+ paths.add(new ResourcePath(null,
+ Fs.fromURL(new URL("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.slice_slice-view-nodeps/android_common/aar/res")), null));
} catch (MalformedURLException e) {
throw new RuntimeException("SettingsRobolectricTestRunner failure", e);
}
diff --git a/tests/uitests/AndroidManifest.xml b/tests/uitests/AndroidManifest.xml
index 91e15b8..49a2fd1 100644
--- a/tests/uitests/AndroidManifest.xml
+++ b/tests/uitests/AndroidManifest.xml
@@ -28,6 +28,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
+ <uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES"/>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/uitests/assets/search_results_list b/tests/uitests/assets/search_results_list
new file mode 100644
index 0000000..a0cc894
--- /dev/null
+++ b/tests/uitests/assets/search_results_list
@@ -0,0 +1,623 @@
+AP Band;wifi_tether_network_ap_band
+About phone;my_device_info_pref_screen
+Accessibility;accessibility_settings_screen
+Accessibility;top_level_accessibility
+Accounts;top_level_accounts
+Accounts;user_and_account_settings_screen
+Active Edge;gesture_assist_application
+Active Edge;gesture_assist_input_summary
+Active Edge;gesture_assist_settings_page
+Adaptive Battery;smart_battery_detail
+Adaptive Battery;smart_battery_manager
+Adaptive brightness;auto_brightness
+Adaptive brightness;auto_brightness_entry
+Add an account;add_account_screen
+Add rule;zen_mode_add_automatic_rule
+Add user or profile;user_add
+Add users from lock screen;security_lockscreen_add_users_when_locked
+Add users from lock screen;user_settings_add_users_when_locked
+Additional system updates;additional_system_update_settings
+Admin can delete all device data;enterprise_privacy_wipe_device
+Admin can lock the device and reset password;enterprise_privacy_lock_device
+Airplane mode;toggle_airplane
+Alarm volume;alarm_volume
+Alarms;zen_mode_alarms
+Allow calls;zen_mode_calls
+Allow events;zen_mode_events
+Allow messages;zen_mode_messages
+Allow notification dots;notification_badging
+Allow reminders;zen_mode_reminders
+Allow repeat callers;zen_mode_repeat_callers
+Allow when screen is off;gesture_assist_wake
+Also vibrate for calls;vibrate_when_ringing
+Always on;ambient_display_always_on
+Always show crash dialog;show_first_crash_dialog
+Always-on VPN turned on in your work profile;always_on_vpn_managed_profile
+Amount of time and data spent in each app;enterprise_privacy_usage_stats
+Android Beam;android_beam_settings
+Android version;my_device_firmware_version
+Animator duration scale;animator_duration_scale
+App data usage cycle;billing_cycle
+App info;all_app_info
+App permissions;manage_perms
+App-level permissions;app_level_permissions
+Apps;debug_applications_category
+Apps & app data;storage_settings_apps_space
+Apps & notifications;apps_and_notification_screen
+Apps & notifications;top_level_apps_and_notifs
+Apps installed;number_enterprise_installed_packages
+Assist & voice input;assist_and_voice_input
+Assist & voice input;manage_assist_screen
+Assist app;default_assist
+Audio & on-screen text;audio_and_captions_category
+Audio (music, ringtones, podcasts, etc.);storage_settings_music_space
+Auto-rotate screen;auto_rotate
+Auto-rotate screen;toggle_lock_screen_rotation_preference
+Auto-sync personal data;auto_sync_personal_account_data
+Auto-sync work data;auto_sync_work_account_data
+Autofill;debug_autofill_category
+Autofill service;default_autofill
+Autofill service;default_autofill_main
+Autofill service;default_autofill_work
+Automatic 24-hour format;auto_24hour
+Automatic date & time;auto_time
+Automatic restore;auto_restore
+Automatic rules;zen_mode_automation_settings_page
+Automatic system updates;ota_disable_automatic_update
+Automatic time zone;auto_zone
+Automatically lock;lock_after_timeout
+Automatically sync data;auto_sync_account_data
+Available;storage_settings_memory_available
+Available media devices;available_device_list
+Back up my data;backup_data
+Background check;background_check
+Background process limit;app_process_limit
+Backup;backup
+Backup;backup_settings
+Backup;privacy_settings_screen
+Backup account;configure_account
+Backup service isn't active;backup_inactive
+Battery;power_usage_summary_screen
+Battery;top_level_battery
+Battery Saver;battery_saver
+Battery Saver;battery_saver_summary
+Battery optimization;high_power_apps
+Battery percentage;battery_percentage
+Battery usage;power_usage_advanced_screen
+Battery usage since full charge;app_list
+Behavior;zen_mode_settings_category_behavior
+Blink light;notification_pulse
+Bluetooth;bluetooth_settings
+Bluetooth;bluetooth_switchbar_screen
+Bluetooth AVRCP Version;bluetooth_select_avrcp_version
+Bluetooth Audio Bits Per Sample;bluetooth_select_a2dp_bits_per_sample
+Bluetooth Audio Channel Mode;bluetooth_select_a2dp_channel_mode
+Bluetooth Audio Codec;bluetooth_select_a2dp_codec
+Bluetooth Audio LDAC Codec: Playback Quality;bluetooth_select_a2dp_ldac_playback_quality
+Bluetooth Audio Sample Rate;bluetooth_select_a2dp_sample_rate
+Bluetooth address;bt_address
+Bluetooth scanning;bluetooth_always_scanning
+Bluetooth tethering;enable_bluetooth_tethering
+Brightness level;brightness
+Browser app;default_browser
+Browser app;work_default_browser
+Bug report shortcut;bugreport_in_power
+Build number;build_number
+Call volume;call_volume
+Calls;zen_mode_calls_settings
+Calls;zen_mode_calls_settings_page
+Camera Laser Sensor;camera_laser_sensor_switch
+Camera permissions;enterprise_privacy_number_camera_access_packages
+Captions;captioning_preference_screen
+Cast;wifi_display_settings_screen
+Changes made by your organization's admin;exposure_changes_category
+Charging sounds;charging_sounds
+Clear credentials;credentials_reset
+Color correction;daltonizer_preference
+Color correction;daltonizer_preference_screen
+Color inversion;toggle_inversion_preference
+Colors;color_mode
+Colors;color_mode_settings_screen
+Connect to open networks;use_open_wifi_automatically
+Connected MAC Randomization;wifi_connected_mac_randomization
+Connected devices;connected_devices_screen
+Connected devices;top_level_connected_devices
+Connection preferences;connected_devices_advanced_screen
+Connection preferences;connection_preferences
+Convert to file encryption;convert_to_file_encryption
+Cool color temperature;color_temperature
+Copyright;copyright
+Correction mode;type
+Credential storage;credentials_management
+Current screen saver;current_screensaver
+Currently connected;connected_device_list
+Custom;zen_custom
+Custom restrictions;zen_mode_block_settings_page
+Data Saver;data_saver_screen
+Data Saver;restrict_background
+Data associated with your work account, such as email and calendar;enterprise_privacy_enterprise_data
+Data limit;data_limit
+Data usage;data_usage_screen
+Data warning;data_warning
+Data warning & limit;billing_cycle_settings
+Data warning & limit;billing_preference
+Date & time;date_time_settings_screen
+Debug GPU overdraw;debug_hw_overdraw
+Debug non-rectangular clip operations;show_non_rect_clip
+Debugging;debug_debugging_category
+Default USB configuration;default_usb_configuration
+Default alarm sound;alarm_ringtone
+Default apps;app_default_settings_screen
+Default apps;number_enterprise_set_default_apps
+Default for work;autofill_work_app_defaults
+Default for work;work_app_defaults
+Default keyboard;input_method
+Default notification sound;notification_default_ringtone
+Default notification sound;notification_ringtone
+Default work alarm sound;work_alarm_ringtone
+Default work notification sound;work_notification_ringtone
+Delay before click;autoclick_delay
+Desktop backup password;local_backup_password
+Developer options;development_prefs_screen
+Device admin apps;device_admin_settings
+Device admin apps;device_administrators
+Device admin apps;manage_device_admin
+Device name;device_name
+Device security;security_category
+Device theme;theme
+Dial pad tones;dial_pad_tones
+Directory access;special_app_directory_access
+Disable Bluetooth A2DP hardware offload;bluetooth_disable_a2dp_hw_offload
+Disable HW overlays;disable_overlays
+Disable USB audio routing;usb_audio
+Disable absolute volume;bluetooth_disable_absolute_volume
+Display;display_category
+Display;display_settings_screen
+Display;top_level_display
+Display cutout;display_cutout_emulation
+Display over other apps;system_alert_window
+Display size;accessibility_settings_screen_zoom
+Display size;display_settings_screen_zoom
+Display size;screen_zoom_settings
+Do Not Disturb;zen_mode
+Do Not Disturb;zen_mode_notifications
+Do Not Disturb;zen_mode_settings
+Do Not Disturb access;zen_access
+Do Not Disturb access;zen_access_screen
+Dock speaker plays;dock_audio_media
+Docking sounds;docking_sounds
+Don't blink light;zen_effect_light
+Don't pop notifications on screen;zen_effect_peek
+Don't turn on screen;zen_effect_intent
+Don't wake for notifications;zen_effect_ambient
+Don’t keep activities;immediately_destroy_activities
+Double twist for camera;camera_gesture
+Double-tap to check phone;ambient_display_double_tap
+Double-tap to check phone;gesture_double_tap_screen
+Double-tap to check phone;gesture_double_tap_screen_input_summary
+Downloaded services;user_installed_services_category
+Drawing;debug_drawing_category
+Duration;zen_mode_duration_settings
+Dwell timing;autoclick_preference
+Dwell timing;autoclick_preference_screen
+Emergency alerts;app_and_notif_cell_broadcast_settings
+Emergency app;default_emergency_app
+Emergency dialing signal;emergency_tone
+Emergency information;emergency_info
+Enable Bluetooth HCI snoop log;bt_hci_snoop_log
+Enable GPU debug layers;enable_gpu_debug_layers
+Enable Wi-Fi Verbose Logging;wifi_verbose_logging
+Enable freeform windows;enable_freeform_support
+Enable view attribute inspection;debug_view_attributes
+Encrypt phone;encryption_and_credentials_encryption_status
+Encryption;encryption_and_credentials_status_category
+Encryption & credentials;encryption_and_credential
+Encryption & credentials;encryption_and_credentials_screen
+End time;night_display_end_time
+Equipment ID;fcc_equipment_id
+Erase all data (factory reset);factory_reset
+Exceptions;zen_mode_settings_category_exceptions
+Experimental;experimental_category
+Face authentication;face_settings
+Face authentication;security_settings_face_settings_page
+Failed password attempts before deleting all device data;failed_password_wipe_current_user
+Failed password attempts before deleting work profile data;failed_password_wipe_managed_profile
+Feature flags;feature_flags_dashboard
+Feature flags;feature_flags_settings
+Files;pref_files
+Files received via Bluetooth;bt_received_files
+Flash screen;flash
+Flip camera;gesture_double_twist
+Flip camera;gesture_double_twist_input_summary
+Font size;font_size
+Font size;font_size_preference_screen
+Font size;font_size_setting_screen
+Force 4x MSAA;force_msaa
+Force RTL layout direction;force_rtl_layout_all_locales
+Force activities to be resizable;force_resizable_activities
+Force allow apps on external;force_allow_on_external
+Force full GNSS measurements;enable_gnss_raw_meas_full_tracking
+Free up space;storage_settings_free_space
+Games;pref_games
+Gestures;gesture_settings
+Gestures;gesture_settings_screen
+Global HTTP proxy set;global_http_proxy
+Google Account;branded_account
+HDCP checking;hdcp_checking
+Hardware accelerated rendering;debug_hw_drawing_category
+Hearing aids;hearing_aid_preference
+Hide from notification list;zen_effect_list
+Hide notification dots;zen_effect_badge
+Hide status bar icons;zen_effect_status
+High contrast text;toggle_high_text_contrast_preference
+Home app;default_home
+Hotspot & tethering;tether_prefs_screen
+Hotspot & tethering;tether_settings
+Hotspot name;wifi_tether_network_name
+Hotspot password;wifi_tether_network_password
+IMEI;imei_info
+IP address;current_ip_address
+IP address;wifi_ip_address
+Improve your face data;security_settings_face_improve
+Input;debug_input_category
+Input assistance;input_assistance_category
+Install certificates;install_credentials
+Install from storage;credentials_install
+Install unknown apps;manage_external_sources
+Installed apps;installed_apps_web_action
+Instant Apps preferences;instant_app_web_action_pref
+Instant apps;instant_app_web_action_toggle
+Instant apps;web_action_category
+Intensity;night_display_temperature
+Interaction controls;interaction_control_category
+Internal shared storage;storage_settings_volume_private
+Internal storage;storage_settings_internal_storage
+Jump to camera;gesture_double_tap_power
+Jump to camera;gesture_double_tap_power_input_summary
+Keyboard & inputs;keyboards_category
+Keyboard assistance;keyboard_assistance_category
+Keyboard shortcuts helper;keyboard_shortcuts_helper
+Language;tts_default_lang
+Languages;phone_language
+Languages & input;language_and_input_settings_screen
+Large mouse pointer;toggle_large_pointer_icon
+Last full charge;last_full_charge
+Legal information;legal_container
+Legal information;legal_screen
+License;license
+Lift to check phone;ambient_display_pick_up
+Lift to check phone;gesture_pick_up
+Lift to check phone;gesture_pick_up_input_summary
+Lift to wake;lift_to_wake
+List of apps on your device;enterprise_privacy_installed_packages
+Local terminal;enable_terminal
+Location;location
+Location;location_settings
+Location for work profile;managed_profile_location_switch
+Location permissions;enterprise_privacy_number_location_access_packages
+Location services;location_services
+Lock device when unpinning;use_screen_lock
+Lock screen display;lockscreen_from_display_settings
+Lock screen display;security_lockscreen_settings_screen
+Lock screen message;owner_info_settings
+Logger buffer sizes;select_logd_size
+Logging level;autofill_logging_level
+MAC address;mac_address
+Magnification;magnification_preference_screen
+Magnification;magnification_preference_screen_title
+Magnify with button;screen_magnification_navbar_preference_screen
+Magnify with triple-tap;screen_magnification_gestures_preference_screen
+Make pattern visible;visiblepattern
+Make profile pattern visible;visiblepattern_profile
+Manage backup account;data_management
+Manage keyboards;add_virtual_keyboard_screen
+Manage keyboards;available_virtual_keyboard_page
+Managed device info;enterprise_privacy
+Managed device info;enterprise_privacy_settings
+Manual;manual
+Max requests per session;autofill_max_partitions
+Max visible datasets;autofill_visible_datasets
+Maximum connected Bluetooth audio devices;bluetooth_max_connected_audio_devices
+Media;media_category
+Media;zen_mode_media
+Media volume;media_volume
+Memory;memory
+Messages, events & reminders;zen_mode_msg_event_reminder_settings
+Messages, events & reminders;zen_mode_msg_event_reminder_settings_page
+Microphone permissions;enterprise_privacy_number_microphone_access_packages
+Mobile;mobile_category
+Mobile data;data_usage_enable
+Mobile data always active;mobile_data_always_on
+Mobile data usage;cellular_data_usage
+Mobile network;mobile_network_settings
+Mobile plan;manage_mobile_plan
+Model & hardware;device_model
+Modify system settings;write_settings_apps
+Monitoring;debug_monitoring_category
+Mono audio;toggle_master_mono
+Most recent bug report;bug_reports
+Most recent network traffic log;network_logs
+Most recent security log;security_logs
+Movie & TV apps;pref_movies
+Multiple users;user_settings_screen
+Music & audio;pref_music_audio
+NFC;toggle_nfc
+Network & internet;network_and_internet_screen
+Network & internet;top_level_network
+Network name;show_operator_name
+Network rating provider;network_scorer_picker
+Networking;debug_networking_category
+New notifications;ambient_display_notification
+Night Light;night_display
+Night Light;night_display_activated
+Night mode;dark_ui_mode
+No sound from notifications;zen_mute_notifications
+No visuals or sound from notifications;zen_hide_notifications
+Notification access;notification_access
+Notification access;notification_access_screen
+Notification volume;notification_volume
+Notifications;all_notifications
+Notifications;zen_mode_block_effects_settings
+Notifications;zen_mode_restrict_settings_page
+OEM unlocking;oem_unlock_enable
+On lock screen;lock_screen_notifications
+On lock screen;security_setting_lock_screen_notif
+Open network notification;notify_open_networks
+Opening links;domain_urls
+Opening links;manage_domain_url_screen
+Other apps;pref_other_apps
+Other files;storage_settings_misc_space
+Other sounds and vibrations;other_sounds_and_vibrations_category
+Other users;pref_secondary_users
+Pair new device;add_bt_devices
+Payment default;nfc_payment
+Personal dictionary;key_user_dictionary_settings
+Personal dictionary;user_dict_list
+Phone app;default_phone_app
+Phone app;work_default_phone_app
+Phone number;phone_number
+Phone ringtone;ringtone
+Photos & videos;pref_photos_videos
+Physical keyboard;physical_keyboard_pref
+Physical keyboard;physical_keyboard_screen
+Picture color mode;picture_color_mode
+Picture-in-picture;picture_in_picture
+Picture-in-picture;picture_in_picture_screen
+Pictures, videos;storage_settings_dcim_space
+Pitch;tts_default_pitch
+Pixel Imprint;fingerprint_settings
+Pixel Imprint;fingerprint_settings_profile
+Play media to;media_output
+Pointer location;pointer_location
+Pointer speed;pointer_speed
+Power button ends call;toggle_power_button_ends_call_preference
+Power button instantly locks;power_button_instantly_locks
+Power on sounds;boot_sounds
+Preferred engine;tts_engine_picker_screen
+Preferred engine;tts_engine_preference
+Premium SMS access;premium_sms
+Premium SMS access;premium_sms_screen
+Press Power & Volume Up together;gesture_prevent_ringing
+Prevent ringing;gesture_prevent_ringing_screen
+Prevent ringing;gesture_prevent_ringing_summary
+Previously connected devices;previously_connected_devices
+Previously connected devices;saved_device_list
+Print jobs;print_jobs_category
+Print services;print_services_category
+Printing;connected_device_printing
+Printing;print_settings_screen
+Privacy;security_settings_misc_category
+Private DNS;private_dns_settings
+Profile HWUI rendering;track_frame_time
+Proxy;proxy_settings
+Quick settings developer tiles;development_tile_settings
+Quick settings developer tiles;quick_settings_tiles
+Reach to check phone;gesture_reach
+Recent location requests;recent_location_requests
+Recent location requests;recent_location_requests_see_all
+Recently opened apps;recent_apps_category
+Recently sent;recent_notifications_category
+Redirect vibration;vibrate_input_devices
+Regulatory labels;regulatory_info
+Remove animations;toggle_disable_animations
+Reset ShortcutManager rate-limiting;reset_shortcut_manager_throttling
+Reset Wi-Fi, mobile & Bluetooth;network_reset_pref
+Reset app preferences;reset_app_prefs
+Reset options;reset_dashboard
+Reset options;reset_dashboard_fragment_screen
+Reset to default values;autofill_reset_developer_options
+Restricted apps;restricted_app
+Revoke USB debugging authorizations;clear_adb_keys
+Ring & notification vibration;notification_vibration_preference_screen
+Ring volume;ring_volume
+Running services;running_apps
+SIM card lock;sim_lock_settings
+SIM status;sim_status
+SMS app;default_sms_app
+Safety & regulatory manual;safety_info
+Scanning;location_scanning
+Scanning;scanning_screen
+Schedule;night_display_auto_mode
+Schedule;zen_mode_settings_category_schedule
+Screen lock;security_settings_password_sub_screen
+Screen lock;unlock_set_or_change
+Screen locking sounds;screen_locking_sounds
+Screen pinning;screen_pinning_settings
+Screen pinning;screen_pinning_settings_screen
+Screen readers;screen_reader_category
+Screen saver;dream_overview_screen
+Screen saver;screensaver
+Screen usage since full charge;screen_usage
+Security;wifi_tether_security
+Security & location;security_dashboard_page
+Security & location;top_level_security
+Security status;security_status
+See all;recent_location_requests_see_all_button
+Select debug app;debug_app
+Select mock location app;mock_location_app
+Select time zone;timezone
+Send feedback about this device;device_feedback
+Set data limit;set_data_limit
+Set data warning;set_data_warning
+Set date;date
+Set time;time
+Settings;top_level_settings
+Shortcut to prevent ringing;gesture_prevent_ringing_sound
+Show Bluetooth devices without names;bluetooth_show_devices_without_names
+Show background ANRs;show_all_anrs
+Show hardware layers updates;show_hw_layers_updates
+Show layout bounds;debug_layout
+Show lockdown option;security_setting_lockdown_enabled
+Show notification channel warnings;show_notification_channel_warnings
+Show passwords;show_password
+Show surface updates;show_screen_updates
+Show taps;show_touches
+Show view updates;show_hw_screen_updates
+Show virtual keyboard;show_virtual_keyboard_switch
+Simulate color space;simulate_color_space
+Simulate secondary displays;overlay_display_devices
+Sleep;screen_timeout
+Smallest width;density
+Smart Storage;toggle_asm
+Sound;sound_settings
+Sound;top_level_sound
+Sound & vibration;zen_mode_sound_vibration_settings_page
+Sound & vibration;zen_sound_vibration_settings
+Special app access;special_access
+Special app access;special_app_access_screen
+Speech rate;tts_default_rate
+Spell checker;spellcheckers_settings
+Squeeze for silence;gesture_assist_silence
+Squeeze for your Assistant;gesture_assist
+Squeeze sensitivity;gesture_assist_sensitivity
+Standby apps;inactive_apps
+Starred contacts;zen_mode_starred_contacts_callers
+Starred contacts;zen_mode_starred_contacts_messages
+Start time;night_display_start_time
+Stay awake;keep_screen_on
+Storage;storage_dashboard_screen
+Storage;storage_settings
+Storage;top_level_storage
+Storage type;credential_storage_type
+Store logger data persistently on device;select_logpersist
+Strict mode enabled;strict_mode
+Swipe fingerprint;gesture_swipe_down_fingerprint_screen
+Swipe fingerprint for notifications;gesture_swipe_down_fingerprint
+Swipe fingerprint for notifications;gesture_swipe_down_fingerprint_input_summary
+Swipe fingerprint for notifications;gesture_swipe_down_fingerprint_notifications
+Swipe up on Home button;gesture_swipe_up
+Swipe up on Home button;gesture_swipe_up_input_summary
+Switch to mobile data automatically;wifi_cellular_data_fallback
+System;pref_system
+System;system_dashboard_screen
+System;top_level_system
+System UI demo mode;demo_mode
+System WebView License;webview_license
+System updates;system_update_settings
+Take bug report;bugreport
+Take call on;take_call_on_output
+Tap & pay;default_payment_app
+Tap & pay;nfc_payment_settings_screen
+Tap to wake;tap_to_wake
+Terms and conditions;terms
+Tethering hardware acceleration;tethering_hardware_offload
+Text-to-speech output;tts_settings_preference
+Text-to-speech output;tts_settings_screen
+Text-to-speech output;tts_settings_summary
+This device's data is being backed up;backups_enabled
+Tips & support;support_dashboard_activity
+Tips & support;top_level_support
+To extend your battery life, Battery Saver turns off some device features and restricts apps.;battery_saver_footer_preference
+Total space;storage_settings_memory_size
+Touch & hold delay;select_long_press_timeout_preference
+Touch sounds;touch_sounds
+Touch sounds;zen_mode_system
+Touch vibration;touch_vibration_preference_screen
+Touch vibration;vibrate_on_touch
+Transition animation scale;transition_animation_scale
+Trust agents;manage_trust_agents
+Trust agents;trust_agents
+Trusted credentials;trusted_credentials
+Trusted credentials in your personal profile;ca_certs_current_user
+Trusted credentials in your work profile;ca_certs_managed_profile
+Turn off hotspot automatically;wifi_tether_auto_turn_off
+Turn on;battery_saver_seek_bar
+Turn on Wi-Fi automatically;enable_wifi_wakeup
+Turn on automatically;auto_battery_saver
+Turn on automatically;zen_mode_automation_settings
+Types of information your organization can see;exposure_category
+USB Preferences;usb_details_fragment
+USB controlled by;usb_details_data_role
+USB debugging;enable_adb
+USB tethering;usb_tether_settings
+Unlock your device;security_settings_face_unlock
+Unrestricted data;data_saver
+Unrestricted data;unrestricted_access
+Unrestricted data;unrestricted_data_screen
+Up time;up_time
+Usage access;special_app_usage_access
+Use 24-hour format;24 hour
+Use Adaptive Battery;smart_battery
+Use Battery Manager;auto_restriction
+Use Bluetooth when driving;bluetooth_on_while_driving
+Use USB for;usb_details_functions
+Use default;nfc_foreground
+Use one lock;unification
+Use personal profile sounds;work_use_personal_sounds
+Use screenshot;screenshot
+Use text from screen;context
+Use your face to;security_settings_face_unlock_category
+User credentials;user_credentials
+Users & profiles;user_list
+VPN;vpn_settings
+VR helper services;enabled_vr_listeners
+VR helper services;vr_listener_settings
+Verify apps over USB;verify_apps_over_usb
+Vibration;accessibility_settings_vibration_screen
+Vibration;vibration_preference_screen
+Virtual keyboard;virtual_keyboard_category
+Virtual keyboard;virtual_keyboard_pref
+Voice input;voice_input_settings
+Volume key shortcut;accessibility_shortcut_preference
+Wait for debugger;wait_for_debugger
+Wallpaper;wallpaper
+Wallpapers;wallpaper_attributions
+Wallpapers;wallpaper_type_settings
+WebView implementation;select_webview_provider
+What to show;lockscreen_what_to_show
+When Do Not Disturb is turned on;restrict_category
+When Do Not Disturb is turned on;zen_mode_settings_category_calls
+When Do Not Disturb is turned on;zen_mode_settings_category_msg_event_reminder
+When Do Not Disturb is turned on;zen_mode_settings_category_sound_vibration
+When device is in VR;vr_display_pref
+When the screen is off;zen_mode_block_screen_off
+When the screen is on;zen_mode_block_screen_on
+When to show;ambient_display_category_when_to_show
+When to start;when_to_start
+When work profile is locked;lock_screen_notifications_profile
+When work profile is locked;security_setting_lock_screen_notif_work
+Wi-Fi;main_toggle_wifi
+Wi-Fi;toggle_wifi
+Wi-Fi;wifi_category
+Wi-Fi Direct;wifi_direct
+Wi-Fi MAC address;wifi_mac_address
+Wi-Fi control;change_wifi_state
+Wi-Fi data usage;wifi_data_usage
+Wi-Fi hotspot;wifi_tether
+Wi-Fi hotspot;wifi_tether_settings_screen
+Wi-Fi preferences;wifi_configure_settings_screen
+Wi-Fi scanning;wifi_always_scanning
+Window animation scale;window_animation_scale
+Wireless display certification;wifi_display_certification
+Work notifications;lock_screen_notifications_profile_header
+Work notifications;security_setting_lock_screen_notif_work_header
+Work phone ringtone;work_ringtone
+Work profile lock;unlock_set_or_change_profile
+Work profile security;security_category_profile
+Work profile sounds;sound_work_settings_section
+Your access to this device;device_access_category
+ ;auto_awesome_battery
+ ;auto_brightness_video
+ ;battery_header
+ ;battery_tip
+ ;feature_flag_category
\ No newline at end of file
diff --git a/tests/uitests/src/com/android/settings/search/SearchData.java b/tests/uitests/src/com/android/settings/search/SearchData.java
new file mode 100644
index 0000000..201841b
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/search/SearchData.java
@@ -0,0 +1,81 @@
+package uitests.src.com.android.settings.search;
+
+import android.text.TextUtils;
+import java.util.Objects;
+
+
+/**
+ * Data class for {@link com.android.settings.search.SettingsSearchResultRegressionTest}
+ */
+public class SearchData {
+ public final String title;
+ public final String key;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getKey() {
+ return key;
+ }
+ public static final String DELIM = ";";
+
+ public static SearchData from(String searchDataString) {
+ String[] split = searchDataString.trim().split(DELIM, -1);
+
+ if (split.length != 2) {
+ throw new IllegalArgumentException("Arg is invalid: " + searchDataString);
+ }
+
+ return new SearchData.Builder()
+ .setTitle(split[0])
+ .setKey(split[1])
+ .build();
+ }
+
+ @Override
+ public String toString() {
+ return title + DELIM + key;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SearchData)) {
+ return false;
+ }
+
+ SearchData other = (SearchData) obj;
+ return TextUtils.equals(this.title, other.title)
+ && TextUtils.equals(this.key, other.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(title, key);
+ }
+
+ private SearchData(
+ SearchData.Builder builder) {
+ this.title = builder.title;
+ this.key = builder.key;
+ }
+
+ public static class Builder {
+ protected String title = "";
+ protected String key = "";
+
+ public SearchData build() {
+ return new SearchData(this);
+ }
+
+ public SearchData.Builder setTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ public SearchData.Builder setKey(String key) {
+ this.key = key;
+ return this;
+ }
+ }
+}
diff --git a/tests/uitests/src/com/android/settings/search/SettingsSearchResultRegressionTest.java b/tests/uitests/src/com/android/settings/search/SettingsSearchResultRegressionTest.java
new file mode 100644
index 0000000..31900e4
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/search/SettingsSearchResultRegressionTest.java
@@ -0,0 +1,210 @@
+
+/*
+ * Copyright (C) 2018 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 static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import uitests.src.com.android.settings.search.SearchData;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SettingsSearchResultRegressionTest {
+
+ private Context mContext;
+
+ public interface IndexColumns {
+ String DATA_TITLE = "data_title";
+ String DATA_KEY_REF = "data_key_reference";
+ }
+
+ private static final String ERROR_RESULTS_MISSING =
+ "\nSettings search results missing. \n"
+ + "If the changes are intentional, we want to update the master-list.\n";
+
+ private static final String ERROR_NEW_RESULTS =
+ "\nNew settings search results have been found.\nIf the changes are intentional, we want to"
+ + "prevent the new results from regressing.\n";
+
+ private static final String ERROR_RERUN_TEST =
+ "Please re-run the test \"generate_search_result_list\" by removing the '@Ignore' annotation above 'generate_search_result_list' test, and run: \n"
+ + "$ runtest --path packages/apps/Settings/tests/uitests/src/com/android/settings/search/SettingsSearchResultRegressionTest.java \n"
+ + "and copy the output into 'packages/apps/Settings/tests/uitests/assets/search_result_list'\n";
+
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ /**
+ * Tests that the set of search results does not regress.
+ * <p>
+ * The data set used here (/tests/unit/assets/search_results_list) needs to be updated
+ * every once in a while so that we can check newly added results.
+ * </p>
+ */
+ @Test
+ @Presubmit
+ public void searchResultsDoNotRegress() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final Uri uri = getTestProviderUri();
+ final Cursor cursor = resolver.query(uri, null, null, null, null);
+
+ if (cursor == null) {
+ // Assume Settings Intelligence is wrong.
+ return;
+ }
+
+ final Set<SearchData> availableSearchResults = getSearchDataFromCursor(cursor);
+ final Set<SearchData> registeredSearchResults = getRegisteredResults();
+
+ // Seed with results that we expect
+ final Set<SearchData> missingSearchResults = new HashSet<>(registeredSearchResults);
+ // Seed with results that are available
+ final Set<SearchData> newSearchResults = new HashSet<>(availableSearchResults);
+
+ // Remove all available results, leaving results that have been removed.
+ missingSearchResults.removeAll(availableSearchResults);
+ // Remove all results we expect, leaving results that have not yet been registered.
+ newSearchResults.removeAll(registeredSearchResults);
+
+ assertWithMessage(ERROR_RESULTS_MISSING + ERROR_RERUN_TEST)
+ .that(missingSearchResults).isEmpty();
+ assertWithMessage(ERROR_NEW_RESULTS + ERROR_RERUN_TEST).that(newSearchResults).isEmpty();
+ }
+
+ // TODO (b/113907111) add a test to catch duplicate title search results.
+
+ /**
+ * Test to generate a new list of search results. Uncomment the Test annotation and run the
+ * test to generate the list.
+ */
+ @Ignore
+ @Test
+ public void generate_search_result_list() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final Uri uri = getTestProviderUri();
+ final Cursor cursor = resolver.query(uri, null, null, null, null);
+ final List<SearchData> availableSearchResults =
+ new ArrayList<>(getSearchDataFromCursor(cursor));
+
+ Collections.sort(availableSearchResults, Comparator.comparing(SearchData::getTitle)
+ .thenComparing(SearchData::getKey));
+
+ assertThat(generateListFromSearchData(availableSearchResults)).isNull();
+ }
+
+ private Set<SearchData> getSearchDataFromCursor(Cursor cursor) {
+ final Set<SearchData> searchData = new HashSet<>();
+
+ final int titleIndex = cursor.getColumnIndex(
+ IndexColumns.DATA_TITLE);
+ final int keyIndex = cursor.getColumnIndex(
+ IndexColumns.DATA_KEY_REF);
+
+ while (cursor.moveToNext()) {
+ String title = cursor.getString(titleIndex);
+ String key = cursor.getString(keyIndex);
+
+ if (TextUtils.isEmpty(title)) {
+ title = "";
+ }
+
+ if (TextUtils.isEmpty(key)) {
+ key = "";
+ }
+
+ searchData.add(new SearchData.Builder()
+ .setTitle(title)
+ .setKey(key)
+ .build());
+ }
+
+ return searchData;
+ }
+
+ /**
+ * Utility method to generate the list of search results that this class uses to validate
+ * results.
+ */
+ private String generateListFromSearchData(List<SearchData> searchData) {
+ StringBuilder builder = new StringBuilder();
+ for (SearchData searchResult : searchData) {
+ builder.append(searchResult.title)
+ .append(
+ SearchData.DELIM)
+ .append(searchResult.key)
+ .append("\n");
+ }
+ return builder.toString();
+ }
+
+ private Uri getTestProviderUri() {
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority("com.google.android.settings.intelligence.modules.search.regression")
+ .build();
+ }
+
+ private Set<SearchData> getRegisteredResults() {
+ final String filename = "search_results_list";
+ final Set<SearchData> registeredResults = new HashSet<>();
+
+ try {
+ final InputStream in = mContext.getAssets().open(filename);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ registeredResults.add(
+ SearchData.from(line));
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Error initializing registered result list "
+ + filename, e);
+ }
+
+ return registeredResults;
+ }
+}
\ No newline at end of file