Loading api/current.txt +6 −3 Original line number Diff line number Diff line Loading @@ -7068,8 +7068,8 @@ package android.app.slice { public final class Slice implements android.os.Parcelable { ctor protected Slice(android.os.Parcel); method public static android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public static android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public static deprecated android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public static deprecated android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public int describeContents(); method public java.util.List<java.lang.String> getHints(); method public java.util.List<android.app.slice.SliceItem> getItems(); Loading Loading @@ -7155,7 +7155,10 @@ package android.app.slice { } public class SliceManager { method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri); method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>); method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, android.os.Handler); Loading @@ -7174,7 +7177,7 @@ package android.app.slice { method public final java.lang.String getType(android.net.Uri); method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues); method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public deprecated android.app.slice.Slice onBindSlice(android.net.Uri); method public java.util.Collection<android.net.Uri> onGetSliceDescendants(android.net.Uri); method public android.net.Uri onMapIntentToUri(android.content.Intent); method public void onSlicePinned(android.net.Uri); method public void onSliceUnpinned(android.net.Uri); core/java/android/app/slice/Slice.java +9 −65 Original line number Diff line number Diff line Loading @@ -21,12 +21,10 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ResolveInfo; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Bundle; Loading Loading @@ -553,16 +551,11 @@ public final class Slice implements Parcelable { } /** * Turns a slice Uri into slice content. * * @param resolver ContentResolver to be used. * @param uri The URI to a slice provider * @param supportedSpecs List of supported specs. * @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, List<SliceSpec> supportedSpecs) { * @deprecated TO BE REMOVED. */ @Deprecated public static @Nullable Slice bindSlice(ContentResolver resolver, @NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { Loading Loading @@ -590,60 +583,11 @@ public final class Slice implements Parcelable { } /** * Turns a slice intent into slice content. Expects an explicit intent. If there is no * {@link ContentProvider} associated with the given intent this will throw * {@link IllegalArgumentException}. * * @param context The context to use. * @param intent The intent associated with a slice. * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice * @see SliceProvider#onMapIntentToUri(Intent) * @see Intent * @deprecated TO BE REMOVED. */ @Deprecated public static @Nullable Slice bindSlice(Context context, @NonNull Intent intent, List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(intent, "intent"); Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, "Slice intent must be explicit " + intent); ContentResolver resolver = context.getContentResolver(); // Check if the intent has data for the slice uri on it and use that final Uri intentData = intent.getData(); if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) { return bindSlice(resolver, intentData, supportedSpecs); } // Otherwise ask the app List<ResolveInfo> providers = context.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null) { throw new IllegalArgumentException("Unable to resolve intent " + intent); } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } 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); } @NonNull List<SliceSpec> supportedSpecs) { return context.getSystemService(SliceManager.class).bindSlice(intent, supportedSpecs); } } core/java/android/app/slice/SliceManager.java +134 −0 Original line number Diff line number Diff line Loading @@ -17,17 +17,29 @@ package android.app.slice; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.content.ContentResolver; import android.content.Context; import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; Loading @@ -39,6 +51,8 @@ import java.util.concurrent.Executor; @SystemService(Context.SLICE_SERVICE) public class SliceManager { private static final String TAG = "SliceManager"; private final ISliceManager mService; private final Context mContext; private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup = Loading Loading @@ -223,6 +237,126 @@ public class SliceManager { } } /** * Obtains a list of slices that are descendants of the specified Uri. * <p> * Not all slice providers will implement this functionality, in which case, * an empty collection will be returned. * * @param uri The uri to look for descendants under. * @return All slices within the space. * @see SliceProvider#onGetSliceDescendants(Uri) */ public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) { ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_GET_DESCENDANTS, null, extras); return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS); } catch (RemoteException e) { Log.e(TAG, "Unable to get slice descendants", e); } finally { resolver.releaseProvider(provider); } return Collections.emptyList(); } /** * Turns a slice Uri into slice content. * * @param uri The URI to a slice provider * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice */ public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); ContentResolver resolver = mContext.getContentResolver(); 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); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE, null, extras); Bundle.setDefusable(res, true); if (res == null) { return null; } 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); } } /** * Turns a slice intent into slice content. Expects an explicit intent. If there is no * {@link android.content.ContentProvider} associated with the given intent this will throw * {@link IllegalArgumentException}. * * @param intent The intent associated with a slice. * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice * @see SliceProvider#onMapIntentToUri(Intent) * @see Intent */ public @Nullable Slice bindSlice(@NonNull Intent intent, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(intent, "intent"); Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, "Slice intent must be explicit " + intent); ContentResolver resolver = mContext.getContentResolver(); // Check if the intent has data for the slice uri on it and use that final Uri intentData = intent.getData(); if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) { return bindSlice(intentData, supportedSpecs); } // Otherwise ask the app List<ResolveInfo> providers = mContext.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null) { throw new IllegalArgumentException("Unable to resolve intent " + intent); } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } 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); } } /** * Class that listens to changes in {@link Slice}s. */ Loading core/java/android/app/slice/SliceProvider.java +50 −8 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ import android.os.StrictMode.ThreadPolicy; import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; Loading Loading @@ -110,6 +113,10 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String METHOD_UNPIN = "unpin"; /** * @hide */ public static final String METHOD_GET_DESCENDANTS = "get_descendants"; /** * @hide */ Loading @@ -118,6 +125,10 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String EXTRA_SLICE = "slice"; /** * @hide */ public static final String EXTRA_SLICE_DESCENDANTS = "slice_descendants"; private static final boolean DEBUG = false; Loading @@ -139,14 +150,6 @@ public abstract class SliceProvider extends ContentProvider { * @see {@link Slice#HINT_PARTIAL} */ public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) { return onBindSlice(sliceUri); } /** * @deprecated migrating to {@link #onBindSlice(Uri, List)} */ @Deprecated public Slice onBindSlice(Uri sliceUri) { return null; } Loading Loading @@ -182,6 +185,20 @@ public abstract class SliceProvider extends ContentProvider { public void onSliceUnpinned(Uri sliceUri) { } /** * Obtains a list of slices that are descendants of the specified Uri. * <p> * Implementing this is optional for a SliceProvider, but does provide a good * discovery mechanism for finding slice Uris. * * @param uri The uri to look for descendants under. * @return All slices within the space. * @see SliceManager#getSliceDescendants(Uri) */ public @NonNull Collection<Uri> onGetSliceDescendants(@NonNull Uri uri) { return Collections.emptyList(); } /** * This method must be overridden if an {@link IntentFilter} is specified on the SliceProvider. * In that case, this method can be called and is expected to return a non-null Uri representing Loading Loading @@ -290,10 +307,35 @@ public abstract class SliceProvider extends ContentProvider { "Slice binding requires the permission BIND_SLICE"); } handleUnpinSlice(uri); } else if (method.equals(METHOD_GET_DESCENDANTS)) { Uri uri = extras.getParcelable(EXTRA_BIND_URI); Bundle b = new Bundle(); b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS, new ArrayList<>(handleGetDescendants(uri))); return b; } return super.call(method, arg, extras); } private Collection<Uri> handleGetDescendants(Uri uri) { if (Looper.myLooper() == Looper.getMainLooper()) { return onGetSliceDescendants(uri); } else { CountDownLatch latch = new CountDownLatch(1); Collection<Uri>[] output = new Collection[1]; Handler.getMain().post(() -> { output[0] = onGetSliceDescendants(uri); latch.countDown(); }); try { latch.await(); return output[0]; } catch (InterruptedException e) { throw new RuntimeException(e); } } } private void handlePinSlice(Uri sliceUri) { if (Looper.myLooper() == Looper.getMainLooper()) { onSlicePinned(sliceUri); Loading Loading
api/current.txt +6 −3 Original line number Diff line number Diff line Loading @@ -7068,8 +7068,8 @@ package android.app.slice { public final class Slice implements android.os.Parcelable { ctor protected Slice(android.os.Parcel); method public static android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public static android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public static deprecated android.app.slice.Slice bindSlice(android.content.ContentResolver, android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public static deprecated android.app.slice.Slice bindSlice(android.content.Context, android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public int describeContents(); method public java.util.List<java.lang.String> getHints(); method public java.util.List<android.app.slice.SliceItem> getItems(); Loading Loading @@ -7155,7 +7155,10 @@ package android.app.slice { } public class SliceManager { method public android.app.slice.Slice bindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public android.app.slice.Slice bindSlice(android.content.Intent, java.util.List<android.app.slice.SliceSpec>); method public java.util.List<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri); method public java.util.Collection<android.net.Uri> getSliceDescendants(android.net.Uri); method public void pinSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>); method public void registerSliceCallback(android.net.Uri, android.app.slice.SliceManager.SliceCallback, java.util.List<android.app.slice.SliceSpec>, android.os.Handler); Loading @@ -7174,7 +7177,7 @@ package android.app.slice { method public final java.lang.String getType(android.net.Uri); method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues); method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>); method public deprecated android.app.slice.Slice onBindSlice(android.net.Uri); method public java.util.Collection<android.net.Uri> onGetSliceDescendants(android.net.Uri); method public android.net.Uri onMapIntentToUri(android.content.Intent); method public void onSlicePinned(android.net.Uri); method public void onSliceUnpinned(android.net.Uri);
core/java/android/app/slice/Slice.java +9 −65 Original line number Diff line number Diff line Loading @@ -21,12 +21,10 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.app.PendingIntent; import android.app.RemoteInput; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ResolveInfo; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.Bundle; Loading Loading @@ -553,16 +551,11 @@ public final class Slice implements Parcelable { } /** * Turns a slice Uri into slice content. * * @param resolver ContentResolver to be used. * @param uri The URI to a slice provider * @param supportedSpecs List of supported specs. * @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, List<SliceSpec> supportedSpecs) { * @deprecated TO BE REMOVED. */ @Deprecated public static @Nullable Slice bindSlice(ContentResolver resolver, @NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { Loading Loading @@ -590,60 +583,11 @@ public final class Slice implements Parcelable { } /** * Turns a slice intent into slice content. Expects an explicit intent. If there is no * {@link ContentProvider} associated with the given intent this will throw * {@link IllegalArgumentException}. * * @param context The context to use. * @param intent The intent associated with a slice. * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice * @see SliceProvider#onMapIntentToUri(Intent) * @see Intent * @deprecated TO BE REMOVED. */ @Deprecated public static @Nullable Slice bindSlice(Context context, @NonNull Intent intent, List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(intent, "intent"); Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, "Slice intent must be explicit " + intent); ContentResolver resolver = context.getContentResolver(); // Check if the intent has data for the slice uri on it and use that final Uri intentData = intent.getData(); if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) { return bindSlice(resolver, intentData, supportedSpecs); } // Otherwise ask the app List<ResolveInfo> providers = context.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null) { throw new IllegalArgumentException("Unable to resolve intent " + intent); } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } 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); } @NonNull List<SliceSpec> supportedSpecs) { return context.getSystemService(SliceManager.class).bindSlice(intent, supportedSpecs); } }
core/java/android/app/slice/SliceManager.java +134 −0 Original line number Diff line number Diff line Loading @@ -17,17 +17,29 @@ package android.app.slice; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.content.ContentResolver; import android.content.Context; import android.content.IContentProvider; import android.content.Intent; import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.ArrayMap; import android.util.Log; import android.util.Pair; import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.Executor; Loading @@ -39,6 +51,8 @@ import java.util.concurrent.Executor; @SystemService(Context.SLICE_SERVICE) public class SliceManager { private static final String TAG = "SliceManager"; private final ISliceManager mService; private final Context mContext; private final ArrayMap<Pair<Uri, SliceCallback>, ISliceListener> mListenerLookup = Loading Loading @@ -223,6 +237,126 @@ public class SliceManager { } } /** * Obtains a list of slices that are descendants of the specified Uri. * <p> * Not all slice providers will implement this functionality, in which case, * an empty collection will be returned. * * @param uri The uri to look for descendants under. * @return All slices within the space. * @see SliceProvider#onGetSliceDescendants(Uri) */ public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) { ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_GET_DESCENDANTS, null, extras); return res.getParcelableArrayList(SliceProvider.EXTRA_SLICE_DESCENDANTS); } catch (RemoteException e) { Log.e(TAG, "Unable to get slice descendants", e); } finally { resolver.releaseProvider(provider); } return Collections.emptyList(); } /** * Turns a slice Uri into slice content. * * @param uri The URI to a slice provider * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice */ public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); ContentResolver resolver = mContext.getContentResolver(); 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); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_SLICE, null, extras); Bundle.setDefusable(res, true); if (res == null) { return null; } 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); } } /** * Turns a slice intent into slice content. Expects an explicit intent. If there is no * {@link android.content.ContentProvider} associated with the given intent this will throw * {@link IllegalArgumentException}. * * @param intent The intent associated with a slice. * @param supportedSpecs List of supported specs. * @return The Slice provided by the app or null if none is given. * @see Slice * @see SliceProvider#onMapIntentToUri(Intent) * @see Intent */ public @Nullable Slice bindSlice(@NonNull Intent intent, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(intent, "intent"); Preconditions.checkArgument(intent.getComponent() != null || intent.getPackage() != null, "Slice intent must be explicit " + intent); ContentResolver resolver = mContext.getContentResolver(); // Check if the intent has data for the slice uri on it and use that final Uri intentData = intent.getData(); if (intentData != null && SliceProvider.SLICE_TYPE.equals(resolver.getType(intentData))) { return bindSlice(intentData, supportedSpecs); } // Otherwise ask the app List<ResolveInfo> providers = mContext.getPackageManager().queryIntentContentProviders(intent, 0); if (providers == null) { throw new IllegalArgumentException("Unable to resolve intent " + intent); } String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); extras.putParcelableArrayList(SliceProvider.EXTRA_SUPPORTED_SPECS, new ArrayList<>(supportedSpecs)); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } 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); } } /** * Class that listens to changes in {@link Slice}s. */ Loading
core/java/android/app/slice/SliceProvider.java +50 −8 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ import android.os.StrictMode.ThreadPolicy; import android.os.UserHandle; import android.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; Loading Loading @@ -110,6 +113,10 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String METHOD_UNPIN = "unpin"; /** * @hide */ public static final String METHOD_GET_DESCENDANTS = "get_descendants"; /** * @hide */ Loading @@ -118,6 +125,10 @@ public abstract class SliceProvider extends ContentProvider { * @hide */ public static final String EXTRA_SLICE = "slice"; /** * @hide */ public static final String EXTRA_SLICE_DESCENDANTS = "slice_descendants"; private static final boolean DEBUG = false; Loading @@ -139,14 +150,6 @@ public abstract class SliceProvider extends ContentProvider { * @see {@link Slice#HINT_PARTIAL} */ public Slice onBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) { return onBindSlice(sliceUri); } /** * @deprecated migrating to {@link #onBindSlice(Uri, List)} */ @Deprecated public Slice onBindSlice(Uri sliceUri) { return null; } Loading Loading @@ -182,6 +185,20 @@ public abstract class SliceProvider extends ContentProvider { public void onSliceUnpinned(Uri sliceUri) { } /** * Obtains a list of slices that are descendants of the specified Uri. * <p> * Implementing this is optional for a SliceProvider, but does provide a good * discovery mechanism for finding slice Uris. * * @param uri The uri to look for descendants under. * @return All slices within the space. * @see SliceManager#getSliceDescendants(Uri) */ public @NonNull Collection<Uri> onGetSliceDescendants(@NonNull Uri uri) { return Collections.emptyList(); } /** * This method must be overridden if an {@link IntentFilter} is specified on the SliceProvider. * In that case, this method can be called and is expected to return a non-null Uri representing Loading Loading @@ -290,10 +307,35 @@ public abstract class SliceProvider extends ContentProvider { "Slice binding requires the permission BIND_SLICE"); } handleUnpinSlice(uri); } else if (method.equals(METHOD_GET_DESCENDANTS)) { Uri uri = extras.getParcelable(EXTRA_BIND_URI); Bundle b = new Bundle(); b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS, new ArrayList<>(handleGetDescendants(uri))); return b; } return super.call(method, arg, extras); } private Collection<Uri> handleGetDescendants(Uri uri) { if (Looper.myLooper() == Looper.getMainLooper()) { return onGetSliceDescendants(uri); } else { CountDownLatch latch = new CountDownLatch(1); Collection<Uri>[] output = new Collection[1]; Handler.getMain().post(() -> { output[0] = onGetSliceDescendants(uri); latch.countDown(); }); try { latch.await(); return output[0]; } catch (InterruptedException e) { throw new RuntimeException(e); } } } private void handlePinSlice(Uri sliceUri) { if (Looper.myLooper() == Looper.getMainLooper()) { onSlicePinned(sliceUri); Loading