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

Commit f864b5a8 authored by Steven Lee's avatar Steven Lee
Browse files

Implement consentless bugreport mechanism

When required conditions are met, bugreport could be approved silently:
 1. BugreportMode allows consentless bugreport.
 2. Current build type is "userdebug" or "eng".
 3. Caller has its OP_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD App-Op ALLOWED.

 - Adds an FLAG_ALLOW_CONSENTLESS_BUGREPORT in IncidentManager
 - Updates PendingReports.authorizeReportImpl() that when consentless bugreport allowed and
   build type is userdebug or eng and corresponding AppOps is allowed, the bugreport could be approved silently.

Legal tracker bug: 262936053
Privacy tracker bug: 262936015
Security tracker bug: 265360498

Bug: 259436697
Bug: 262628255
Bug: 263163716
Test: builds
Test: Manual test
Change-Id: I6c2fb50d307c8d227774b76ab86d608bd95027fa
parent 8c2e86d1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -10041,6 +10041,7 @@ package android.os {
    method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
    method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
    method public void unregisterSection(int);
    field public static final int FLAG_ALLOW_CONSENTLESS_BUGREPORT = 2; // 0x2
    field public static final int FLAG_CONFIRMATION_DIALOG = 1; // 0x1
    field public static final int PRIVACY_POLICY_AUTO = 200; // 0xc8
    field public static final int PRIVACY_POLICY_EXPLICIT = 100; // 0x64
+15 −1
Original line number Diff line number Diff line
@@ -118,6 +118,19 @@ public class IncidentManager {
     */
    public static final int FLAG_CONFIRMATION_DIALOG = 0x1;

    /**
     * Flag marking whether corresponding pending report allows consentless bugreport.
     */
    public static final int FLAG_ALLOW_CONSENTLESS_BUGREPORT = 0x2;

    /** @hide */
    @IntDef(flag = true, prefix = { "FLAG_" }, value = {
            FLAG_CONFIRMATION_DIALOG,
            FLAG_ALLOW_CONSENTLESS_BUGREPORT,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PendingReportFlags {}

    /**
     * Flag marking fields and incident reports than can be taken
     * off the device only via adb.
@@ -220,8 +233,9 @@ public class IncidentManager {
        /**
         * Get the flags requested for this pending report.
         *
         * @see #FLAG_CONFIRMATION_DIALOG
         * @see PendingReportFlags
         */
        @PendingReportFlags
        public int getFlags() {
            return mFlags;
        }
+37 −0
Original line number Diff line number Diff line
@@ -16,15 +16,20 @@

package com.android.server.incident;

import static android.permission.PermissionManager.PERMISSION_GRANTED;

import android.Manifest;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.IIncidentAuthListener;
import android.os.IncidentManager;
@@ -32,6 +37,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.permission.PermissionManager;
import android.util.Log;

import java.io.FileDescriptor;
@@ -55,6 +61,7 @@ class PendingReports {
    private final Context mContext;
    private final PackageManager mPackageManager;
    private final AppOpsManager mAppOpsManager;
    private final PermissionManager mPermissionManager;

    //
    // All fields below must be protected by mLock
@@ -126,6 +133,7 @@ class PendingReports {
        mContext = context;
        mPackageManager = context.getPackageManager();
        mAppOpsManager = context.getSystemService(AppOpsManager.class);
        mPermissionManager = context.getSystemService(PermissionManager.class);
    }

    /**
@@ -297,6 +305,35 @@ class PendingReports {
            return;
        }

        // Only with userdebug/eng build: it could check capture consentless bugreport permission
        // and approve the report when it's granted.
        boolean captureConsentlessBugreportOnUserdebugBuildGranted = false;
        if ((Build.IS_USERDEBUG || Build.IS_ENG)
                && (flags & IncidentManager.FLAG_ALLOW_CONSENTLESS_BUGREPORT) != 0) {
            AttributionSource attributionSource =
                    new AttributionSource.Builder(callingUid)
                            .setPackageName(callingPackage)
                            .build();
            captureConsentlessBugreportOnUserdebugBuildGranted =
                    mPermissionManager.checkPermissionForDataDelivery(
                            Manifest.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
                            attributionSource,
                            /* message= */ null)
                            == PERMISSION_GRANTED;
        }
        if (captureConsentlessBugreportOnUserdebugBuildGranted) {
            try {
                PendingReportRec rec =
                        new PendingReportRec(
                                callingPackage, receiverClass, reportId, flags, listener);
                Log.d(TAG, "approving consentless report: " + rec.getUri());
                listener.onReportApproved();
                return;
            } catch (RemoteException e) {
                Log.e(TAG, "authorizeReportImpl listener.onReportApproved RemoteException: ", e);
            }
        }

        // Save the record for when the PermissionController comes back to authorize it.
        PendingReportRec rec = null;
        synchronized (mLock) {