</intent-filter>
</activity>
- <provider android:name=".SettingsSliceProvider"
+ <provider android:name=".slices.SettingsSliceProvider"
android:authorities="com.android.settings.slices"
android:exported="true">
</provider>
<receiver
- android:name=".SliceBroadcastReceiver" >
+ android:name=".slices.SliceBroadcastReceiver" >
<intent-filter>
<action android:name="com.android.settings.slice.action.WIFI_CHANGED"/>
</intent-filter>
private static final String TAG = "IndexingUtil";
- private static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
+ public static final String FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER =
"SEARCH_INDEX_DATA_PROVIDER";
/**
* limitations under the License
*/
-package com.android.settings;
+package com.android.settings.slices;
import android.app.PendingIntent;
-import android.app.slice.Slice;
-import android.app.slice.SliceProvider;
+
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
-import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import com.android.settings.R;
+
+import androidx.app.slice.Slice;
+import androidx.app.slice.SliceProvider;
+import androidx.app.slice.builders.ListBuilder;
+
public class SettingsSliceProvider extends SliceProvider {
public static final String SLICE_AUTHORITY = "com.android.settings.slices";
public static final String PATH_WIFI = "wifi";
public static final String ACTION_WIFI_CHANGED =
"com.android.settings.slice.action.WIFI_CHANGED";
- // TODO -- Associate slice URI with search result instead of separate hardcoded thing
- public static final String[] WIFI_SEARCH_TERMS = {"wi-fi", "wifi", "internet"};
+ // TODO -- Associate slice URI with search result instead of separate hardcoded thing
public static Uri getUri(String path) {
return new Uri.Builder()
.scheme(ContentResolver.SCHEME_CONTENT)
}
@Override
- public boolean onCreate() {
+ public boolean onCreateSliceProvider() {
return true;
}
String path = sliceUri.getPath();
switch (path) {
case "/" + PATH_WIFI:
- return createWifi(sliceUri);
-
+ return createWifiSlice(sliceUri);
}
throw new IllegalArgumentException("Unrecognized slice uri: " + sliceUri);
}
- private Slice createWifi(Uri uri) {
+
+ // TODO (b/70622039) remove this when the proper wifi slice is enabled.
+ private Slice createWifiSlice(Uri sliceUri) {
// Get wifi state
- String[] toggleHints;
WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
int wifiState = wifiManager.getWifiState();
boolean wifiEnabled = false;
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
state = wifiManager.getConnectionInfo().getSSID();
- WifiInfo.removeDoubleQuotes(state);
wifiEnabled = true;
break;
case WifiManager.WIFI_STATE_UNKNOWN:
state = ""; // just don't show anything?
break;
}
- if (wifiEnabled) {
- toggleHints = new String[] {Slice.HINT_TOGGLE, Slice.HINT_SELECTED};
- } else {
- toggleHints = new String[] {Slice.HINT_TOGGLE};
- }
- // Construct the slice
- Slice.Builder b = new Slice.Builder(uri);
- b.addSubSlice(new Slice.Builder(b)
- .addAction(getIntent("android.settings.WIFI_SETTINGS"),
- new Slice.Builder(b)
- .addText(getContext().getString(R.string.wifi_settings), null)
- .addText(state, null)
- .addIcon(Icon.createWithResource(getContext(),
- R.drawable.ic_settings_wireless), null, Slice.HINT_HIDDEN)
- .addHints(Slice.HINT_TITLE)
- .build())
- .addAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
- new Slice.Builder(b)
- .addHints(toggleHints)
- .build())
- .build());
- return b.build();
+
+ boolean finalWifiEnabled = wifiEnabled;
+ return new ListBuilder(sliceUri)
+ .setColor(R.color.material_blue_500)
+ .add(b -> b
+ .setTitle(getContext().getString(R.string.wifi_settings))
+ .setTitleItem(Icon.createWithResource(getContext(), R.drawable.wifi_signal))
+ .setSubtitle(state)
+ .addToggle(getBroadcastIntent(ACTION_WIFI_CHANGED), finalWifiEnabled)
+ .setContentIntent(getIntent(Intent.ACTION_MAIN)))
+ .build();
}
private PendingIntent getIntent(String action) {
* limitations under the License
*/
-package com.android.settings;
+package com.android.settings.slices;
-import static com.android.settings.SettingsSliceProvider.ACTION_WIFI_CHANGED;
+import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED;
import android.app.slice.Slice;
import android.content.BroadcastReceiver;
// Wait a bit for wifi to update (TODO: is there a better way to do this?)
Handler h = new Handler();
h.postDelayed(() -> {
- Uri uri = SettingsSliceProvider.getUri(SettingsSliceProvider.PATH_WIFI);
- context.getContentResolver().notifyChange(uri, null);
+ Uri uri = SettingsSliceProvider.getUri(SettingsSliceProvider.PATH_WIFI);
+ context.getContentResolver().notifyChange(uri, null);
}, 1000);
break;
}
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.slices;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+/**
+ * TODO (b/67996923) Add SlicesIndexingManager
+ * Data class representing a slice stored by {@link SlicesIndexingManager}.
+ * Note that {@link #key} is treated as a primary key for this class and determines equality.
+ */
+public class SliceData {
+
+ private final String key;
+
+ private final String title;
+
+ private final String summary;
+
+ private final String screenTitle;
+
+ private final int iconResource;
+
+ private final String fragmentClassName;
+
+ private final Uri uri;
+
+ private final String preferenceController;
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getSummary() {
+ return summary;
+ }
+
+ public String getScreenTitle() {
+ return screenTitle;
+ }
+
+ public int getIconResource() {
+ return iconResource;
+ }
+
+ public String getFragmentClassName() {
+ return fragmentClassName;
+ }
+
+ public Uri getUri() {
+ return uri;
+ }
+
+ public String getPreferenceController() {
+ return preferenceController;
+ }
+
+ private SliceData(Builder builder) {
+ key = builder.mKey;
+ title = builder.mTitle;
+ summary = builder.mSummary;
+ screenTitle = builder.mScreenTitle;
+ iconResource = builder.mIconResource;
+ fragmentClassName = builder.mFragmentClassName;
+ uri = builder.mUri;
+ preferenceController = builder.mPrefControllerClassName;
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof SliceData)) {
+ return false;
+ }
+ SliceData newObject = (SliceData) obj;
+ return TextUtils.equals(key, newObject.key);
+ }
+
+ static class Builder {
+ private String mKey;
+
+ private String mTitle;
+
+ private String mSummary;
+
+ private String mScreenTitle;
+
+ private int mIconResource;
+
+ private String mFragmentClassName;
+
+ private Uri mUri;
+
+ private String mPrefControllerClassName;
+
+ public Builder setKey(String key) {
+ mKey = key;
+ return this;
+ }
+
+ public Builder setTitle(String title) {
+ mTitle = title;
+ return this;
+ }
+
+ public Builder setSummary(String summary) {
+ mSummary = summary;
+ return this;
+ }
+
+ public Builder setScreenTitle(String screenTitle) {
+ mScreenTitle = screenTitle;
+ return this;
+ }
+
+ public Builder setIcon(int iconResource) {
+ mIconResource = iconResource;
+ return this;
+ }
+
+ public Builder setPreferenceControllerClassName(String controllerClassName) {
+ mPrefControllerClassName = controllerClassName;
+ return this;
+ }
+
+ public Builder setFragmentName(String fragmentClassName) {
+ mFragmentClassName = fragmentClassName;
+ return this;
+ }
+
+ public Builder setUri(Uri uri) {
+ mUri = uri;
+ return this;
+ }
+
+ public SliceData build() {
+ if (TextUtils.isEmpty(mKey)) {
+ throw new IllegalStateException("Key cannot be empty");
+ }
+
+ if (TextUtils.isEmpty(mTitle)) {
+ throw new IllegalStateException("Title cannot be empty");
+ }
+
+ if (TextUtils.isEmpty(mFragmentClassName)) {
+ throw new IllegalStateException("Fragment Name cannot be empty");
+ }
+
+ if (TextUtils.isEmpty(mPrefControllerClassName)) {
+ throw new IllegalStateException("Preference Controller cannot be empty");
+ }
+
+ if (mUri == null) {
+ throw new IllegalStateException("Uri cannot be null");
+ }
+
+ return new SliceData(this);
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package com.android.settings.slices;
+
+import android.content.Context;
+
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Defines the schema for the Slices database.
+ */
+public class SlicesDatabaseHelper extends SQLiteOpenHelper {
+
+ private static final String TAG = "SlicesDatabaseHelper";
+
+ private static final String DATABASE_NAME = "slices_index.db";
+ private static final String SHARED_PREFS_TAG = "slices_shared_prefs";
+
+ private static final int DATABASE_VERSION = 1;
+
+ public interface Tables {
+ String TABLE_SLICES_INDEX = "slices_index";
+ }
+
+ public interface IndexColumns {
+ /**
+ * Primary key of the DB. Preference key from preference controllers.
+ */
+ String KEY = "key";
+
+ /**
+ * Title of the Setting.
+ */
+ String TITLE = "title";
+
+ /**
+ * Summary / Subtitle for the setting.
+ */
+ String SUBTITLE = "subtitle";
+
+ /**
+ * Title of the Setting screen on which the Setting lives.
+ */
+ String SCREENTITLE = "screentitle";
+
+ /**
+ * Resource ID for the icon of the setting. Should be 0 for no icon.
+ */
+ String ICON_RESOURCE = "icon";
+
+ /**
+ * Classname of the fragment name of the page that hosts the setting.
+ */
+ String FRAGMENT = "fragment";
+
+ /**
+ * Class name of the controller backing the setting. Must be a
+ * {@link com.android.settings.core.BasePreferenceController}.
+ */
+ String CONTROLLER = "controller";
+ }
+
+ private static final String CREATE_SLICES_TABLE =
+ "CREATE VIRTUAL TABLE " + Tables.TABLE_SLICES_INDEX + " USING fts4" +
+ "(" +
+ IndexColumns.KEY +
+ ", " +
+ IndexColumns.TITLE +
+ ", " +
+ IndexColumns.SUBTITLE +
+ ", " +
+ IndexColumns.SCREENTITLE +
+ ", " +
+ IndexColumns.ICON_RESOURCE +
+ ", " +
+ IndexColumns.FRAGMENT +
+ ", " +
+ IndexColumns.CONTROLLER +
+ ");";
+
+ private final Context mContext;
+
+ public SlicesDatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null /* CursorFactor */, DATABASE_VERSION);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createDatabases(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (oldVersion < DATABASE_VERSION) {
+ Log.d(TAG, "Reconstructing DB from " + oldVersion + "to " + newVersion);
+ reconstruct(db);
+ }
+ }
+
+ @VisibleForTesting
+ void reconstruct(SQLiteDatabase db) {
+ mContext.getSharedPreferences(SHARED_PREFS_TAG, Context.MODE_PRIVATE)
+ .edit()
+ .clear()
+ .commit();
+ dropTables(db);
+ createDatabases(db);
+ }
+
+ private void createDatabases(SQLiteDatabase db) {
+ db.execSQL(CREATE_SLICES_TABLE);
+ Log.d(TAG, "Created databases");
+ }
+
+
+ private void dropTables(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + Tables.TABLE_SLICES_INDEX);
+ }
+}
\ No newline at end of file
"SettingsPreferenceFragment should implement Indexable, but these do not:\n";
private static final String NOT_CONTAINING_PROVIDER_OBJECT_ERROR =
"Indexable should have public field "
- + DatabaseIndexingManager.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
+ + DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
+ " but these are not:\n";
private static final String NOT_SHARING_PREF_CONTROLLERS_BETWEEN_FRAG_AND_PROVIDER =
"DashboardFragment should share pref controllers with its SearchIndexProvider, but "
+ " these are not: \n";
private static final String NOT_IN_INDEXABLE_PROVIDER_REGISTRY =
- "Class containing " + DatabaseIndexingManager.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
+ "Class containing " + DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER
+ " must be added to " + SearchIndexableResources.class.getName()
+ " but these are not: \n";
private static final String NOT_PROVIDING_VALID_RESOURCE_ERROR =
private boolean hasSearchIndexProvider(Class clazz) {
try {
final Field f = clazz.getField(
- DatabaseIndexingManager.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
+ DatabaseIndexingUtils.FIELD_NAME_SEARCH_INDEX_DATA_PROVIDER);
return f != null;
} catch (NoClassDefFoundError e) {
// Cannot find class def, ignore
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.slices;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SliceDataTest {
+
+ private final String KEY = "KEY";
+ private final String TITLE = "title";
+ private final String SUMMARY = "summary";
+ private final String SCREEN_TITLE = "screen title";
+ private final String FRAGMENT_NAME = "fragment name";
+ private final int ICON = 1234; // I declare a thumb war
+ private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
+ private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
+
+ @Test
+ public void testBuilder_buildsMatchingObject() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData data = builder.build();
+
+ assertThat(data.getKey()).isEqualTo(KEY);
+ assertThat(data.getTitle()).isEqualTo(TITLE);
+ assertThat(data.getSummary()).isEqualTo(SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(SCREEN_TITLE);
+ assertThat(data.getIconResource()).isEqualTo(ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FRAGMENT_NAME);
+ assertThat(data.getUri()).isEqualTo(URI);
+ assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilder_noKey_throwsIllegalStateException() {
+ new SliceData.Builder()
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER)
+ .build();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilder_noTitle_throwsIllegalStateException() {
+ new SliceData.Builder()
+ .setKey(KEY)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER)
+ .build();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilder_noFragment_throwsIllegalStateException() {
+ new SliceData.Builder()
+ .setKey(KEY)
+ .setFragmentName(FRAGMENT_NAME)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER)
+ .build();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilder_noUri_throwsIllegalStateException() {
+ new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setPreferenceControllerClassName(PREF_CONTROLLER)
+ .build();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testBuilder_noPrefController_throwsIllegalStateException() {
+ new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setUri(URI)
+ .setFragmentName(FRAGMENT_NAME)
+ .build();
+ }
+
+ @Test
+ public void testBuilder_noSubtitle_buildsMatchingObject() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData data = builder.build();
+
+ assertThat(data.getKey()).isEqualTo(KEY);
+ assertThat(data.getTitle()).isEqualTo(TITLE);
+ assertThat(data.getSummary()).isNull();
+ assertThat(data.getScreenTitle()).isEqualTo(SCREEN_TITLE);
+ assertThat(data.getIconResource()).isEqualTo(ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FRAGMENT_NAME);
+ assertThat(data.getUri()).isEqualTo(URI);
+ assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
+ }
+
+ @Test
+ public void testBuilder_noScreenTitle_buildsMatchingObject() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData data = builder.build();
+
+ assertThat(data.getKey()).isEqualTo(KEY);
+ assertThat(data.getTitle()).isEqualTo(TITLE);
+ assertThat(data.getSummary()).isEqualTo(SUMMARY);
+ assertThat(data.getScreenTitle()).isNull();
+ assertThat(data.getIconResource()).isEqualTo(ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FRAGMENT_NAME);
+ assertThat(data.getUri()).isEqualTo(URI);
+ assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
+ }
+
+ @Test
+ public void testBuilder_noIcon_buildsMatchingObject() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData data = builder.build();
+
+ assertThat(data.getKey()).isEqualTo(KEY);
+ assertThat(data.getTitle()).isEqualTo(TITLE);
+ assertThat(data.getSummary()).isEqualTo(SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(SCREEN_TITLE);
+ assertThat(data.getIconResource()).isEqualTo(0);
+ assertThat(data.getFragmentClassName()).isEqualTo(FRAGMENT_NAME);
+ assertThat(data.getUri()).isEqualTo(URI);
+ assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
+ }
+
+ @Test
+ public void testEquality_identicalObjects() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData dataOne = builder.build();
+ SliceData dataTwo = builder.build();
+
+ assertThat(dataOne.hashCode()).isEqualTo(dataTwo.hashCode());
+ assertThat(dataOne).isEqualTo(dataTwo);
+ }
+
+ @Test
+ public void testEquality_matchingKey_EqualObjects() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData dataOne = builder.build();
+
+ builder.setTitle(TITLE + " diff")
+ .setSummary(SUMMARY + " diff")
+ .setScreenTitle(SCREEN_TITLE + " diff")
+ .setIcon(ICON + 1)
+ .setFragmentName(FRAGMENT_NAME + " diff")
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER + " diff");
+
+ SliceData dataTwo = builder.build();
+
+ assertThat(dataOne.hashCode()).isEqualTo(dataTwo.hashCode());
+ assertThat(dataOne).isEqualTo(dataTwo);
+ }
+
+ @Test
+ public void testEquality_differentKey_differentObjects() {
+ SliceData.Builder builder = new SliceData.Builder()
+ .setKey(KEY)
+ .setTitle(TITLE)
+ .setSummary(SUMMARY)
+ .setScreenTitle(SCREEN_TITLE)
+ .setIcon(ICON)
+ .setFragmentName(FRAGMENT_NAME)
+ .setUri(URI)
+ .setPreferenceControllerClassName(PREF_CONTROLLER);
+
+ SliceData dataOne = builder.build();
+
+ builder.setKey("not key");
+ SliceData dataTwo = builder.build();
+
+ assertThat(dataOne.hashCode()).isNotEqualTo(dataTwo.hashCode());
+ assertThat(dataOne).isNotEqualTo(dataTwo);
+ }
+}
--- /dev/null
+package com.android.settings.slices;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
+import com.android.settings.TestConfig;
+import com.android.settings.slices.SlicesDatabaseHelper.IndexColumns;
+import com.android.settings.testutils.DatabaseTestUtils;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SlicesDatabaseHelperTest {
+
+ private Context mContext;
+ private SlicesDatabaseHelper mSlicesDatabaseHelper;
+ private SQLiteDatabase mDatabase;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSlicesDatabaseHelper = new SlicesDatabaseHelper(mContext);
+ mDatabase = mSlicesDatabaseHelper.getWritableDatabase();
+ }
+
+ @After
+ public void cleanUp() {
+ DatabaseTestUtils.clearDb(mContext);
+ }
+
+ @Test
+ public void testDatabaseSchema() {
+ Cursor cursor = mDatabase.rawQuery("SELECT * FROM slices_index", null);
+ String[] columnNames = cursor.getColumnNames();
+
+ String[] expectedNames = new String[]{
+ IndexColumns.KEY,
+ IndexColumns.TITLE,
+ IndexColumns.SUBTITLE,
+ IndexColumns.SCREENTITLE,
+ IndexColumns.ICON_RESOURCE,
+ IndexColumns.FRAGMENT,
+ IndexColumns.CONTROLLER
+ };
+
+ assertThat(columnNames).isEqualTo(expectedNames);
+ }
+
+ @Test
+ public void testUpgrade_dropsOldData() {
+ ContentValues dummyValues = getDummyRow();
+
+ mDatabase.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, dummyValues);
+ Cursor baseline = mDatabase.rawQuery("SELECT * FROM slices_index", null);
+ assertThat(baseline.getCount()).isEqualTo(1);
+
+ mSlicesDatabaseHelper.onUpgrade(mDatabase, 0, 1);
+
+ Cursor newCursor = mDatabase.rawQuery("SELECT * FROM slices_index", null);
+ assertThat(newCursor.getCount()).isEqualTo(0);
+ }
+
+ private ContentValues getDummyRow() {
+ ContentValues values;
+
+ values = new ContentValues();
+ values.put(IndexColumns.KEY, "key");
+ values.put(IndexColumns.TITLE, "title");
+ values.put(IndexColumns.SUBTITLE, "subtitle");
+ values.put(IndexColumns.ICON_RESOURCE, 99);
+ values.put(IndexColumns.FRAGMENT, "fragmentClassName");
+ values.put(IndexColumns.CONTROLLER, "preferenceController");
+
+ return values;
+ }
+}