Allow callers with automotive projection role to call startBugreport().
See go/delayed-bugreport-retrieval-v2 for full context. The delayed bugreport retrieval API was added for Android Auto, but Android Auto does not have access to use it without this change.
BYPASS_INCLUSIVE_LANGUAGE_REASON=The name of the config field cannot be changed.
Bug: 289532159
Test: Treehugger passes and tested on phone
Change-Id: I2b612b367650f0e1f9ddef4e6c95da4540a12149
(cherry picked from commit 9e995a5724)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user