Merge "Refactor Bug report flow to work for all ADMIN users"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 68679c79..6f7d20a 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -455,8 +455,7 @@
intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash);
intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_NONCE, nonce);
intent.putExtra(EXTRA_BUGREPORT, bugreportFileName);
- context.sendBroadcastAsUser(intent, UserHandle.SYSTEM,
- android.Manifest.permission.DUMP);
+ context.sendBroadcast(intent, android.Manifest.permission.DUMP);
}
/**
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e7e2081..6b06bcd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7436,10 +7436,11 @@
if (shareDescription != null) {
triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
}
+ UserHandle callingUser = Binder.getCallingUserHandle();
final long identity = Binder.clearCallingIdentity();
try {
// Send broadcast to shell to trigger bugreport using Bugreport API
- mContext.sendBroadcastAsUser(triggerShellBugreport, UserHandle.SYSTEM);
+ mContext.sendBroadcastAsUser(triggerShellBugreport, callingUser);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/incident/IncidentCompanionService.java b/services/core/java/com/android/server/incident/IncidentCompanionService.java
index 87fe785..b8e7d49 100644
--- a/services/core/java/com/android/server/incident/IncidentCompanionService.java
+++ b/services/core/java/com/android/server/incident/IncidentCompanionService.java
@@ -34,7 +34,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Log;
import com.android.internal.util.DumpUtils;
@@ -128,21 +127,21 @@
try {
final Context context = getContext();
- final int primaryUser = getAndValidateUser(context);
- if (primaryUser == UserHandle.USER_NULL) {
+ // Get the current admin user. Only they can do incident reports.
+ final int currentAdminUser = getCurrentUserIfAdmin();
+ if (currentAdminUser == UserHandle.USER_NULL) {
return;
}
final Intent intent = new Intent(Intent.ACTION_INCIDENT_REPORT_READY);
intent.setComponent(new ComponentName(pkg, cls));
- Log.d(TAG, "sendReportReadyBroadcast sending primaryUser=" + primaryUser
- + " userHandle=" + UserHandle.getUserHandleForUid(primaryUser)
+ Log.d(TAG, "sendReportReadyBroadcast sending currentUser=" + currentAdminUser
+ + " userHandle=" + UserHandle.of(currentAdminUser)
+ " intent=" + intent);
- // Send it to the primary user. Only they can do incident reports.
context.sendBroadcastAsUserMultiplePermissions(intent,
- UserHandle.getUserHandleForUid(primaryUser),
+ UserHandle.of(currentAdminUser),
DUMP_AND_USAGE_STATS_PERMISSIONS);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -414,10 +413,10 @@
}
/**
- * Check whether the current user is the primary user, and return the user id if they are.
+ * Check whether the current user is an admin user, and return the user id if they are.
* Returns UserHandle.USER_NULL if not valid.
*/
- public static int getAndValidateUser(Context context) {
+ public static int getCurrentUserIfAdmin() {
// Current user
UserInfo currentUser;
try {
@@ -427,28 +426,21 @@
throw new RuntimeException(ex);
}
- // Primary user
- final UserManager um = UserManager.get(context);
- final UserInfo primaryUser = um.getPrimaryUser();
-
// Check that we're using the right user.
if (currentUser == null) {
Log.w(TAG, "No current user. Nobody to approve the report."
+ " The report will be denied.");
return UserHandle.USER_NULL;
}
- if (primaryUser == null) {
- Log.w(TAG, "No primary user. Nobody to approve the report."
- + " The report will be denied.");
- return UserHandle.USER_NULL;
- }
- if (primaryUser.id != currentUser.id) {
- Log.w(TAG, "Only the primary user can approve bugreports, but they are not"
- + " the current user. The report will be denied.");
+
+ if (!currentUser.isAdmin()) {
+ Log.w(TAG, "Only an admin user running in foreground can approve "
+ + "bugreports, but the current foreground user is not an admin user. "
+ + "The report will be denied.");
return UserHandle.USER_NULL;
}
- return primaryUser.id;
+ return currentUser.id;
}
}
diff --git a/services/core/java/com/android/server/incident/PendingReports.java b/services/core/java/com/android/server/incident/PendingReports.java
index f39bebf..6285bc3 100644
--- a/services/core/java/com/android/server/incident/PendingReports.java
+++ b/services/core/java/com/android/server/incident/PendingReports.java
@@ -16,6 +16,7 @@
package com.android.server.incident;
+import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.content.ComponentName;
@@ -272,15 +273,19 @@
return;
}
- // Find the primary user of this device.
- final int primaryUser = getAndValidateUser();
- if (primaryUser == UserHandle.USER_NULL) {
+ // Find the current user of the device and check if they are an admin.
+ final int currentAdminUser = getCurrentUserIfAdmin();
+
+ // Deny the report if the current admin user is null
+ // or not the user who requested the report.
+ if (currentAdminUser == UserHandle.USER_NULL
+ || currentAdminUser != UserHandle.getUserId(callingUid)) {
denyReportBeforeAddingRec(listener, callingPackage);
return;
}
// Find the approver app (hint: it's PermissionController).
- final ComponentName receiver = getApproverComponent(primaryUser);
+ final ComponentName receiver = getApproverComponent(currentAdminUser);
if (receiver == null) {
// We couldn't find an approver... so deny the request here and now, before we
// do anything else.
@@ -298,26 +303,26 @@
try {
listener.asBinder().linkToDeath(() -> {
Log.i(TAG, "Got death notification listener=" + listener);
- cancelReportImpl(listener, receiver, primaryUser);
+ cancelReportImpl(listener, receiver, currentAdminUser);
}, 0);
} catch (RemoteException ex) {
Log.e(TAG, "Remote died while trying to register death listener: " + rec.getUri());
// First, remove from our list.
- cancelReportImpl(listener, receiver, primaryUser);
+ cancelReportImpl(listener, receiver, currentAdminUser);
}
// Go tell Permission controller to start asking the user.
- sendBroadcast(receiver, primaryUser);
+ sendBroadcast(receiver, currentAdminUser);
}
/**
* Cancel a pending report request (because of an explicit call to cancel)
*/
private void cancelReportImpl(IIncidentAuthListener listener) {
- final int primaryUser = getAndValidateUser();
- final ComponentName receiver = getApproverComponent(primaryUser);
- if (primaryUser != UserHandle.USER_NULL && receiver != null) {
- cancelReportImpl(listener, receiver, primaryUser);
+ final int currentAdminUser = getCurrentUserIfAdmin();
+ final ComponentName receiver = getApproverComponent(currentAdminUser);
+ if (currentAdminUser != UserHandle.USER_NULL && receiver != null) {
+ cancelReportImpl(listener, receiver, currentAdminUser);
}
}
@@ -326,13 +331,13 @@
* by the calling app, or because of a binder death).
*/
private void cancelReportImpl(IIncidentAuthListener listener, ComponentName receiver,
- int primaryUser) {
+ @UserIdInt int user) {
// First, remove from our list.
synchronized (mLock) {
removePendingReportRecLocked(listener);
}
// Second, call back to PermissionController to say it's canceled.
- sendBroadcast(receiver, primaryUser);
+ sendBroadcast(receiver, user);
}
/**
@@ -342,21 +347,21 @@
* cleanup cases to keep the apps' list in sync with ours.
*/
private void sendBroadcast() {
- final int primaryUser = getAndValidateUser();
- if (primaryUser == UserHandle.USER_NULL) {
+ final int currentAdminUser = getCurrentUserIfAdmin();
+ if (currentAdminUser == UserHandle.USER_NULL) {
return;
}
- final ComponentName receiver = getApproverComponent(primaryUser);
+ final ComponentName receiver = getApproverComponent(currentAdminUser);
if (receiver == null) {
return;
}
- sendBroadcast(receiver, primaryUser);
+ sendBroadcast(receiver, currentAdminUser);
}
/**
* Send the confirmation broadcast.
*/
- private void sendBroadcast(ComponentName receiver, int primaryUser) {
+ private void sendBroadcast(ComponentName receiver, int currentUser) {
final Intent intent = new Intent(Intent.ACTION_PENDING_INCIDENT_REPORTS_CHANGED);
intent.setComponent(receiver);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -364,8 +369,8 @@
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setBackgroundActivityStartsAllowed(true);
- // Send it to the primary user.
- mContext.sendBroadcastAsUser(intent, UserHandle.getUserHandleForUid(primaryUser),
+ // Send it to the current user.
+ mContext.sendBroadcastAsUser(intent, UserHandle.of(currentUser),
android.Manifest.permission.APPROVE_INCIDENT_REPORTS, options.toBundle());
}
@@ -420,11 +425,11 @@
}
/**
- * Check whether the current user is the primary user, and return the user id if they are.
+ * Check whether the current user is an admin user, and return the user id if they are.
* Returns UserHandle.USER_NULL if not valid.
*/
- private int getAndValidateUser() {
- return IncidentCompanionService.getAndValidateUser(mContext);
+ private int getCurrentUserIfAdmin() {
+ return IncidentCompanionService.getCurrentUserIfAdmin();
}
/**
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 58428ca..2fdc4cd 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -33,8 +33,8 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
-import android.os.UserManager;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
@@ -189,10 +189,10 @@
}
/**
- * Validates that the current user is the primary user or when bugreport is requested remotely
- * and current user is affiliated user.
+ * Validates that the current user is an admin user or, when bugreport is requested remotely
+ * that the current user is an affiliated user.
*
- * @throws IllegalArgumentException if the current user is not the primary user
+ * @throws IllegalArgumentException if the current user is not an admin user
*/
private void ensureUserCanTakeBugReport(int bugreportMode) {
UserInfo currentUser = null;
@@ -202,20 +202,17 @@
// Impossible to get RemoteException for an in-process call.
}
- UserInfo primaryUser = UserManager.get(mContext).getPrimaryUser();
if (currentUser == null) {
- logAndThrow("No current user. Only primary user is allowed to take bugreports.");
+ logAndThrow("There is no current user, so no bugreport can be requested.");
}
- if (primaryUser == null) {
- logAndThrow("No primary user. Only primary user is allowed to take bugreports.");
- }
- if (primaryUser.id != currentUser.id) {
+
+ if (!currentUser.isAdmin()) {
if (bugreportMode == BugreportParams.BUGREPORT_MODE_REMOTE
&& isCurrentUserAffiliated(currentUser.id)) {
return;
}
- logAndThrow("Current user not primary user. Only primary user"
- + " is allowed to take bugreports.");
+ logAndThrow(TextUtils.formatSimple("Current user %s is not an admin user."
+ + " Only admin users are allowed to take bugreport.", currentUser.id));
}
}