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

Commit fb9ecfc8 authored by Jason Monk's avatar Jason Monk Committed by android-build-merger
Browse files

Merge "Add shell command to get slice permissions" into pi-dev

am: 33da7043

Change-Id: I14985fc75c6066cc0c21df870300d435d5127299
parents 9cb0a9f1 33da7043
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -127,6 +127,10 @@ public abstract class SliceProvider extends ContentProvider {
     * @hide
     */
    public static final String METHOD_GET_DESCENDANTS = "get_descendants";
    /**
     * @hide
     */
    public static final String METHOD_GET_PERMISSIONS = "get_permissions";
    /**
     * @hide
     */
@@ -147,6 +151,10 @@ public abstract class SliceProvider extends ContentProvider {
     * @hide
     */
    public static final String EXTRA_PROVIDER_PKG = "provider_pkg";
    /**
     * @hide
     */
    public static final String EXTRA_RESULT = "result";

    private static final boolean DEBUG = false;

@@ -392,6 +400,13 @@ public abstract class SliceProvider extends ContentProvider {
            b.putParcelableArrayList(EXTRA_SLICE_DESCENDANTS,
                    new ArrayList<>(handleGetDescendants(uri)));
            return b;
        } else if (method.equals(METHOD_GET_PERMISSIONS)) {
            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                throw new SecurityException("Only the system can get permissions");
            }
            Bundle b = new Bundle();
            b.putStringArray(EXTRA_RESULT, mAutoGrantPermissions);
            return b;
        }
        return super.call(method, arg, extras);
    }
+18 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -49,6 +50,8 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Slog;
@@ -69,6 +72,7 @@ import org.xmlpull.v1.XmlSerializer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -320,6 +324,12 @@ public class SliceManagerService extends ISliceManager.Stub {
        }
    }

    @Override
    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
        new SliceShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
    }

    ///  ----- internal code -----
    private void enforceOwner(String pkg, Uri uri, int user) {
        if (!Objects.equals(getProviderPkg(uri, user), pkg) || pkg == null) {
@@ -541,6 +551,14 @@ public class SliceManagerService extends ISliceManager.Stub {
        }
    };

    public String[] getAllPackagesGranted(String authority) {
        String pkg = getProviderPkg(new Uri.Builder()
                .scheme(ContentResolver.SCHEME_CONTENT)
                .authority(authority)
                .build(), 0);
        return mPermissions.getAllPackagesGranted(pkg);
    }

    public static class Lifecycle extends SystemService {
        private SliceManagerService mService;

+10 −0
Original line number Diff line number Diff line
@@ -133,6 +133,16 @@ public class SlicePermissionManager implements DirtyTracker {
        mHandler.obtainMessage(H.MSG_REMOVE, pkgUser);
    }

    public String[] getAllPackagesGranted(String pkg) {
        ArraySet<String> ret = new ArraySet<>();
        for (SliceAuthority authority : getProvider(new PkgUser(pkg, 0)).getAuthorities()) {
            for (PkgUser pkgUser : authority.getPkgs()) {
                ret.add(pkgUser.mPkg);
            }
        }
        return ret.toArray(new String[ret.size()]);
    }

    public boolean hasFullAccess(String pkg, int userId) {
        PkgUser pkgUser = new PkgUser(pkg, userId);
        return getClient(pkgUser).hasFullAccess();
+110 −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.slice;

import android.app.slice.SliceProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Process;
import android.os.ShellCommand;
import android.util.ArraySet;

import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

public class SliceShellCommand extends ShellCommand {

    private final SliceManagerService mService;

    public SliceShellCommand(SliceManagerService service) {
        mService = service;
    }

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
            return handleDefaultCommands(cmd);
        }
        switch (cmd) {
            case "get-permissions":
                return runGetPermissions(getNextArgRequired());
        }
        return 0;
    }

    @Override
    public void onHelp() {
        final PrintWriter pw = getOutPrintWriter();
        pw.println("Status bar commands:");
        pw.println("  help");
        pw.println("    Print this help text.");
        pw.println("");
        pw.println("  get-permissions <authority>");
        pw.println("    List the pkgs that have permission to an authority.");
        pw.println("");

    }

    private int runGetPermissions(String authority) {
        if (Binder.getCallingUid() != Process.SHELL_UID
                && Binder.getCallingUid() != Process.ROOT_UID) {
            getOutPrintWriter().println("Only shell can get permissions");
            return -1;
        }
        Context context = mService.getContext();
        long ident = Binder.clearCallingIdentity();
        try {
            Uri uri = new Uri.Builder()
                    .scheme(ContentResolver.SCHEME_CONTENT)
                    .authority(authority)
                    .build();
            if (!SliceProvider.SLICE_TYPE.equals(context.getContentResolver().getType(uri))) {
                getOutPrintWriter().println(authority + " is not a slice provider");
                return -1;
            }
            Bundle b = context.getContentResolver().call(uri, SliceProvider.METHOD_GET_PERMISSIONS,
                    null, null);
            if (b == null) {
                getOutPrintWriter().println("An error occurred getting permissions");
                return -1;
            }
            String[] permissions = b.getStringArray(SliceProvider.EXTRA_RESULT);
            final PrintWriter pw = getOutPrintWriter();
            Set<String> listedPackages = new ArraySet<>();
            if (permissions != null && permissions.length != 0) {
                List<PackageInfo> apps =
                        context.getPackageManager().getPackagesHoldingPermissions(permissions, 0);
                for (PackageInfo app : apps) {
                    pw.println(app.packageName);
                    listedPackages.add(app.packageName);
                }
            }
            for (String pkg : mService.getAllPackagesGranted(authority)) {
                if (!listedPackages.contains(pkg)) {
                    pw.println(pkg);
                    listedPackages.add(pkg);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
        return 0;
    }
}