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

Commit e9b10faf authored by Chris Baron's avatar Chris Baron Committed by Android (Google) Code Review
Browse files

Merge "Allow callers with automotive projection role to call startBugreport()." into udc-qpr-dev

parents 4cdfacac 5d82a5e2
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
@@ -64,6 +65,8 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
    private static final int LOCAL_LOG_SIZE = 20;
    private static final String TAG = "BugreportManagerService";
    private static final boolean DEBUG = false;
    private static final String ROLE_SYSTEM_AUTOMOTIVE_PROJECTION =
            "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION";

    private static final String BUGREPORT_SERVICE = "bugreportd";
    private static final long DEFAULT_BUGREPORT_SERVICE_TIMEOUT_MILLIS = 30 * 1000;
@@ -326,11 +329,22 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {

        // To gain access through the DUMP permission, the OEM has to allow this package explicitly
        // via sysconfig and privileged permissions.
        if (mBugreportAllowlistedPackages.contains(callingPackage)
                && mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                        == PackageManager.PERMISSION_GRANTED) {
        boolean allowlisted = mBugreportAllowlistedPackages.contains(callingPackage);
        if (!allowlisted) {
            final long token = Binder.clearCallingIdentity();
            try {
                allowlisted = mContext.getSystemService(RoleManager.class).getRoleHolders(
                        ROLE_SYSTEM_AUTOMOTIVE_PROJECTION).contains(callingPackage);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        if (allowlisted && mContext.checkCallingOrSelfPermission(
                android.Manifest.permission.DUMP) == PackageManager.PERMISSION_GRANTED) {
            return;
        }

        // For carrier privileges, this can include user-installed apps. This is essentially a
        // function of the current active SIM(s) in the device to let carrier apps through.
        final long token = Binder.clearCallingIdentity();
@@ -346,7 +360,8 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {

        String message =
                callingPackage
                        + " does not hold the DUMP permission or is not bugreport-whitelisted "
                        + " does not hold the DUMP permission or is not bugreport-whitelisted or "
                        + "does not have an allowed role "
                        + (checkCarrierPrivileges ? "and does not have carrier privileges " : "")
                        + "to request a bugreport";
        Slog.w(TAG, message);
+1 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@
    <uses-permission android:name="android.permission.ACCESS_CONTEXT_HUB" />
    <uses-permission android:name="android.permission.USE_BIOMETRIC_INTERNAL" />
    <uses-permission android:name="android.permission.MANAGE_MEDIA_PROJECTION" />
    <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />

    <queries>
        <package android:name="com.android.servicestests.apps.suspendtestapp" />
+50 −7
Original line number Diff line number Diff line
@@ -16,15 +16,18 @@

package com.android.server.os;

import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertThrows;

import android.app.role.RoleManager;
import android.content.Context;
import android.os.Binder;
import android.os.BugreportManager.BugreportCallback;
import android.os.IBinder;
import android.os.IDumpstateListener;
import android.os.Process;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Pair;
@@ -37,21 +40,23 @@ import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.FileDescriptor;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

@RunWith(AndroidJUnit4.class)
public class BugreportManagerServiceImplTest {

    Context mContext;
    BugreportManagerServiceImpl mService;
    BugreportManagerServiceImpl.BugreportFileManager mBugreportFileManager;
    private Context mContext;
    private BugreportManagerServiceImpl mService;
    private BugreportManagerServiceImpl.BugreportFileManager mBugreportFileManager;

    int mCallingUid = 1234;
    String mCallingPackage  = "test.package";
    private int mCallingUid = 1234;
    private String mCallingPackage  = "test.package";

    String mBugreportFile = "bugreport-file.zip";
    String mBugreportFile2 = "bugreport-file2.zip";
    private String mBugreportFile = "bugreport-file.zip";
    private String mBugreportFile2 = "bugreport-file2.zip";

    @Before
    public void setUp() {
@@ -109,6 +114,36 @@ public class BugreportManagerServiceImplTest {
                BugreportCallback.BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE);
    }

    @Test
    public void testCancelBugreportWithoutRole() throws Exception {
        // Clear out allowlisted packages.
        mService = new BugreportManagerServiceImpl(
                new BugreportManagerServiceImpl.Injector(mContext, new ArraySet<>()));

        assertThrows(SecurityException.class, () -> mService.cancelBugreport(
                Binder.getCallingUid(), mContext.getPackageName()));
    }

    @Test
    public void testCancelBugreportWithRole() throws Exception {
        // Clear out allowlisted packages.
        mService = new BugreportManagerServiceImpl(
                new BugreportManagerServiceImpl.Injector(mContext, new ArraySet<>()));
        RoleManager roleManager = mContext.getSystemService(RoleManager.class);
        CallbackFuture future = new CallbackFuture();
        runWithShellPermissionIdentity(() -> roleManager.setBypassingRoleQualification(true));
        runWithShellPermissionIdentity(() -> roleManager.addRoleHolderAsUser(
                "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION",
                mContext.getPackageName(),
                /* flags= */ 0,
                Process.myUserHandle(),
                mContext.getMainExecutor(),
                future));

        assertThat(future.get()).isEqualTo(true);
        mService.cancelBugreport(Binder.getCallingUid(), mContext.getPackageName());
    }

    private static class Listener implements IDumpstateListener {
        CountDownLatch mLatch;
        int mErrorCode;
@@ -149,4 +184,12 @@ public class BugreportManagerServiceImplTest {
            return mErrorCode;
        }
    }

    private static class CallbackFuture extends CompletableFuture<Boolean>
            implements Consumer<Boolean> {
        @Override
        public void accept(Boolean successful) {
            complete(successful);
        }
    }
}