From 79c6395295fa2361901ed94bd5ee035418626d81 Mon Sep 17 00:00:00 2001 From: Matthew Fritze Date: Fri, 2 Mar 2018 10:24:42 -0800 Subject: [PATCH] Index SliceType and Official Platform flag Extend slices_index.db to include SliceType and platform flag. This will be used when we generate a list of all available slices for different authorities & separated intent/action paths. Bug: 62807132 Test: robotests Change-Id: I1cce49d077c02ab79153db9bfdfc894dbab5e16a --- res/xml/power_usage_summary.xml | 3 +- .../settings/slices/SliceBuilderUtils.java | 33 ++++++++++++ .../slices/SlicesDatabaseAccessor.java | 34 ++++++++---- .../settings/slices/SlicesDatabaseHelper.java | 14 +++++ .../settings/slices/SlicesIndexer.java | 2 + ...java => PreferenceXmlParserUtilsTest.java} | 2 +- .../slices/SettingsSliceProviderTest.java | 4 +- .../slices/SliceBuilderUtilsTest.java | 54 +++++++++++++++++++ .../slices/SlicesDatabaseAccessorTest.java | 6 +-- .../slices/SlicesDatabaseHelperTest.java | 4 +- .../settings/slices/SlicesIndexerTest.java | 40 +++++++++----- 11 files changed, 167 insertions(+), 29 deletions(-) rename tests/robotests/src/com/android/settings/core/{PreferenceXmlParserUtilTest.java => PreferenceXmlParserUtilsTest.java} (99%) diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index ac96151557e..391ef2cfaf6 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -37,7 +37,8 @@ android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings" android:key="battery_saver_summary" android:title="@string/battery_saver" - settings:controller="com.android.settings.fuelgauge.BatterySaverController"/> + settings:controller="com.android.settings.fuelgauge.BatterySaverController" + settings:platform_slice="true"/> + * Examples of valid paths are: + * - intent/wifi + * - intent/bluetooth + * - action/wifi + * - action/accessibility/servicename + * + * @param uri of the Slice. Follows pattern outlined in {@link SettingsSliceProvider}. + * @return Pair whose first element {@code true} if the path is prepended with "action", and + * second is a key. + */ + public static Pair getPathData(Uri uri) { + final String path = uri.getPath(); + final String[] split = path.split("/", 3); + + // Split should be: [{}, SLICE_TYPE, KEY]. + // Example: "/action/wifi" -> [{}, "action", "wifi"] + // "/action/longer/path" -> [{}, "action", "longer/path"] + if (split.length != 3) { + throw new IllegalArgumentException("Uri (" + uri + ") has incomplete path: " + path); + } + + final boolean isInline = TextUtils.equals(SettingsSlicesContract.PATH_SETTING_ACTION, + split[1]); + + return new Pair<>(isInline, split[2]); + } + /** * Looks at the {@link SliceData#preferenceController} from {@param sliceData} and attempts to * build an {@link AbstractPreferenceController}. diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java index acd296bd0e1..82b3506f739 100644 --- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java +++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java @@ -24,6 +24,7 @@ import android.net.Uri; import android.content.Context; import android.os.Binder; +import android.util.Pair; import com.android.settings.overlay.FeatureFactory; import com.android.settings.slices.SlicesDatabaseHelper.IndexColumns; @@ -35,7 +36,7 @@ import androidx.slice.Slice; */ public class SlicesDatabaseAccessor { - public static final String[] SELECT_COLUMNS = { + public static final String[] SELECT_COLUMNS_ALL = { IndexColumns.KEY, IndexColumns.TITLE, IndexColumns.SUMMARY, @@ -43,8 +44,13 @@ public class SlicesDatabaseAccessor { IndexColumns.ICON_RESOURCE, IndexColumns.FRAGMENT, IndexColumns.CONTROLLER, + IndexColumns.PLATFORM_SLICE, + IndexColumns.SLICE_TYPE, }; + // Cursor value for boolean true + private final int TRUE = 1; + Context mContext; public SlicesDatabaseAccessor(Context context) { @@ -58,9 +64,9 @@ public class SlicesDatabaseAccessor { * Used when building a {@link Slice}. */ public SliceData getSliceDataFromUri(Uri uri) { - String key = uri.getLastPathSegment(); - Cursor cursor = getIndexedSliceData(key); - return buildSliceData(cursor, uri); + Pair pathData = SliceBuilderUtils.getPathData(uri); + Cursor cursor = getIndexedSliceData(pathData.second /* key */); + return buildSliceData(cursor, uri, pathData.first /* isIntentOnly */); } /** @@ -70,18 +76,18 @@ public class SlicesDatabaseAccessor { */ public SliceData getSliceDataFromKey(String key) { Cursor cursor = getIndexedSliceData(key); - return buildSliceData(cursor, null /* uri */); + return buildSliceData(cursor, null /* uri */, false /* isInlineOnly */); } private Cursor getIndexedSliceData(String path) { verifyIndexing(); - final String whereClause = buildWhereClause(); + final String whereClause = buildKeyMatchWhereClause(); final SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext); final SQLiteDatabase database = helper.getReadableDatabase(); final String[] selection = new String[]{path}; - Cursor resultCursor = database.query(TABLE_SLICES_INDEX, SELECT_COLUMNS, whereClause, + Cursor resultCursor = database.query(TABLE_SLICES_INDEX, SELECT_COLUMNS_ALL, whereClause, selection, null /* groupBy */, null /* having */, null /* orderBy */); int numResults = resultCursor.getCount(); @@ -99,13 +105,13 @@ public class SlicesDatabaseAccessor { return resultCursor; } - private String buildWhereClause() { + private String buildKeyMatchWhereClause() { return new StringBuilder(IndexColumns.KEY) .append(" = ?") .toString(); } - private SliceData buildSliceData(Cursor cursor, Uri uri) { + private SliceData buildSliceData(Cursor cursor, Uri uri, boolean isInlineOnly) { final String key = cursor.getString(cursor.getColumnIndex(IndexColumns.KEY)); final String title = cursor.getString(cursor.getColumnIndex(IndexColumns.TITLE)); final String summary = cursor.getString(cursor.getColumnIndex(IndexColumns.SUMMARY)); @@ -116,6 +122,14 @@ public class SlicesDatabaseAccessor { cursor.getColumnIndex(IndexColumns.FRAGMENT)); final String controllerClassName = cursor.getString( cursor.getColumnIndex(IndexColumns.CONTROLLER)); + final boolean isPlatformDefined = cursor.getInt( + cursor.getColumnIndex(IndexColumns.PLATFORM_SLICE)) == TRUE; + int sliceType = cursor.getInt( + cursor.getColumnIndex(IndexColumns.SLICE_TYPE)); + + if (!isInlineOnly) { + sliceType = SliceData.SliceType.INTENT; + } return new SliceData.Builder() .setKey(key) @@ -126,6 +140,8 @@ public class SlicesDatabaseAccessor { .setFragmentName(fragmentClassName) .setPreferenceControllerClassName(controllerClassName) .setUri(uri) + .setPlatformDefined(isPlatformDefined) + .setSliceType(sliceType) .build(); } diff --git a/src/com/android/settings/slices/SlicesDatabaseHelper.java b/src/com/android/settings/slices/SlicesDatabaseHelper.java index 627c62e55f9..43346658176 100644 --- a/src/com/android/settings/slices/SlicesDatabaseHelper.java +++ b/src/com/android/settings/slices/SlicesDatabaseHelper.java @@ -78,6 +78,16 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper { * {@link com.android.settings.core.BasePreferenceController}. */ String CONTROLLER = "controller"; + + /** + * Boolean flag, {@code true} when the Slice is officially platform-supported. + */ + String PLATFORM_SLICE = "platform_slice"; + + /** + * {@link SliceData.SliceType} representing the inline type of the result. + */ + String SLICE_TYPE = "slice_type"; } private static final String CREATE_SLICES_TABLE = @@ -96,6 +106,10 @@ public class SlicesDatabaseHelper extends SQLiteOpenHelper { IndexColumns.FRAGMENT + ", " + IndexColumns.CONTROLLER + + ", " + + IndexColumns.PLATFORM_SLICE + + ", " + + IndexColumns.SLICE_TYPE+ ");"; private final Context mContext; diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java index a92388aa752..d7de7bc27a9 100644 --- a/src/com/android/settings/slices/SlicesIndexer.java +++ b/src/com/android/settings/slices/SlicesIndexer.java @@ -108,6 +108,8 @@ class SlicesIndexer implements Runnable { values.put(IndexColumns.ICON_RESOURCE, dataRow.getIconResource()); values.put(IndexColumns.FRAGMENT, dataRow.getFragmentClassName()); values.put(IndexColumns.CONTROLLER, dataRow.getPreferenceController()); + values.put(IndexColumns.PLATFORM_SLICE, dataRow.isPlatformDefined()); + values.put(IndexColumns.SLICE_TYPE, dataRow.getSliceType()); database.replaceOrThrow(Tables.TABLE_SLICES_INDEX, null /* nullColumnHack */, values); diff --git a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilTest.java b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java similarity index 99% rename from tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilTest.java rename to tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java index 458bc023209..c96cebd9667 100644 --- a/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilTest.java +++ b/tests/robotests/src/com/android/settings/core/PreferenceXmlParserUtilsTest.java @@ -48,7 +48,7 @@ import java.util.List; * with another preference with a matchin replacement attribute. */ @RunWith(SettingsRobolectricTestRunner.class) -public class PreferenceXmlParserUtilTest { +public class PreferenceXmlParserUtilsTest { private Context mContext; diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java index 8ddd48a1672..d54d16fc6a4 100644 --- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java +++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java @@ -82,7 +82,7 @@ public class SettingsSliceProviderTest { @Test public void testInitialSliceReturned_emptySlice() { - insertSpecialCase(INTENT_PATH); + insertSpecialCase(KEY); Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false); Slice slice = mProvider.onBindSlice(uri); @@ -93,7 +93,7 @@ public class SettingsSliceProviderTest { @Test public void testLoadSlice_returnsSliceFromAccessor() { insertSpecialCase(KEY); - Uri uri = SliceBuilderUtils.getUri(KEY, false); + Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false); mProvider.loadSlice(uri); SliceData data = mProvider.mSliceDataCache.get(uri); diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java index 39b381d4eeb..869ba489d6b 100644 --- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java +++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java @@ -24,6 +24,7 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.provider.SettingsSlicesContract; +import android.util.Pair; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; @@ -188,6 +189,59 @@ public class SliceBuilderUtilsTest { assertThat(summary).isEqualTo(data.getScreenTitle()); } + @Test + public void getPathData_splitsIntentUri() { + Uri uri = new Uri.Builder() + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_INTENT) + .appendPath(KEY) + .build(); + + Pair pathPair = SliceBuilderUtils.getPathData(uri); + + assertThat(pathPair.first).isFalse(); + assertThat(pathPair.second).isEqualTo(KEY); + } + + @Test + public void getPathData_splitsActionUri() { + Uri uri = new Uri.Builder() + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath(KEY) + .build(); + + Pair pathPair = SliceBuilderUtils.getPathData(uri); + + assertThat(pathPair.first).isTrue(); + assertThat(pathPair.second).isEqualTo(KEY); + } + + @Test(expected = IllegalArgumentException.class) + public void getPathData_noKey_returnsNull() { + Uri uri = new Uri.Builder() + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .build(); + + SliceBuilderUtils.getPathData(uri); + } + + @Test + public void getPathData_extraArg_returnsNull() { + Uri uri = new Uri.Builder() + .authority(SettingsSliceProvider.SLICE_AUTHORITY) + .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION) + .appendPath(KEY) + .appendPath(KEY) + .build(); + + Pair pathPair = SliceBuilderUtils.getPathData(uri); + + assertThat(pathPair.first).isTrue(); + assertThat(pathPair.second).isEqualTo(KEY + "/" + KEY); + } + private SliceData getDummyData() { return getDummyData(PREF_CONTROLLER, SUMMARY); } diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java index 331058c96c5..77c9891da18 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java @@ -89,8 +89,9 @@ public class SlicesDatabaseAccessorTest { @Test public void testGetSliceFromUri_validUri_validSliceReturned() { String key = "key"; + String path = "intent/" + key; insertSpecialCase(key); - Uri uri = SliceBuilderUtils.getUri(key, false); + Uri uri = SliceBuilderUtils.getUri(path, false); SliceData data = mAccessor.getSliceDataFromUri(uri); @@ -106,8 +107,7 @@ public class SlicesDatabaseAccessorTest { @Test(expected = IllegalStateException.class) public void testGetSliceFromUri_invalidUri_errorThrown() { - Uri uri = SliceBuilderUtils.getUri("durr", false); - + Uri uri = SliceBuilderUtils.getUri("intent/durr", false); mAccessor.getSliceDataFromUri(uri); } diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java index 7d1b4014c46..98ab2a1d024 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseHelperTest.java @@ -68,7 +68,9 @@ public class SlicesDatabaseHelperTest { IndexColumns.SCREENTITLE, IndexColumns.ICON_RESOURCE, IndexColumns.FRAGMENT, - IndexColumns.CONTROLLER + IndexColumns.CONTROLLER, + IndexColumns.PLATFORM_SLICE, + IndexColumns.SLICE_TYPE, }; assertThat(columnNames).isEqualTo(expectedNames); diff --git a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java index ca198cb2177..2af9c7925e4 100644 --- a/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java +++ b/tests/robotests/src/com/android/settings/slices/SlicesIndexerTest.java @@ -50,6 +50,8 @@ public class SlicesIndexerTest { 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"; + private final boolean PLATFORM_DEFINED = true; + private final int SLICE_TYPE = SliceData.SliceType.SLIDER; private Context mContext; @@ -109,10 +111,22 @@ public class SlicesIndexerTest { cursor.moveToFirst(); for (int i = 0; i < sliceData.size(); i++) { - assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.KEY))) - .isEqualTo(KEYS[i]); - assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.TITLE))) - .isEqualTo(TITLES[i]); + assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.KEY))).isEqualTo( + KEYS[i]); + assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.TITLE))).isEqualTo( + TITLES[i]); + assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.FRAGMENT))).isEqualTo( + FRAGMENT_NAME); + assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.SCREENTITLE))).isEqualTo( + SCREEN_TITLE); + assertThat(cursor.getInt(cursor.getColumnIndex(IndexColumns.ICON_RESOURCE))).isEqualTo( + ICON); + assertThat(cursor.getString(cursor.getColumnIndex(IndexColumns.CONTROLLER))).isEqualTo( + PREF_CONTROLLER); + assertThat(cursor.getInt(cursor.getColumnIndex(IndexColumns.PLATFORM_SLICE))).isEqualTo( + 1 /* true */); + assertThat(cursor.getInt(cursor.getColumnIndex(IndexColumns.SLICE_TYPE))).isEqualTo( + SLICE_TYPE); cursor.moveToNext(); } } @@ -126,15 +140,17 @@ public class SlicesIndexerTest { } private List getDummyIndexableData() { - final SliceData.Builder builder = new SliceData.Builder() - .setSummary(SUMMARY) - .setScreenTitle(SCREEN_TITLE) - .setFragmentName(FRAGMENT_NAME) - .setIcon(ICON) - .setUri(URI) - .setPreferenceControllerClassName(PREF_CONTROLLER); - final List sliceData = new ArrayList<>(); + final SliceData.Builder builder = new SliceData.Builder() + .setSummary(SUMMARY) + .setScreenTitle(SCREEN_TITLE) + .setFragmentName(FRAGMENT_NAME) + .setIcon(ICON) + .setUri(URI) + .setPreferenceControllerClassName(PREF_CONTROLLER) + .setPlatformDefined(PLATFORM_DEFINED) + .setSliceType(SLICE_TYPE); + for (int i = 0; i < KEYS.length; i++) { builder.setKey(KEYS[i]).setTitle(TITLES[i]); sliceData.add(builder.build());