Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 64070557 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I25ebbcb3,Ic4439e0e

* changes:
  Switch SliceManager IContentProvider to ContentProviderClient
  Add backup/restore for slices access
parents 9fad6d28 632def14
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
}
+28 −34
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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 {
@@ -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();
    }
@@ -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;
@@ -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);
        }
    }

@@ -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;
            }
@@ -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);
        }
    }

@@ -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;
            }
@@ -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);
        }
    }

+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");
            }
        }
    }

}
+3 −0
Original line number Diff line number Diff line
@@ -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
@@ -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);
    }

@@ -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);
    }
+5 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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));

@@ -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) {
@@ -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