Unhide slice data APIs

Test: CTS
Change-Id: Ie2a05e30e5ac6c830b6a9a14b2d207b7e2fbe9da
diff --git a/core/java/android/slice/Slice.java b/core/java/android/app/slice/Slice.java
similarity index 65%
rename from core/java/android/slice/Slice.java
rename to core/java/android/app/slice/Slice.java
index 5768654..7f9f74b 100644
--- a/core/java/android/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -14,38 +14,35 @@
  * limitations under the License.
  */
 
-package android.slice;
-
-import static android.slice.SliceItem.TYPE_ACTION;
-import static android.slice.SliceItem.TYPE_COLOR;
-import static android.slice.SliceItem.TYPE_IMAGE;
-import static android.slice.SliceItem.TYPE_REMOTE_INPUT;
-import static android.slice.SliceItem.TYPE_REMOTE_VIEW;
-import static android.slice.SliceItem.TYPE_SLICE;
-import static android.slice.SliceItem.TYPE_TEXT;
-import static android.slice.SliceItem.TYPE_TIMESTAMP;
+package android.app.slice;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
+import android.content.ContentResolver;
+import android.content.IContentProvider;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
 import android.widget.RemoteViews;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 /**
  * A slice is a piece of app content and actions that can be surfaced outside of the app.
  *
  * <p>They are constructed using {@link Builder} in a tree structure
  * that provides the OS some information about how the content should be displayed.
- * @hide
  */
 public final class Slice implements Parcelable {
 
@@ -53,7 +50,7 @@
      * @hide
      */
     @StringDef({HINT_TITLE, HINT_LIST, HINT_LIST_ITEM, HINT_LARGE, HINT_ACTIONS, HINT_SELECTED,
-            HINT_SOURCE, HINT_MESSAGE, HINT_HORIZONTAL, HINT_NO_TINT})
+            HINT_SOURCE, HINT_MESSAGE, HINT_HORIZONTAL, HINT_NO_TINT, HINT_PARTIAL})
     public @interface SliceHint{ }
 
     /**
@@ -102,6 +99,12 @@
      * Hint to indicate that this content should not be tinted.
      */
     public static final String HINT_NO_TINT     = "no_tint";
+    /**
+     * Hint to indicate that this slice is incomplete and an update will be sent once
+     * loading is complete. Slices which contain HINT_PARTIAL will not be cached by the
+     * OS and should not be cached by apps.
+     */
+    public static final String HINT_PARTIAL     = "partial";
 
     // These two are coming over from prototyping, but we probably don't want in
     // public API, at least not right now.
@@ -109,19 +112,12 @@
      * @hide
      */
     public static final String HINT_ALT         = "alt";
-    /**
-     * @hide
-     */
-    public static final String HINT_PARTIAL     = "partial";
 
     private final SliceItem[] mItems;
     private final @SliceHint String[] mHints;
     private Uri mUri;
 
-    /**
-     * @hide
-     */
-    public Slice(ArrayList<SliceItem> items, @SliceHint String[] hints, Uri uri) {
+    Slice(ArrayList<SliceItem> items, @SliceHint String[] hints, Uri uri) {
         mHints = hints;
         mItems = items.toArray(new SliceItem[items.size()]);
         mUri = uri;
@@ -147,15 +143,15 @@
     /**
      * @return All child {@link SliceItem}s that this Slice contains.
      */
-    public SliceItem[] getItems() {
-        return mItems;
+    public List<SliceItem> getItems() {
+        return Arrays.asList(mItems);
     }
 
     /**
      * @return All hints associated with this Slice.
      */
-    public @SliceHint String[] getHints() {
-        return mHints;
+    public @SliceHint List<String> getHints() {
+        return Arrays.asList(mHints);
     }
 
     /**
@@ -163,14 +159,14 @@
      */
     public SliceItem getPrimaryIcon() {
         for (SliceItem item : getItems()) {
-            if (item.getType() == TYPE_IMAGE) {
+            if (item.getType() == SliceItem.TYPE_IMAGE) {
                 return item;
             }
-            if (!(item.getType() == TYPE_SLICE && item.hasHint(Slice.HINT_LIST))
+            if (!(item.getType() == SliceItem.TYPE_SLICE && item.hasHint(Slice.HINT_LIST))
                     && !item.hasHint(Slice.HINT_ACTIONS)
                     && !item.hasHint(Slice.HINT_LIST_ITEM)
-                    && (item.getType() != TYPE_ACTION)) {
-                SliceItem icon = SliceQuery.find(item, TYPE_IMAGE);
+                    && (item.getType() != SliceItem.TYPE_ACTION)) {
+                SliceItem icon = SliceQuery.find(item, SliceItem.TYPE_IMAGE);
                 if (icon != null) return icon;
             }
         }
@@ -235,10 +231,18 @@
         }
 
         /**
+         * Add hints to the Slice being constructed
+         */
+        public Builder addHints(@SliceHint List<String> hints) {
+            return addHints(hints.toArray(new String[hints.size()]));
+        }
+
+        /**
          * Add a sub-slice to the slice being constructed
          */
         public Builder addSubSlice(@NonNull Slice slice) {
-            mItems.add(new SliceItem(slice, TYPE_SLICE, slice.getHints()));
+            mItems.add(new SliceItem(slice, SliceItem.TYPE_SLICE, slice.getHints().toArray(
+                    new String[slice.getHints().size()])));
             return this;
         }
 
@@ -246,7 +250,7 @@
          * Add an action to the slice being constructed
          */
         public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s) {
-            mItems.add(new SliceItem(action, s, TYPE_ACTION, new String[0]));
+            mItems.add(new SliceItem(action, s, SliceItem.TYPE_ACTION, new String[0]));
             return this;
         }
 
@@ -254,31 +258,53 @@
          * Add text to the slice being constructed
          */
         public Builder addText(CharSequence text, @SliceHint String... hints) {
-            mItems.add(new SliceItem(text, TYPE_TEXT, hints));
+            mItems.add(new SliceItem(text, SliceItem.TYPE_TEXT, hints));
             return this;
         }
 
         /**
+         * Add text to the slice being constructed
+         */
+        public Builder addText(CharSequence text, @SliceHint List<String> hints) {
+            return addText(text, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
          * Add an image to the slice being constructed
          */
         public Builder addIcon(Icon icon, @SliceHint String... hints) {
-            mItems.add(new SliceItem(icon, TYPE_IMAGE, hints));
+            mItems.add(new SliceItem(icon, SliceItem.TYPE_IMAGE, hints));
             return this;
         }
 
         /**
+         * Add an image to the slice being constructed
+         */
+        public Builder addIcon(Icon icon, @SliceHint List<String> hints) {
+            return addIcon(icon, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
          * @hide This isn't final
          */
         public Builder addRemoteView(RemoteViews remoteView, @SliceHint String... hints) {
-            mItems.add(new SliceItem(remoteView, TYPE_REMOTE_VIEW, hints));
+            mItems.add(new SliceItem(remoteView, SliceItem.TYPE_REMOTE_VIEW, hints));
             return this;
         }
 
         /**
          * Add remote input to the slice being constructed
          */
+        public Slice.Builder addRemoteInput(RemoteInput remoteInput,
+                @SliceHint List<String> hints) {
+            return addRemoteInput(remoteInput, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
+         * Add remote input to the slice being constructed
+         */
         public Slice.Builder addRemoteInput(RemoteInput remoteInput, @SliceHint String... hints) {
-            mItems.add(new SliceItem(remoteInput, TYPE_REMOTE_INPUT, hints));
+            mItems.add(new SliceItem(remoteInput, SliceItem.TYPE_REMOTE_INPUT, hints));
             return this;
         }
 
@@ -286,19 +312,33 @@
          * Add a color to the slice being constructed
          */
         public Builder addColor(int color, @SliceHint String... hints) {
-            mItems.add(new SliceItem(color, TYPE_COLOR, hints));
+            mItems.add(new SliceItem(color, SliceItem.TYPE_COLOR, hints));
             return this;
         }
 
         /**
+         * Add a color to the slice being constructed
+         */
+        public Builder addColor(int color, @SliceHint List<String> hints) {
+            return addColor(color, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
          * Add a timestamp to the slice being constructed
          */
         public Slice.Builder addTimestamp(long time, @SliceHint String... hints) {
-            mItems.add(new SliceItem(time, TYPE_TIMESTAMP, hints));
+            mItems.add(new SliceItem(time, SliceItem.TYPE_TIMESTAMP, hints));
             return this;
         }
 
         /**
+         * Add a timestamp to the slice being constructed
+         */
+        public Slice.Builder addTimestamp(long time, @SliceHint List<String> hints) {
+            return addTimestamp(time, hints.toArray(new String[hints.size()]));
+        }
+
+        /**
          * Construct the slice.
          */
         public Slice build() {
@@ -322,18 +362,18 @@
      * @hide
      * @return A string representation of this slice.
      */
-    public String getString() {
-        return getString("");
+    public String toString() {
+        return toString("");
     }
 
-    private String getString(String indent) {
+    private String toString(String indent) {
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < mItems.length; i++) {
             sb.append(indent);
-            if (mItems[i].getType() == TYPE_SLICE) {
+            if (mItems[i].getType() == SliceItem.TYPE_SLICE) {
                 sb.append("slice:\n");
-                sb.append(mItems[i].getSlice().getString(indent + "   "));
-            } else if (mItems[i].getType() == TYPE_TEXT) {
+                sb.append(mItems[i].getSlice().toString(indent + "   "));
+            } else if (mItems[i].getType() == SliceItem.TYPE_TEXT) {
                 sb.append("text: ");
                 sb.append(mItems[i].getText());
                 sb.append("\n");
@@ -344,4 +384,34 @@
         }
         return sb.toString();
     }
+
+    /**
+     * Turns a slice Uri into slice content.
+     *
+     * @param resolver ContentResolver to be used.
+     * @param uri The URI to a slice provider
+     * @return The Slice provided by the app or null if none is given.
+     * @see Slice
+     */
+    public static @Nullable Slice bindSlice(ContentResolver resolver, @NonNull Uri uri) {
+        Preconditions.checkNotNull(uri, "uri");
+        IContentProvider provider = resolver.acquireProvider(uri);
+        if (provider == null) {
+            throw new IllegalArgumentException("Unknown URI " + uri);
+        }
+        try {
+            Bundle extras = new Bundle();
+            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
+            final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE,
+                    null, extras);
+            Bundle.setDefusable(res, true);
+            return res.getParcelable(SliceProvider.EXTRA_SLICE);
+        } catch (RemoteException e) {
+            // Arbitrary and not worth documenting, as Activity
+            // Manager will kill this process shortly anyway.
+            return null;
+        } finally {
+            resolver.releaseProvider(provider);
+        }
+    }
 }
diff --git a/core/java/android/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
similarity index 93%
rename from core/java/android/slice/SliceItem.java
rename to core/java/android/app/slice/SliceItem.java
index 2827ab9..6e69b05 100644
--- a/core/java/android/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.slice;
+package android.app.slice;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -23,13 +23,15 @@
 import android.graphics.drawable.Icon;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.slice.Slice.SliceHint;
 import android.text.TextUtils;
 import android.util.Pair;
 import android.widget.RemoteViews;
 
 import com.android.internal.util.ArrayUtils;
 
+import java.util.Arrays;
+import java.util.List;
+
 
 /**
  * A SliceItem is a single unit in the tree structure of a {@link Slice}.
@@ -47,7 +49,6 @@
  * The hints that a {@link SliceItem} are a set of strings which annotate
  * the content. The hints that are guaranteed to be understood by the system
  * are defined on {@link Slice}.
- * @hide
  */
 public final class SliceItem implements Parcelable {
 
@@ -97,14 +98,15 @@
     /**
      * @hide
      */
-    protected @SliceHint String[] mHints;
+    protected @Slice.SliceHint
+    String[] mHints;
     private final int mType;
     private final Object mObj;
 
     /**
      * @hide
      */
-    public SliceItem(Object obj, @SliceType int type, @SliceHint String[] hints) {
+    public SliceItem(Object obj, @SliceType int type, @Slice.SliceHint String[] hints) {
         mHints = hints;
         mType = type;
         mObj = obj;
@@ -113,7 +115,7 @@
     /**
      * @hide
      */
-    public SliceItem(PendingIntent intent, Slice slice, int type, @SliceHint String[] hints) {
+    public SliceItem(PendingIntent intent, Slice slice, int type, @Slice.SliceHint String[] hints) {
         this(new Pair<>(intent, slice), type, hints);
     }
 
@@ -121,14 +123,14 @@
      * Gets all hints associated with this SliceItem.
      * @return Array of hints.
      */
-    public @NonNull @SliceHint String[] getHints() {
-        return mHints;
+    public @NonNull @Slice.SliceHint List<String> getHints() {
+        return Arrays.asList(mHints);
     }
 
     /**
      * @hide
      */
-    public void addHint(@SliceHint String hint) {
+    public void addHint(@Slice.SliceHint String hint) {
         mHints = ArrayUtils.appendElement(String.class, mHints, hint);
     }
 
@@ -206,7 +208,7 @@
      * @param hint The hint to check for
      * @return true if this item contains the given hint
      */
-    public boolean hasHint(@SliceHint String hint) {
+    public boolean hasHint(@Slice.SliceHint String hint) {
         return ArrayUtils.contains(mHints, hint);
     }
 
@@ -234,7 +236,7 @@
     /**
      * @hide
      */
-    public boolean hasHints(@SliceHint String[] hints) {
+    public boolean hasHints(@Slice.SliceHint String[] hints) {
         if (hints == null) return true;
         for (String hint : hints) {
             if (!TextUtils.isEmpty(hint) && !ArrayUtils.contains(mHints, hint)) {
@@ -247,7 +249,7 @@
     /**
      * @hide
      */
-    public boolean hasAnyHints(@SliceHint String[] hints) {
+    public boolean hasAnyHints(@Slice.SliceHint String[] hints) {
         if (hints == null) return false;
         for (String hint : hints) {
             if (ArrayUtils.contains(mHints, hint)) {
diff --git a/core/java/android/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
similarity index 76%
rename from core/java/android/slice/SliceProvider.java
rename to core/java/android/app/slice/SliceProvider.java
index 4e21371..df87b45 100644
--- a/core/java/android/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.slice;
+package android.app.slice;
 
 import android.Manifest.permission;
 import android.content.ContentProvider;
@@ -26,6 +26,8 @@
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.StrictMode;
+import android.os.StrictMode.ThreadPolicy;
 import android.util.Log;
 
 import java.util.concurrent.CountDownLatch;
@@ -51,10 +53,15 @@
  * </pre>
  *
  * @see Slice
- * @hide
  */
 public abstract class SliceProvider extends ContentProvider {
 
+    /**
+     * This is the Android platform's MIME type for a slice: URI
+     * containing a slice implemented through {@link SliceProvider}.
+     */
+    public static final String SLICE_TYPE = "vnd.android.slice";
+
     private static final String TAG = "SliceProvider";
     /**
      * @hide
@@ -73,8 +80,18 @@
 
     /**
      * Implemented to create a slice. Will be called on the main thread.
+     * <p>
+     * onBindSlice should return as quickly as possible so that the UI tied
+     * to this slice can be responsive. No network or other IO will be allowed
+     * during onBindSlice. Any loading that needs to be done should happen
+     * off the main thread with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
+     * when the app is ready to provide the complete data in onBindSlice.
+     * <p>
+     *
      * @see {@link Slice}.
+     * @see {@link Slice#HINT_PARTIAL}
      */
+    // TODO: Provide alternate notifyChange that takes in the slice (i.e. notifyChange(Uri, Slice)).
     public abstract Slice onBindSlice(Uri sliceUri);
 
     @Override
@@ -120,11 +137,11 @@
     @Override
     public final String getType(Uri uri) {
         if (DEBUG) Log.d(TAG, "getType " + uri);
-        return null;
+        return SLICE_TYPE;
     }
 
     @Override
-    public final Bundle call(String method, String arg, Bundle extras) {
+    public Bundle call(String method, String arg, Bundle extras) {
         if (method.equals(METHOD_SLICE)) {
             getContext().enforceCallingPermission(permission.BIND_SLICE,
                     "Slice binding requires the permission BIND_SLICE");
@@ -143,8 +160,17 @@
         CountDownLatch latch = new CountDownLatch(1);
         Handler mainHandler = new Handler(Looper.getMainLooper());
         mainHandler.post(() -> {
-            output[0] = onBindSlice(sliceUri);
-            latch.countDown();
+            ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
+            try {
+                StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
+                        .detectAll()
+                        .penaltyDeath()
+                        .build());
+                output[0] = onBindSlice(sliceUri);
+            } finally {
+                StrictMode.setThreadPolicy(oldPolicy);
+                latch.countDown();
+            }
         });
         try {
             latch.await();
diff --git a/core/java/android/slice/SliceQuery.java b/core/java/android/app/slice/SliceQuery.java
similarity index 90%
rename from core/java/android/slice/SliceQuery.java
rename to core/java/android/app/slice/SliceQuery.java
index d99b26a..d1fe2c9 100644
--- a/core/java/android/slice/SliceQuery.java
+++ b/core/java/android/app/slice/SliceQuery.java
@@ -14,12 +14,8 @@
  * limitations under the License.
  */
 
-package android.slice;
+package android.app.slice;
 
-import static android.slice.SliceItem.TYPE_ACTION;
-import static android.slice.SliceItem.TYPE_SLICE;
-
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -114,7 +110,9 @@
      * @hide
      */
     public static SliceItem find(Slice s, int type, String[] hints, String[] nonHints) {
-        return find(new SliceItem(s, TYPE_SLICE, s.getHints()), type, hints, nonHints);
+        List<String> h = s.getHints();
+        return find(new SliceItem(s, SliceItem.TYPE_SLICE, h.toArray(new String[h.size()])), type,
+                hints, nonHints);
     }
 
     /**
@@ -140,8 +138,9 @@
             @Override
             public SliceItem next() {
                 SliceItem item = items.poll();
-                if (item.getType() == TYPE_SLICE || item.getType() == TYPE_ACTION) {
-                    items.addAll(Arrays.asList(item.getSlice().getItems()));
+                if (item.getType() == SliceItem.TYPE_SLICE
+                        || item.getType() == SliceItem.TYPE_ACTION) {
+                    items.addAll(item.getSlice().getItems());
                 }
                 return item;
             }
diff --git a/core/java/android/slice/views/ActionRow.java b/core/java/android/app/slice/views/ActionRow.java
similarity index 97%
rename from core/java/android/slice/views/ActionRow.java
rename to core/java/android/app/slice/views/ActionRow.java
index 93e9c03..c7d99f7 100644
--- a/core/java/android/slice/views/ActionRow.java
+++ b/core/java/android/app/slice/views/ActionRow.java
@@ -14,19 +14,19 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
 import android.app.RemoteInput;
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
 import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewParent;
diff --git a/core/java/android/slice/views/GridView.java b/core/java/android/app/slice/views/GridView.java
similarity index 94%
rename from core/java/android/slice/views/GridView.java
rename to core/java/android/app/slice/views/GridView.java
index 18a90f7..6f30c50 100644
--- a/core/java/android/slice/views/GridView.java
+++ b/core/java/android/app/slice/views/GridView.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.views.LargeSliceAdapter.SliceListView;
 import android.content.Context;
 import android.graphics.Color;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.views.LargeSliceAdapter.SliceListView;
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.Gravity;
@@ -38,7 +38,7 @@
 import com.android.internal.R;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.List;
 
 /**
  * @hide
@@ -76,10 +76,10 @@
         removeAllViews();
         int total = 1;
         if (slice.getType() == SliceItem.TYPE_SLICE) {
-            SliceItem[] items = slice.getSlice().getItems();
-            total = items.length;
+            List<SliceItem> items = slice.getSlice().getItems();
+            total = items.size();
             for (int i = 0; i < total; i++) {
-                SliceItem item = items[i];
+                SliceItem item = items.get(i);
                 if (isFull()) {
                     continue;
                 }
@@ -142,7 +142,7 @@
             // TODO: Unify sporadic inflates that happen throughout the code.
             ArrayList<SliceItem> items = new ArrayList<>();
             if (item.getType() == SliceItem.TYPE_SLICE) {
-                items.addAll(Arrays.asList(item.getSlice().getItems()));
+                items.addAll(item.getSlice().getItems());
             }
             items.forEach(i -> {
                 Context context = getContext();
diff --git a/core/java/android/slice/views/LargeSliceAdapter.java b/core/java/android/app/slice/views/LargeSliceAdapter.java
similarity index 97%
rename from core/java/android/slice/views/LargeSliceAdapter.java
rename to core/java/android/app/slice/views/LargeSliceAdapter.java
index e77a1b2..6794ff9 100644
--- a/core/java/android/slice/views/LargeSliceAdapter.java
+++ b/core/java/android/app/slice/views/LargeSliceAdapter.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
+import android.app.slice.views.LargeSliceAdapter.SliceViewHolder;
 import android.content.Context;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
-import android.slice.views.LargeSliceAdapter.SliceViewHolder;
 import android.util.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
diff --git a/core/java/android/slice/views/LargeTemplateView.java b/core/java/android/app/slice/views/LargeTemplateView.java
similarity index 92%
rename from core/java/android/slice/views/LargeTemplateView.java
rename to core/java/android/app/slice/views/LargeTemplateView.java
index d53e8fc..9e22516 100644
--- a/core/java/android/slice/views/LargeTemplateView.java
+++ b/core/java/android/app/slice/views/LargeTemplateView.java
@@ -14,22 +14,21 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
+import android.app.slice.views.SliceView.SliceModeView;
 import android.content.Context;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
-import android.slice.views.SliceView.SliceModeView;
 import android.util.TypedValue;
 
 import com.android.internal.widget.LinearLayoutManager;
 import com.android.internal.widget.RecyclerView;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -86,7 +85,7 @@
         if (slice.hasHint(Slice.HINT_LIST)) {
             addList(slice, items);
         } else {
-            Arrays.asList(slice.getItems()).forEach(item -> {
+            slice.getItems().forEach(item -> {
                 if (item.hasHint(Slice.HINT_ACTIONS)) {
                     return;
                 } else if (item.getType() == SliceItem.TYPE_COLOR) {
@@ -109,7 +108,7 @@
     }
 
     private void addList(Slice slice, List<SliceItem> items) {
-        List<SliceItem> sliceItems = Arrays.asList(slice.getItems());
+        List<SliceItem> sliceItems = slice.getItems();
         sliceItems.forEach(i -> i.addHint(Slice.HINT_LIST_ITEM));
         items.addAll(sliceItems);
     }
diff --git a/core/java/android/slice/views/MessageView.java b/core/java/android/app/slice/views/MessageView.java
similarity index 92%
rename from core/java/android/slice/views/MessageView.java
rename to core/java/android/app/slice/views/MessageView.java
index 7b03e0b..77252bf 100644
--- a/core/java/android/slice/views/MessageView.java
+++ b/core/java/android/app/slice/views/MessageView.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
+import android.app.slice.views.LargeSliceAdapter.SliceListView;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
-import android.slice.views.LargeSliceAdapter.SliceListView;
 import android.text.SpannableStringBuilder;
 import android.util.AttributeSet;
 import android.util.TypedValue;
diff --git a/core/java/android/slice/views/RemoteInputView.java b/core/java/android/app/slice/views/RemoteInputView.java
similarity index 99%
rename from core/java/android/slice/views/RemoteInputView.java
rename to core/java/android/app/slice/views/RemoteInputView.java
index a29bb5c..e53cb1e 100644
--- a/core/java/android/slice/views/RemoteInputView.java
+++ b/core/java/android/app/slice/views/RemoteInputView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.animation.Animator;
 import android.app.Notification;
diff --git a/core/java/android/slice/views/ShortcutView.java b/core/java/android/app/slice/views/ShortcutView.java
similarity index 94%
rename from core/java/android/slice/views/ShortcutView.java
rename to core/java/android/app/slice/views/ShortcutView.java
index 8fe2f1a..b6790c7 100644
--- a/core/java/android/slice/views/ShortcutView.java
+++ b/core/java/android/app/slice/views/ShortcutView.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.app.PendingIntent;
 import android.app.PendingIntent.CanceledException;
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
+import android.app.slice.views.SliceView.SliceModeView;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.OvalShape;
 import android.net.Uri;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
-import android.slice.views.SliceView.SliceModeView;
 import android.view.ViewGroup;
 
 import com.android.internal.R;
diff --git a/core/java/android/slice/views/SliceView.java b/core/java/android/app/slice/views/SliceView.java
similarity index 93%
rename from core/java/android/slice/views/SliceView.java
rename to core/java/android/app/slice/views/SliceView.java
index f379248..32484fc 100644
--- a/core/java/android/slice/views/SliceView.java
+++ b/core/java/android/app/slice/views/SliceView.java
@@ -14,23 +14,25 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.annotation.StringDef;
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
+import java.util.List;
+
 /**
  * A view that can display a {@link Slice} in different {@link SliceMode}'s.
  *
@@ -120,7 +122,7 @@
      */
     public void bindSlice(Uri sliceUri) {
         validate(sliceUri);
-        Slice s = mContext.getContentResolver().bindSlice(sliceUri);
+        Slice s = Slice.bindSlice(mContext.getContentResolver(), sliceUri);
         bindSlice(s);
     }
 
@@ -201,7 +203,7 @@
         }
         // TODO: Smarter mapping here from one state to the next.
         SliceItem color = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_COLOR);
-        SliceItem[] items = mCurrentSlice.getItems();
+        List<SliceItem> items = mCurrentSlice.getItems();
         SliceItem actionRow = SliceQuery.find(mCurrentSlice, SliceItem.TYPE_SLICE,
                 Slice.HINT_ACTIONS,
                 Slice.HINT_ALT);
@@ -212,7 +214,7 @@
             addView(mCurrentView);
             addView(mActions);
         }
-        if (items.length > 1 || (items.length != 0 && items[0] != actionRow)) {
+        if (items.size() > 1 || (items.size() != 0 && items.get(0) != actionRow)) {
             mCurrentView.setVisibility(View.VISIBLE);
             mCurrentView.setSlice(mCurrentSlice);
         } else {
@@ -239,7 +241,7 @@
     }
 
     private static void validate(Uri sliceUri) {
-        if (!ContentResolver.SCHEME_SLICE.equals(sliceUri.getScheme())) {
+        if (!ContentResolver.SCHEME_CONTENT.equals(sliceUri.getScheme())) {
             throw new RuntimeException("Invalid uri " + sliceUri);
         }
         if (sliceUri.getPathSegments().size() == 0) {
diff --git a/core/java/android/slice/views/SliceViewUtil.java b/core/java/android/app/slice/views/SliceViewUtil.java
similarity index 99%
rename from core/java/android/slice/views/SliceViewUtil.java
rename to core/java/android/app/slice/views/SliceViewUtil.java
index 1b5a6d1..19e8e7c 100644
--- a/core/java/android/slice/views/SliceViewUtil.java
+++ b/core/java/android/app/slice/views/SliceViewUtil.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.annotation.ColorInt;
 import android.content.Context;
diff --git a/core/java/android/slice/views/SmallTemplateView.java b/core/java/android/app/slice/views/SmallTemplateView.java
similarity index 91%
rename from core/java/android/slice/views/SmallTemplateView.java
rename to core/java/android/app/slice/views/SmallTemplateView.java
index b0b181e..42b2d21 100644
--- a/core/java/android/slice/views/SmallTemplateView.java
+++ b/core/java/android/app/slice/views/SmallTemplateView.java
@@ -14,16 +14,16 @@
  * limitations under the License.
  */
 
-package android.slice.views;
+package android.app.slice.views;
 
 import android.app.PendingIntent.CanceledException;
+import android.app.slice.Slice;
+import android.app.slice.SliceItem;
+import android.app.slice.SliceQuery;
+import android.app.slice.views.LargeSliceAdapter.SliceListView;
+import android.app.slice.views.SliceView.SliceModeView;
 import android.content.Context;
 import android.os.AsyncTask;
-import android.slice.Slice;
-import android.slice.SliceItem;
-import android.slice.SliceQuery;
-import android.slice.views.LargeSliceAdapter.SliceListView;
-import android.slice.views.SliceView.SliceModeView;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -34,7 +34,6 @@
 import java.text.Format;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 
@@ -117,7 +116,7 @@
         int itemCount = 0;
         boolean hasSummary = false;
         ArrayList<SliceItem> sliceItems = new ArrayList<SliceItem>(
-                Arrays.asList(slice.getSlice().getItems()));
+                slice.getSlice().getItems());
         for (int i = 0; i < sliceItems.size(); i++) {
             SliceItem item = sliceItems.get(i);
             if (!hasSummary && item.getType() == SliceItem.TYPE_TEXT
@@ -140,9 +139,9 @@
                     mEndContainer.addView(tv);
                     itemCount++;
                 } else if (item.getType() == SliceItem.TYPE_SLICE) {
-                    SliceItem[] subItems = item.getSlice().getItems();
-                    for (int j = 0; j < subItems.length; j++) {
-                        sliceItems.add(subItems[j]);
+                    List<SliceItem> subItems = item.getSlice().getItems();
+                    for (int j = 0; j < subItems.size(); j++) {
+                        sliceItems.add(subItems.get(j));
                     }
                 }
             }
@@ -151,7 +150,8 @@
 
     @Override
     public void setSlice(Slice slice) {
-        setSliceItem(new SliceItem(slice, SliceItem.TYPE_SLICE, slice.getHints()));
+        setSliceItem(new SliceItem(slice, SliceItem.TYPE_SLICE,
+                slice.getHints().toArray(new String[slice.getHints().size()])));
     }
 
     /**
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 5b2bf45..cdeaea3 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -2099,8 +2099,7 @@
     public static Uri maybeAddUserId(Uri uri, int userId) {
         if (uri == null) return null;
         if (userId != UserHandle.USER_CURRENT
-                && (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())
-                        || ContentResolver.SCHEME_SLICE.equals(uri.getScheme()))) {
+                && ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
             if (!uriHasUserId(uri)) {
                 //We don't add the user Id if there's already one
                 Uri.Builder builder = uri.buildUpon();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 02e70f5..9ccc552 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -47,8 +47,6 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.slice.Slice;
-import android.slice.SliceProvider;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
@@ -180,8 +178,6 @@
     public static final Intent ACTION_SYNC_CONN_STATUS_CHANGED =
             new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
 
-    /** @hide */
-    public static final String SCHEME_SLICE = "slice";
     public static final String SCHEME_CONTENT = "content";
     public static final String SCHEME_ANDROID_RESOURCE = "android.resource";
     public static final String SCHEME_FILE = "file";
@@ -1722,36 +1718,6 @@
     }
 
     /**
-     * Turns a slice Uri into slice content.
-     *
-     * @param uri The URI to a slice provider
-     * @return The Slice provided by the app or null if none is given.
-     * @see Slice
-     * @hide
-     */
-    public final @Nullable Slice bindSlice(@NonNull Uri uri) {
-        Preconditions.checkNotNull(uri, "uri");
-        IContentProvider provider = acquireProvider(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("Unknown URI " + uri);
-        }
-        try {
-            Bundle extras = new Bundle();
-            extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri);
-            final Bundle res = provider.call(mPackageName, SliceProvider.METHOD_SLICE, null,
-                    extras);
-            Bundle.setDefusable(res, true);
-            return res.getParcelable(SliceProvider.EXTRA_SLICE);
-        } catch (RemoteException e) {
-            // Arbitrary and not worth documenting, as Activity
-            // Manager will kill this process shortly anyway.
-            return null;
-        } finally {
-            releaseProvider(provider);
-        }
-    }
-
-    /**
      * Returns the content provider for the given content URI.
      *
      * @param uri The URI to a content provider
@@ -1759,7 +1725,7 @@
      * @hide
      */
     public final IContentProvider acquireProvider(Uri uri) {
-        if (!SCHEME_CONTENT.equals(uri.getScheme()) && !SCHEME_SLICE.equals(uri.getScheme())) {
+        if (!SCHEME_CONTENT.equals(uri.getScheme())) {
             return null;
         }
         final String auth = uri.getAuthority();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 37b5d5d..105bb7e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3112,7 +3112,7 @@
     <!-- Allows an application to bind app's slices and get their
          content. This content will be surfaced to the
          user and not to leave the device.
-         <p>Not for use by third-party applications. @hide -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BIND_SLICE"
         android:protectionLevel="signature|privileged|development" />
 
diff --git a/core/res/res/layout/slice_grid.xml b/core/res/res/layout/slice_grid.xml
index 70df76b..15ded7b 100644
--- a/core/res/res/layout/slice_grid.xml
+++ b/core/res/res/layout/slice_grid.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<android.slice.views.GridView
+<android.app.slice.views.GridView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -21,4 +21,4 @@
     android:gravity="center_vertical"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:clipToPadding="false">
-</android.slice.views.GridView>
+</android.app.slice.views.GridView>
diff --git a/core/res/res/layout/slice_message.xml b/core/res/res/layout/slice_message.xml
index a3279b6..96f8078 100644
--- a/core/res/res/layout/slice_message.xml
+++ b/core/res/res/layout/slice_message.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<android.slice.views.MessageView
+<android.app.slice.views.MessageView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -48,4 +48,4 @@
         android:layout_alignStart="@android:id/title"
         android:textAppearance="?android:attr/textAppearanceListItem"
         android:maxLines="10" />
-</android.slice.views.MessageView>
+</android.app.slice.views.MessageView>
diff --git a/core/res/res/layout/slice_message_local.xml b/core/res/res/layout/slice_message_local.xml
index d4180f3..5c767ba 100644
--- a/core/res/res/layout/slice_message_local.xml
+++ b/core/res/res/layout/slice_message_local.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<android.slice.views.MessageView
+<android.app.slice.views.MessageView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -35,4 +35,4 @@
         android:background="#ffeeeeee"
         android:maxLines="10" />
 
-</android.slice.views.MessageView>
+</android.app.slice.views.MessageView>
diff --git a/core/res/res/layout/slice_remote_input.xml b/core/res/res/layout/slice_remote_input.xml
index dc570c4..90d0c82 100644
--- a/core/res/res/layout/slice_remote_input.xml
+++ b/core/res/res/layout/slice_remote_input.xml
@@ -15,7 +15,7 @@
      limitations under the License.
 -->
 <!-- LinearLayout -->
-<android.slice.views.RemoteInputView
+<android.app.slice.views.RemoteInputView
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/remote_input"
         android:background="@drawable/slice_remote_input_bg"
@@ -73,4 +73,4 @@
 
     </FrameLayout>
 
-</android.slice.views.RemoteInputView>
\ No newline at end of file
+</android.app.slice.views.RemoteInputView>
\ No newline at end of file