Declare official platform slice

Create the notion of an official platform slice.
This includes:
- Adding a second authority to the provider
- tagging slices in xml with a platform slice flag
- Including authority in the getUri method

Bug:73359139
Test: robotests
Change-Id: I5382be138a262dbc5a8324c34aab131c5d0d5516
Merged-In: I581ee6dfcdf935f452a15e89e5d055e375ff1877
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dbe231b..f1bb595 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3218,7 +3218,7 @@
         </activity>
 
         <provider android:name=".slices.SettingsSliceProvider"
-                  android:authorities="com.android.settings.slices"
+                  android:authorities="com.android.settings.slices;android.settings.slices"
                   android:exported="true">
         </provider>
 
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index d37091c..d0ddab6 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -96,8 +96,12 @@
 
     <!-- For Search -->
     <declare-styleable name="Preference">
+        <!-- Synonyms for search results -->
         <attr name="keywords" format="string" />
+        <!-- Classname of a PreferenceController corresponding to the preference -->
         <attr name="controller" format="string" />
+        <!-- {@code true} when the controller declared represents a slice from {@link android.app.SettingsSliceContract} -->
+        <attr name="platform_slice" format="boolean" />
     </declare-styleable>
 
     <!-- For DotsPageIndicator -->
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 36eab22..dda5655 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -26,7 +26,8 @@
       android:icon="@drawable/ic_settings_bluetooth"
       android:summary="@string/bluetooth_pref_summary"
       android:order="-7"
-      settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"/>
+      settings:controller="com.android.settings.bluetooth.BluetoothSwitchPreferenceController"
+      settings:platform_slice="true"/>
 
     <SwitchPreference
         android:key="toggle_nfc"
diff --git a/src/com/android/settings/core/PreferenceXmlParserUtils.java b/src/com/android/settings/core/PreferenceXmlParserUtils.java
index 7afe8d8..8620dce 100644
--- a/src/com/android/settings/core/PreferenceXmlParserUtils.java
+++ b/src/com/android/settings/core/PreferenceXmlParserUtils.java
@@ -76,6 +76,7 @@
         int FLAG_NEED_PREF_TITLE = 1 << 4;
         int FLAG_NEED_PREF_SUMMARY = 1 << 5;
         int FLAG_NEED_PREF_ICON = 1 << 6;
+        int FLAG_NEED_PLATFORM_SLICE_FLAG = 1 << 7;
     }
 
     public static final String METADATA_PREF_TYPE = "type";
@@ -84,35 +85,48 @@
     public static final String METADATA_TITLE = "title";
     public static final String METADATA_SUMMARY = "summary";
     public static final String METADATA_ICON = "icon";
+    public static final String METADATA_PLATFORM_SLICE_FLAG = "platform_slice";
 
     private static final String ENTRIES_SEPARATOR = "|";
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_KEY} instead.
+     */
+    @Deprecated
     public static String getDataKey(Context context, AttributeSet attrs) {
-        return getData(context, attrs,
+        return getStringData(context, attrs,
                 com.android.internal.R.styleable.Preference,
                 com.android.internal.R.styleable.Preference_key);
     }
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_TITLE} instead.
+     */
+    @Deprecated
     public static String getDataTitle(Context context, AttributeSet attrs) {
-        return getData(context, attrs,
+        return getStringData(context, attrs,
                 com.android.internal.R.styleable.Preference,
                 com.android.internal.R.styleable.Preference_title);
     }
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_SUMMARY} instead.
+     */
+    @Deprecated
     public static String getDataSummary(Context context, AttributeSet attrs) {
-        return getData(context, attrs,
+        return getStringData(context, attrs,
                 com.android.internal.R.styleable.Preference,
                 com.android.internal.R.styleable.Preference_summary);
     }
 
     public static String getDataSummaryOn(Context context, AttributeSet attrs) {
-        return getData(context, attrs,
+        return getStringData(context, attrs,
                 com.android.internal.R.styleable.CheckBoxPreference,
                 com.android.internal.R.styleable.CheckBoxPreference_summaryOn);
     }
 
     public static String getDataSummaryOff(Context context, AttributeSet attrs) {
-        return getData(context, attrs,
+        return getStringData(context, attrs,
                 com.android.internal.R.styleable.CheckBoxPreference,
                 com.android.internal.R.styleable.CheckBoxPreference_summaryOff);
     }
@@ -124,13 +138,23 @@
     }
 
     public static String getDataKeywords(Context context, AttributeSet attrs) {
-        return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_keywords);
+        return getStringData(context, attrs, R.styleable.Preference,
+                R.styleable.Preference_keywords);
     }
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_CONTROLLER} instead.
+     */
+    @Deprecated
     public static String getController(Context context, AttributeSet attrs) {
-        return getData(context, attrs, R.styleable.Preference, R.styleable.Preference_controller);
+        return getStringData(context, attrs, R.styleable.Preference,
+                R.styleable.Preference_controller);
     }
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with {@link #METADATA_ICON} instead.
+     */
+    @Deprecated
     public static int getDataIcon(Context context, AttributeSet attrs) {
         final TypedArray ta = context.obtainStyledAttributes(attrs,
                 com.android.internal.R.styleable.Preference);
@@ -176,25 +200,35 @@
             }
             final Bundle preferenceMetadata = new Bundle();
             final AttributeSet attrs = Xml.asAttributeSet(parser);
+            final TypedArray preferenceAttributes = context.obtainStyledAttributes(attrs,
+                    R.styleable.Preference);
+
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TYPE)) {
                 preferenceMetadata.putString(METADATA_PREF_TYPE, nodeName);
             }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_KEY)) {
-                preferenceMetadata.putString(METADATA_KEY, getDataKey(context, attrs));
+                preferenceMetadata.putString(METADATA_KEY, getKey(preferenceAttributes));
             }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_CONTROLLER)) {
-                preferenceMetadata.putString(METADATA_CONTROLLER, getController(context, attrs));
+                preferenceMetadata.putString(METADATA_CONTROLLER,
+                        getController(preferenceAttributes));
             }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_TITLE)) {
-                preferenceMetadata.putString(METADATA_TITLE, getDataTitle(context, attrs));
+                preferenceMetadata.putString(METADATA_TITLE, getTitle(preferenceAttributes));
             }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_SUMMARY)) {
-                preferenceMetadata.putString(METADATA_SUMMARY, getDataSummary(context, attrs));
+                preferenceMetadata.putString(METADATA_SUMMARY, getSummary(preferenceAttributes));
             }
             if (hasFlag(flags, MetadataFlag.FLAG_NEED_PREF_ICON)) {
-                preferenceMetadata.putInt(METADATA_ICON, getDataIcon(context, attrs));
+                preferenceMetadata.putInt(METADATA_ICON, getIcon(preferenceAttributes));
+            }
+            if (hasFlag(flags, MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG)) {
+                preferenceMetadata.putBoolean(METADATA_PLATFORM_SLICE_FLAG,
+                        getPlatformSlice(preferenceAttributes));
             }
             metadata.add(preferenceMetadata);
+
+            preferenceAttributes.recycle();
         } while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth));
         parser.close();
@@ -205,12 +239,16 @@
      * Returns the fragment name if this preference launches a child fragment.
      */
     public static String getDataChildFragment(Context context, AttributeSet attrs) {
-        return getData(context, attrs, R.styleable.Preference,
+        return getStringData(context, attrs, R.styleable.Preference,
                 R.styleable.Preference_android_fragment);
     }
 
+    /**
+     * Call {@link #extractMetadata(Context, int, int)} with a {@link MetadataFlag} instead.
+     */
+    @Deprecated
     @Nullable
-    private static String getData(Context context, AttributeSet set, int[] attrs, int resId) {
+    private static String getStringData(Context context, AttributeSet set, int[] attrs, int resId) {
         final TypedArray ta = context.obtainStyledAttributes(set, attrs);
         String data = ta.getString(resId);
         ta.recycle();
@@ -243,4 +281,28 @@
         }
         return result.toString();
     }
+
+    private static String getKey(TypedArray styledAttributes) {
+        return styledAttributes.getString(com.android.internal.R.styleable.Preference_key);
+    }
+
+    private static String getTitle(TypedArray styledAttributes) {
+        return styledAttributes.getString(com.android.internal.R.styleable.Preference_title);
+    }
+
+    private static String getSummary(TypedArray styledAttributes) {
+        return styledAttributes.getString(com.android.internal.R.styleable.Preference_summary);
+    }
+
+    private static String getController(TypedArray styledAttributes) {
+        return styledAttributes.getString(R.styleable.Preference_controller);
+    }
+
+    private static int getIcon(TypedArray styledAttributes) {
+        return styledAttributes.getResourceId(com.android.internal.R.styleable.Icon_icon, 0);
+    }
+
+    private static boolean getPlatformSlice(TypedArray styledAttributes) {
+        return styledAttributes.getBoolean(R.styleable.Preference_platform_slice, false /* def */);
+    }
 }
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index d8ba991..68c9731 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -24,6 +24,7 @@
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
+import android.provider.SettingsSlicesContract;
 import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 
@@ -63,6 +64,10 @@
 
     private static final String TAG = "SettingsSliceProvider";
 
+    /**
+     * Authority for Settings slices not officially supported by the platform, but extensible for
+     * OEMs.
+     */
     public static final String SLICE_AUTHORITY = "com.android.settings.slices";
 
     public static final String PATH_WIFI = "wifi";
@@ -82,13 +87,6 @@
     @VisibleForTesting
     Map<Uri, SliceData> mSliceDataCache;
 
-    public static Uri getUri(String path) {
-        return new Uri.Builder()
-                .scheme(ContentResolver.SCHEME_CONTENT)
-                .authority(SLICE_AUTHORITY)
-                .appendPath(path).build();
-    }
-
     @Override
     public boolean onCreateSliceProvider() {
         mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(getContext());
@@ -176,7 +174,8 @@
                         .setSubtitle(state)
                         .addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
                                 null, finalWifiEnabled))
-                        .setPrimaryAction(new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
+                        .setPrimaryAction(
+                                new SliceAction(getIntent(Intent.ACTION_MAIN), null, null)))
                 .build();
     }
 
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index a68ed19..4124df7 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -59,7 +59,8 @@
                 // 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);
+                    Uri uri = SliceBuilderUtils.getUri(SettingsSliceProvider.PATH_WIFI,
+                            false /* isPlatformSlice */);
                     context.getContentResolver().notifyChange(uri, null);
                 }, 1000);
                 break;
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index e94ee56..e90ea8e 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -19,9 +19,12 @@
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
 
 import android.app.PendingIntent;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
+import android.net.Uri;
+import android.provider.SettingsSlicesContract;
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -98,6 +101,17 @@
                 sliceData.getKey());
     }
 
+    public static Uri getUri(String path, boolean isPlatformSlice) {
+        final String authority = isPlatformSlice
+                ? SettingsSlicesContract.AUTHORITY
+                : SettingsSliceProvider.SLICE_AUTHORITY;
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(authority)
+                .appendPath(path)
+                .build();
+    }
+
     private static BasePreferenceController getPreferenceController(Context context,
             String controllerClassName, String controllerKey) {
         try {
diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java
index a7c9a11..c02b113 100644
--- a/src/com/android/settings/slices/SliceData.java
+++ b/src/com/android/settings/slices/SliceData.java
@@ -70,6 +70,8 @@
     @SliceType
     private final int mSliceType;
 
+    private final boolean mIsPlatformDefined;
+
     public String getKey() {
         return mKey;
     }
@@ -106,6 +108,10 @@
         return mSliceType;
     }
 
+    public boolean isPlatformDefined() {
+        return mIsPlatformDefined;
+    }
+
     private SliceData(Builder builder) {
         mKey = builder.mKey;
         mTitle = builder.mTitle;
@@ -116,6 +122,7 @@
         mUri = builder.mUri;
         mPreferenceController = builder.mPrefControllerClassName;
         mSliceType = builder.mSliceType;
+        mIsPlatformDefined = builder.mIsPlatformDefined;
     }
 
     @Override
@@ -151,6 +158,8 @@
 
         private int mSliceType;
 
+        private boolean mIsPlatformDefined;
+
         public Builder setKey(String key) {
             mKey = key;
             return this;
@@ -196,6 +205,11 @@
             return this;
         }
 
+        public Builder setPlatformDefined(boolean isPlatformDefined) {
+            mIsPlatformDefined = isPlatformDefined;
+            return this;
+        }
+
         public SliceData build() {
             if (TextUtils.isEmpty(mKey)) {
                 throw new IllegalStateException("Key cannot be empty");
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index e7b53d0..7cf1994 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -19,6 +19,7 @@
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_CONTROLLER;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_ICON;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_KEY;
+import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFORM_SLICE_FLAG;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
 import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
 
@@ -164,7 +165,8 @@
                             | MetadataFlag.FLAG_NEED_PREF_TYPE
                             | MetadataFlag.FLAG_NEED_PREF_TITLE
                             | MetadataFlag.FLAG_NEED_PREF_ICON
-                            | MetadataFlag.FLAG_NEED_PREF_SUMMARY);
+                            | MetadataFlag.FLAG_NEED_PREF_SUMMARY
+                            | MetadataFlag.FLAG_NEED_PLATFORM_SLICE_FLAG);
 
             for (Bundle bundle : metadata) {
                 // TODO (b/67996923) Non-controller Slices should become intent-only slices.
@@ -179,6 +181,7 @@
                 final int iconResId = bundle.getInt(METADATA_ICON);
                 final int sliceType = SliceBuilderUtils.getSliceType(mContext, controllerClassName,
                         key);
+                final boolean isPlatformSlice = bundle.getBoolean(METADATA_PLATFORM_SLICE_FLAG);
 
                 final SliceData xmlSlice = new SliceData.Builder()
                         .setKey(key)
@@ -189,6 +192,7 @@
                         .setPreferenceControllerClassName(controllerClassName)
                         .setFragmentName(fragmentName)
                         .setSliceType(sliceType)
+                        .setPlatformDefined(isPlatformSlice)
                         .build();
 
                 xmlSliceData.add(xmlSlice);
diff --git a/tests/robotests/res/xml-mcc999/location_settings.xml b/tests/robotests/res/xml-mcc999/location_settings.xml
index 5619c77..08cd8ad 100644
--- a/tests/robotests/res/xml-mcc999/location_settings.xml
+++ b/tests/robotests/res/xml-mcc999/location_settings.xml
@@ -25,6 +25,7 @@
         android:title="title"
         android:icon="@drawable/ic_android"
         android:summary="summary"
-        settings:controller="com.android.settings.slices.FakePreferenceController"/>
+        settings:controller="com.android.settings.slices.FakePreferenceController"
+        settings:platform_slice="true"/>
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index 50f47ff..9edae7e 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -18,8 +18,7 @@
 package com.android.settings.slices;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -28,6 +27,7 @@
 import android.content.Context;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
+import android.provider.SettingsSlicesContract;
 
 import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.FakeToggleController;
@@ -50,6 +50,8 @@
 public class SettingsSliceProviderTest {
 
     private final String KEY = "KEY";
+    private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+    private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
     private final String TITLE = "title";
     private final String SUMMARY = "summary";
     private final String SCREEN_TITLE = "screen title";
@@ -67,6 +69,8 @@
         mProvider = spy(new SettingsSliceProvider());
         mProvider.mSliceDataCache = new HashMap<>();
         mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
+        when(mProvider.getContext()).thenReturn(mContext);
+
         mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
         SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
     }
@@ -78,12 +82,8 @@
 
     @Test
     public void testInitialSliceReturned_emptySlice() {
-        insertSpecialCase(KEY);
-        ContentResolver mockResolver = mock(ContentResolver.class);
-        doReturn(mockResolver).when(mContext).getContentResolver();
-        when(mProvider.getContext()).thenReturn(mContext);
-
-        Uri uri = SettingsSliceProvider.getUri(KEY);
+        insertSpecialCase(INTENT_PATH);
+        Uri uri = SliceBuilderUtils.getUri(INTENT_PATH, false);
         Slice slice = mProvider.onBindSlice(uri);
 
         assertThat(slice.getUri()).isEqualTo(uri);
@@ -91,21 +91,9 @@
     }
 
     @Test
-    public void testUriBuilder_returnsValidSliceUri() {
-        Uri uri = SettingsSliceProvider.getUri(KEY);
-
-        assertThat(uri.getScheme()).isEqualTo(ContentResolver.SCHEME_CONTENT);
-        assertThat(uri.getAuthority()).isEqualTo(SettingsSliceProvider.SLICE_AUTHORITY);
-        assertThat(uri.getLastPathSegment()).isEqualTo(KEY);
-    }
-
-    @Test
     public void testLoadSlice_returnsSliceFromAccessor() {
-        ContentResolver mockResolver = mock(ContentResolver.class);
-        doReturn(mockResolver).when(mContext).getContentResolver();
-        when(mProvider.getContext()).thenReturn(mContext);
         insertSpecialCase(KEY);
-        Uri uri = SettingsSliceProvider.getUri(KEY);
+        Uri uri = SliceBuilderUtils.getUri(KEY, false);
 
         mProvider.loadSlice(uri);
         SliceData data = mProvider.mSliceDataCache.get(uri);
@@ -116,7 +104,6 @@
 
     @Test
     public void testLoadSlice_cachedEntryRemovedOnBuild() {
-        when(mProvider.getContext()).thenReturn(mContext);
         SliceData data = getDummyData();
         mProvider.mSliceDataCache.put(data.getUri(), data);
         mProvider.onBindSlice(data.getUri());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 5a2271a..0fcce5f 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -20,8 +20,10 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.net.Uri;
+import android.provider.SettingsSlicesContract;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
@@ -48,6 +50,9 @@
     private final Class PREF_CONTROLLER = FakeToggleController.class;
     private final Class PREF_CONTROLLER2 = FakeContextOnlyPreferenceController.class;
 
+    private final String INTENT_PATH = SettingsSlicesContract.PATH_SETTING_INTENT + "/" + KEY;
+    private final String ACTION_PATH = SettingsSlicesContract.PATH_SETTING_ACTION + "/" + KEY;
+
     private Context mContext;
 
     @Before
@@ -63,6 +68,58 @@
     }
 
     @Test
+    public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
+        Uri expectedUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+                .appendPath(INTENT_PATH)
+                .build();
+
+        Uri actualUri = SliceBuilderUtils.getUri(INTENT_PATH, false);
+
+        assertThat(actualUri).isEqualTo(expectedUri);
+    }
+
+    @Test
+    public void testUriBuilder_oemAuthority_actionPath_returnsValidSliceUri() {
+        Uri expectedUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+                .appendPath(ACTION_PATH)
+                .build();
+
+        Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, false);
+
+        assertThat(actualUri).isEqualTo(expectedUri);
+    }
+
+    @Test
+    public void testUriBuilder_platformAuthority_intentPath_returnsValidSliceUri() {
+        Uri expectedUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsSlicesContract.AUTHORITY)
+                .appendPath(ACTION_PATH)
+                .build();
+
+        Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+        assertThat(actualUri).isEqualTo(expectedUri);
+    }
+
+    @Test
+    public void testUriBuilder_platformAuthority_actionPath_returnsValidSliceUri() {
+        Uri expectedUri = new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(SettingsSlicesContract.AUTHORITY)
+                .appendPath(ACTION_PATH)
+                .build();
+
+        Uri actualUri = SliceBuilderUtils.getUri(ACTION_PATH, true);
+
+        assertThat(actualUri).isEqualTo(expectedUri);
+    }
+
+    @Test
     public void testGetPreferenceController_buildsMatchingController() {
         BasePreferenceController controller =
             SliceBuilderUtils.getPreferenceController(mContext, getDummyData());
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index 4d6c08d..36c2754 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -81,6 +81,7 @@
         assertThat(fakeSlice.getUri()).isNull();
         assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
         assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
-        assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
+        assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); // from XML
+        assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
     }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
index 7cd19b5..c2ab0af 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataTest.java
@@ -37,6 +37,7 @@
     private final Uri URI = Uri.parse("content://com.android.settings.slices/test");
     private final String PREF_CONTROLLER = "com.android.settings.slices.tester";
     private final int SLICE_TYPE = SliceData.SliceType.SWITCH;
+    private final boolean IS_PLATFORM_DEFINED = true;
 
     @Test
     public void testBuilder_buildsMatchingObject() {
@@ -49,7 +50,8 @@
                 .setFragmentName(FRAGMENT_NAME)
                 .setUri(URI)
                 .setPreferenceControllerClassName(PREF_CONTROLLER)
-                .setSliceType(SLICE_TYPE);
+                .setSliceType(SLICE_TYPE)
+                .setPlatformDefined(IS_PLATFORM_DEFINED);
 
         SliceData data = builder.build();
 
@@ -62,6 +64,7 @@
         assertThat(data.getUri()).isEqualTo(URI);
         assertThat(data.getPreferenceController()).isEqualTo(PREF_CONTROLLER);
         assertThat(data.getSliceType()).isEqualTo(SLICE_TYPE);
+        assertThat(data.isPlatformDefined()).isEqualTo(IS_PLATFORM_DEFINED);
     }
 
     @Test(expected = IllegalStateException.class)
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index 8989de9..331058c 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -90,7 +90,7 @@
     public void testGetSliceFromUri_validUri_validSliceReturned() {
         String key = "key";
         insertSpecialCase(key);
-        Uri uri = SettingsSliceProvider.getUri(key);
+        Uri uri = SliceBuilderUtils.getUri(key, false);
 
         SliceData data = mAccessor.getSliceDataFromUri(uri);
 
@@ -106,7 +106,7 @@
 
     @Test(expected = IllegalStateException.class)
     public void testGetSliceFromUri_invalidUri_errorThrown() {
-        Uri uri = SettingsSliceProvider.getUri("durr");
+        Uri uri = SliceBuilderUtils.getUri("durr", false);
 
         mAccessor.getSliceDataFromUri(uri);
     }