Loading core/java/android/app/slice/ISliceManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,7 @@ interface ISliceManager { SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices); byte[] getBackupPayload(int user); void applyRestore(in byte[] payload, int user); } core/java/android/app/slice/SliceManager.java +28 −34 Original line number Diff line number Diff line Loading @@ -20,9 +20,9 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.content.ContentProviderClient; 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; Loading Loading @@ -193,10 +193,15 @@ public class SliceManager { * <p> * Pinned state is not persisted across reboots, so apps are expected to re-pin any slices * they still care about after a reboot. * <p> * This may only be called by apps that are the default launcher for the device * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being pinned. * @param specs The list of supported {@link SliceSpec}s of the callback. * @see SliceProvider#onSlicePinned(Uri) * @see Intent#ACTION_ASSIST * @see Intent#CATEGORY_HOME */ public void pinSlice(@NonNull Uri uri, @NonNull List<SliceSpec> specs) { try { Loading @@ -211,10 +216,15 @@ public class SliceManager { * Remove a pin for a slice. * <p> * If the slice has no other pins/callbacks then the slice will be unpinned. * <p> * This may only be called by apps that are the default launcher for the device * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being unpinned. * @see #pinSlice * @see SliceProvider#onSliceUnpinned(Uri) * @see Intent#ACTION_ASSIST * @see Intent#CATEGORY_HOME */ public void unpinSlice(@NonNull Uri uri) { try { Loading Loading @@ -262,17 +272,13 @@ public class SliceManager { */ public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) { ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try { try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_GET_DESCENDANTS, null, extras); final Bundle res = provider.call(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(); } Loading @@ -288,17 +294,15 @@ public class SliceManager { public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(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(mContext.getPackageName(), SliceProvider.METHOD_SLICE, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_SLICE, null, extras); Bundle.setDefusable(res, true); if (res == null) { return null; Loading @@ -308,8 +312,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading Loading @@ -344,15 +346,13 @@ public class SliceManager { String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); final Bundle res = provider.call(mContext.getPackageName(), SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras); if (res == null) { return null; } Loading @@ -361,8 +361,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading Loading @@ -399,17 +397,15 @@ public class SliceManager { String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(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(mContext.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } Loading @@ -418,8 +414,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading core/java/com/android/server/backup/SliceBackupHelper.java 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.android.server.backup; import android.app.backup.BlobBackupHelper; import android.app.slice.ISliceManager; import android.content.Context; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import android.util.Slog; public class SliceBackupHelper extends BlobBackupHelper { static final String TAG = "SliceBackupHelper"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // Current version of the blob schema static final int BLOB_VERSION = 1; // Key under which the payload blob is stored static final String KEY_SLICES = "slices"; public SliceBackupHelper(Context context) { super(BLOB_VERSION, KEY_SLICES); // context is currently unused } @Override protected byte[] getBackupPayload(String key) { byte[] newPayload = null; if (KEY_SLICES.equals(key)) { try { ISliceManager sm = ISliceManager.Stub.asInterface( ServiceManager.getService(Context.SLICE_SERVICE)); // TODO: http://b/22388012 newPayload = sm.getBackupPayload(UserHandle.USER_SYSTEM); } catch (Exception e) { // Treat as no data Slog.e(TAG, "Couldn't communicate with slice manager"); newPayload = null; } } return newPayload; } @Override protected void applyRestoredPayload(String key, byte[] payload) { if (DEBUG) Slog.v(TAG, "Got restore of " + key); if (KEY_SLICES.equals(key)) { try { ISliceManager sm = ISliceManager.Stub.asInterface( ServiceManager.getService(Context.SLICE_SERVICE)); // TODO: http://b/22388012 sm.applyRestore(payload, UserHandle.USER_SYSTEM); } catch (Exception e) { Slog.e(TAG, "Couldn't communicate with slice manager"); } } } } core/java/com/android/server/backup/SystemBackupAgent.java +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String USAGE_STATS_HELPER = "usage_stats"; private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; private static final String SLICES_HELPER = "slices"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are Loading Loading @@ -88,6 +89,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onBackup(oldState, data, newState); } Loading Loading @@ -116,6 +118,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onRestore(data, appVersionCode, newState); } Loading services/core/java/com/android/server/slice/SliceFullAccessList.java +5 −3 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.server.slice; import android.content.Context; import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.util.XmlUtils; Loading Loading @@ -72,7 +72,7 @@ public class SliceFullAccessList { pkgs.remove(pkg); } public void writeXml(XmlSerializer out) throws IOException { public void writeXml(XmlSerializer out, int user) throws IOException { out.startTag(null, TAG_LIST); out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION)); Loading @@ -80,6 +80,9 @@ public class SliceFullAccessList { for (int i = 0 ; i < N; i++) { final int userId = mFullAccessPkgs.keyAt(i); final ArraySet<String> pkgs = mFullAccessPkgs.valueAt(i); if (user != UserHandle.USER_ALL && user != userId) { continue; } out.startTag(null, TAG_USER); out.attribute(null, ATT_USER_ID, Integer.toString(userId)); if (pkgs != null) { Loading @@ -88,7 +91,6 @@ public class SliceFullAccessList { out.startTag(null, TAG_PKG); out.text(pkgs.valueAt(j)); out.endTag(null, TAG_PKG); } } out.endTag(null, TAG_USER); Loading Loading
core/java/android/app/slice/ISliceManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -31,4 +31,7 @@ interface ISliceManager { SliceSpec[] getPinnedSpecs(in Uri uri, String pkg); int checkSlicePermission(in Uri uri, String pkg, int pid, int uid); void grantPermissionFromUser(in Uri uri, String pkg, String callingPkg, boolean allSlices); byte[] getBackupPayload(int user); void applyRestore(in byte[] payload, int user); }
core/java/android/app/slice/SliceManager.java +28 −34 Original line number Diff line number Diff line Loading @@ -20,9 +20,9 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.content.ContentProviderClient; 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; Loading Loading @@ -193,10 +193,15 @@ public class SliceManager { * <p> * Pinned state is not persisted across reboots, so apps are expected to re-pin any slices * they still care about after a reboot. * <p> * This may only be called by apps that are the default launcher for the device * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being pinned. * @param specs The list of supported {@link SliceSpec}s of the callback. * @see SliceProvider#onSlicePinned(Uri) * @see Intent#ACTION_ASSIST * @see Intent#CATEGORY_HOME */ public void pinSlice(@NonNull Uri uri, @NonNull List<SliceSpec> specs) { try { Loading @@ -211,10 +216,15 @@ public class SliceManager { * Remove a pin for a slice. * <p> * If the slice has no other pins/callbacks then the slice will be unpinned. * <p> * This may only be called by apps that are the default launcher for the device * or the default voice interaction service. Otherwise will throw {@link SecurityException}. * * @param uri The uri of the slice being unpinned. * @see #pinSlice * @see SliceProvider#onSliceUnpinned(Uri) * @see Intent#ACTION_ASSIST * @see Intent#CATEGORY_HOME */ public void unpinSlice(@NonNull Uri uri) { try { Loading Loading @@ -262,17 +272,13 @@ public class SliceManager { */ public @NonNull Collection<Uri> getSliceDescendants(@NonNull Uri uri) { ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try { try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_BIND_URI, uri); final Bundle res = provider.call(resolver.getPackageName(), SliceProvider.METHOD_GET_DESCENDANTS, null, extras); final Bundle res = provider.call(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(); } Loading @@ -288,17 +294,15 @@ public class SliceManager { public @Nullable Slice bindSlice(@NonNull Uri uri, @NonNull List<SliceSpec> supportedSpecs) { Preconditions.checkNotNull(uri, "uri"); ContentResolver resolver = mContext.getContentResolver(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(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(mContext.getPackageName(), SliceProvider.METHOD_SLICE, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_SLICE, null, extras); Bundle.setDefusable(res, true); if (res == null) { return null; Loading @@ -308,8 +312,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading Loading @@ -344,15 +346,13 @@ public class SliceManager { String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(uri)) { if (provider == null) { throw new IllegalArgumentException("Unknown URI " + uri); } try { Bundle extras = new Bundle(); extras.putParcelable(SliceProvider.EXTRA_INTENT, intent); final Bundle res = provider.call(mContext.getPackageName(), SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_MAP_ONLY_INTENT, null, extras); if (res == null) { return null; } Loading @@ -361,8 +361,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading Loading @@ -399,17 +397,15 @@ public class SliceManager { String authority = providers.get(0).providerInfo.authority; Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) .authority(authority).build(); IContentProvider provider = resolver.acquireProvider(uri); try (ContentProviderClient provider = resolver.acquireContentProviderClient(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(mContext.getPackageName(), SliceProvider.METHOD_MAP_INTENT, null, extras); final Bundle res = provider.call(SliceProvider.METHOD_MAP_INTENT, null, extras); if (res == null) { return null; } Loading @@ -418,8 +414,6 @@ public class SliceManager { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { resolver.releaseProvider(provider); } } Loading
core/java/com/android/server/backup/SliceBackupHelper.java 0 → 100644 +74 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.android.server.backup; import android.app.backup.BlobBackupHelper; import android.app.slice.ISliceManager; import android.content.Context; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import android.util.Slog; public class SliceBackupHelper extends BlobBackupHelper { static final String TAG = "SliceBackupHelper"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // Current version of the blob schema static final int BLOB_VERSION = 1; // Key under which the payload blob is stored static final String KEY_SLICES = "slices"; public SliceBackupHelper(Context context) { super(BLOB_VERSION, KEY_SLICES); // context is currently unused } @Override protected byte[] getBackupPayload(String key) { byte[] newPayload = null; if (KEY_SLICES.equals(key)) { try { ISliceManager sm = ISliceManager.Stub.asInterface( ServiceManager.getService(Context.SLICE_SERVICE)); // TODO: http://b/22388012 newPayload = sm.getBackupPayload(UserHandle.USER_SYSTEM); } catch (Exception e) { // Treat as no data Slog.e(TAG, "Couldn't communicate with slice manager"); newPayload = null; } } return newPayload; } @Override protected void applyRestoredPayload(String key, byte[] payload) { if (DEBUG) Slog.v(TAG, "Got restore of " + key); if (KEY_SLICES.equals(key)) { try { ISliceManager sm = ISliceManager.Stub.asInterface( ServiceManager.getService(Context.SLICE_SERVICE)); // TODO: http://b/22388012 sm.applyRestore(payload, UserHandle.USER_SYSTEM); } catch (Exception e) { Slog.e(TAG, "Couldn't communicate with slice manager"); } } } }
core/java/com/android/server/backup/SystemBackupAgent.java +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String USAGE_STATS_HELPER = "usage_stats"; private static final String SHORTCUT_MANAGER_HELPER = "shortcut_manager"; private static final String ACCOUNT_MANAGER_HELPER = "account_manager"; private static final String SLICES_HELPER = "slices"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are Loading Loading @@ -88,6 +89,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onBackup(oldState, data, newState); } Loading Loading @@ -116,6 +118,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); addHelper(SHORTCUT_MANAGER_HELPER, new ShortcutBackupHelper()); addHelper(ACCOUNT_MANAGER_HELPER, new AccountManagerBackupHelper()); addHelper(SLICES_HELPER, new SliceBackupHelper(this)); super.onRestore(data, appVersionCode, newState); } Loading
services/core/java/com/android/server/slice/SliceFullAccessList.java +5 −3 Original line number Diff line number Diff line Loading @@ -16,9 +16,9 @@ package com.android.server.slice; import android.content.Context; import android.content.pm.UserInfo; import android.os.UserHandle; import android.os.UserManager; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; import com.android.internal.util.XmlUtils; Loading Loading @@ -72,7 +72,7 @@ public class SliceFullAccessList { pkgs.remove(pkg); } public void writeXml(XmlSerializer out) throws IOException { public void writeXml(XmlSerializer out, int user) throws IOException { out.startTag(null, TAG_LIST); out.attribute(null, ATT_VERSION, String.valueOf(DB_VERSION)); Loading @@ -80,6 +80,9 @@ public class SliceFullAccessList { for (int i = 0 ; i < N; i++) { final int userId = mFullAccessPkgs.keyAt(i); final ArraySet<String> pkgs = mFullAccessPkgs.valueAt(i); if (user != UserHandle.USER_ALL && user != userId) { continue; } out.startTag(null, TAG_USER); out.attribute(null, ATT_USER_ID, Integer.toString(userId)); if (pkgs != null) { Loading @@ -88,7 +91,6 @@ public class SliceFullAccessList { out.startTag(null, TAG_PKG); out.text(pkgs.valueAt(j)); out.endTag(null, TAG_PKG); } } out.endTag(null, TAG_USER); Loading