Merge "Make BugreportManager a public API that respects carrier privileges." am: 0dcf4de7df
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1552883 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I9e835752e37bcb99e35078025bb43fb46313833f
This commit is contained in:
@@ -10187,6 +10187,7 @@ package android.content {
|
||||
field public static final String BIOMETRIC_SERVICE = "biometric";
|
||||
field public static final String BLOB_STORE_SERVICE = "blob_store";
|
||||
field public static final String BLUETOOTH_SERVICE = "bluetooth";
|
||||
field public static final String BUGREPORT_SERVICE = "bugreport";
|
||||
field public static final String CAMERA_SERVICE = "camera";
|
||||
field public static final String CAPTIONING_SERVICE = "captioning";
|
||||
field public static final String CARRIER_CONFIG_SERVICE = "carrier_config";
|
||||
@@ -29596,6 +29597,24 @@ package android.os {
|
||||
method public boolean unlinkToDeath(@NonNull android.os.IBinder.DeathRecipient, int);
|
||||
}
|
||||
|
||||
public final class BugreportManager {
|
||||
method public void cancelBugreport();
|
||||
method public void startConnectivityBugreport(@NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
|
||||
}
|
||||
|
||||
public abstract static class BugreportManager.BugreportCallback {
|
||||
ctor public BugreportManager.BugreportCallback();
|
||||
method public void onEarlyReportFinished();
|
||||
method public void onError(int);
|
||||
method public void onFinished();
|
||||
method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
|
||||
field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
|
||||
field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
|
||||
field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
|
||||
field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
|
||||
field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
|
||||
}
|
||||
|
||||
public class Build {
|
||||
ctor public Build();
|
||||
method @NonNull public static java.util.List<android.os.Build.Partition> getFingerprintedPartitions();
|
||||
|
||||
@@ -1684,7 +1684,6 @@ package android.content {
|
||||
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
|
||||
field public static final String BACKUP_SERVICE = "backup";
|
||||
field public static final String BATTERY_STATS_SERVICE = "batterystats";
|
||||
field public static final String BUGREPORT_SERVICE = "bugreport";
|
||||
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
|
||||
field public static final String CONTEXTHUB_SERVICE = "contexthub";
|
||||
field public static final String ETHERNET_SERVICE = "ethernet";
|
||||
@@ -7046,24 +7045,10 @@ package android.os {
|
||||
}
|
||||
|
||||
public final class BugreportManager {
|
||||
method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
|
||||
method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
|
||||
method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
|
||||
}
|
||||
|
||||
public abstract static class BugreportManager.BugreportCallback {
|
||||
ctor public BugreportManager.BugreportCallback();
|
||||
method public void onEarlyReportFinished();
|
||||
method public void onError(int);
|
||||
method public void onFinished();
|
||||
method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
|
||||
field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
|
||||
field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
|
||||
field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
|
||||
field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
|
||||
field public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3; // 0x3
|
||||
}
|
||||
|
||||
public final class BugreportParams {
|
||||
ctor public BugreportParams(int);
|
||||
method public int getMode();
|
||||
|
||||
@@ -4999,9 +4999,7 @@ public abstract class Context {
|
||||
* Service to capture a bugreport.
|
||||
* @see #getSystemService(String)
|
||||
* @see android.os.BugreportManager
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final String BUGREPORT_SERVICE = "bugreport";
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SuppressAutoDoc;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.app.ActivityManager;
|
||||
@@ -40,12 +41,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Class that provides a privileged API to capture and consume bugreports.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
/** Class that provides a privileged API to capture and consume bugreports. */
|
||||
@SystemService(Context.BUGREPORT_SERVICE)
|
||||
public final class BugreportManager {
|
||||
|
||||
@@ -60,28 +56,30 @@ public final class BugreportManager {
|
||||
mBinder = binder;
|
||||
}
|
||||
|
||||
/**
|
||||
* An interface describing the callback for bugreport progress and status.
|
||||
*/
|
||||
/** An interface describing the callback for bugreport progress and status. */
|
||||
public abstract static class BugreportCallback {
|
||||
/** @hide */
|
||||
/**
|
||||
* Possible error codes taking a bugreport can encounter.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
|
||||
BUGREPORT_ERROR_INVALID_INPUT,
|
||||
BUGREPORT_ERROR_RUNTIME,
|
||||
BUGREPORT_ERROR_USER_DENIED_CONSENT,
|
||||
BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
|
||||
BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
|
||||
})
|
||||
|
||||
/** Possible error codes taking a bugreport can encounter */
|
||||
@IntDef(
|
||||
prefix = {"BUGREPORT_ERROR_"},
|
||||
value = {
|
||||
BUGREPORT_ERROR_INVALID_INPUT,
|
||||
BUGREPORT_ERROR_RUNTIME,
|
||||
BUGREPORT_ERROR_USER_DENIED_CONSENT,
|
||||
BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
|
||||
BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
|
||||
})
|
||||
public @interface BugreportErrorCode {}
|
||||
|
||||
/** The input options were invalid */
|
||||
public static final int BUGREPORT_ERROR_INVALID_INPUT =
|
||||
IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
|
||||
|
||||
/** A runtime error occured */
|
||||
/** A runtime error occurred */
|
||||
public static final int BUGREPORT_ERROR_RUNTIME =
|
||||
IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
|
||||
|
||||
@@ -99,6 +97,7 @@ public final class BugreportManager {
|
||||
|
||||
/**
|
||||
* Called when there is a progress update.
|
||||
*
|
||||
* @param progress the progress in [0.0, 100.0]
|
||||
*/
|
||||
public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
|
||||
@@ -113,14 +112,12 @@ public final class BugreportManager {
|
||||
* out, but the bugreport could be available in the internal directory of dumpstate for
|
||||
* manual retrieval.
|
||||
*
|
||||
* <p> If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the
|
||||
* caller should try later, as only one bugreport can be in progress at a time.
|
||||
* <p>If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the caller
|
||||
* should try later, as only one bugreport can be in progress at a time.
|
||||
*/
|
||||
public void onError(@BugreportErrorCode int errorCode) {}
|
||||
|
||||
/**
|
||||
* Called when taking bugreport finishes successfully.
|
||||
*/
|
||||
/** Called when taking bugreport finishes successfully. */
|
||||
public void onFinished() {}
|
||||
|
||||
/**
|
||||
@@ -137,20 +134,23 @@ public final class BugreportManager {
|
||||
* seconds to return in the worst case. {@code callback} will receive progress and status
|
||||
* updates.
|
||||
*
|
||||
* <p>The bugreport artifacts will be copied over to the given file descriptors only if the
|
||||
* user consents to sharing with the calling app.
|
||||
* <p>The bugreport artifacts will be copied over to the given file descriptors only if the user
|
||||
* consents to sharing with the calling app.
|
||||
*
|
||||
* <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
|
||||
*
|
||||
* @param bugreportFd file to write the bugreport. This should be opened in write-only,
|
||||
* append mode.
|
||||
* @param screenshotFd file to write the screenshot, if necessary. This should be opened
|
||||
* in write-only, append mode.
|
||||
* @param bugreportFd file to write the bugreport. This should be opened in write-only, append
|
||||
* mode.
|
||||
* @param screenshotFd file to write the screenshot, if necessary. This should be opened in
|
||||
* write-only, append mode.
|
||||
* @param params options that specify what kind of a bugreport should be taken
|
||||
* @param callback callback for progress and status updates
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.DUMP)
|
||||
public void startBugreport(@NonNull ParcelFileDescriptor bugreportFd,
|
||||
public void startBugreport(
|
||||
@NonNull ParcelFileDescriptor bugreportFd,
|
||||
@Nullable ParcelFileDescriptor screenshotFd,
|
||||
@NonNull BugreportParams params,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@@ -164,17 +164,21 @@ public final class BugreportManager {
|
||||
boolean isScreenshotRequested = screenshotFd != null;
|
||||
if (screenshotFd == null) {
|
||||
// Binder needs a valid File Descriptor to be passed
|
||||
screenshotFd = ParcelFileDescriptor.open(new File("/dev/null"),
|
||||
ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
screenshotFd =
|
||||
ParcelFileDescriptor.open(
|
||||
new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
|
||||
}
|
||||
DumpstateListener dsListener = new DumpstateListener(executor, callback,
|
||||
isScreenshotRequested);
|
||||
DumpstateListener dsListener =
|
||||
new DumpstateListener(executor, callback, isScreenshotRequested);
|
||||
// Note: mBinder can get callingUid from the binder transaction.
|
||||
mBinder.startBugreport(-1 /* callingUid */,
|
||||
mBinder.startBugreport(
|
||||
-1 /* callingUid */,
|
||||
mContext.getOpPackageName(),
|
||||
bugreportFd.getFileDescriptor(),
|
||||
screenshotFd.getFileDescriptor(),
|
||||
params.getMode(), dsListener, isScreenshotRequested);
|
||||
params.getMode(),
|
||||
dsListener,
|
||||
isScreenshotRequested);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} catch (FileNotFoundException e) {
|
||||
@@ -188,15 +192,61 @@ public final class BugreportManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a connectivity bugreport.
|
||||
*
|
||||
* <p>The connectivity bugreport is a specialized version of bugreport that only includes
|
||||
* information specifically for debugging connectivity-related issues (e.g. telephony, wi-fi,
|
||||
* and IP networking issues). It is intended primarily for use by OEMs and network providers
|
||||
* such as mobile network operators. In addition to generally excluding information that isn't
|
||||
* targeted to connectivity debugging, this type of bugreport excludes PII and sensitive
|
||||
* information that isn't strictly necessary for connectivity debugging.
|
||||
*
|
||||
* <p>The calling app MUST have a context-specific reason for requesting a connectivity
|
||||
* bugreport, such as detecting a connectivity-related issue. This API SHALL NOT be used to
|
||||
* perform random sampling from a fleet of public end-user devices.
|
||||
*
|
||||
* <p>Calling this API will cause the system to ask the user for consent every single time. The
|
||||
* bugreport artifacts will be copied over to the given file descriptors only if the user
|
||||
* consents to sharing with the calling app.
|
||||
*
|
||||
* <p>This starts a bugreport in the background. However the call itself can take several
|
||||
* seconds to return in the worst case. {@code callback} will receive progress and status
|
||||
* updates.
|
||||
*
|
||||
* <p>Requires that the calling app has carrier privileges (see {@link
|
||||
* android.telephony.TelephonyManager#hasCarrierPrivileges}) on any active subscription.
|
||||
*
|
||||
* @param bugreportFd file to write the bugreport. This should be opened in write-only, append
|
||||
* mode.
|
||||
* @param callback callback for progress and status updates.
|
||||
*/
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
public void startConnectivityBugreport(
|
||||
@NonNull ParcelFileDescriptor bugreportFd,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull BugreportCallback callback) {
|
||||
startBugreport(
|
||||
bugreportFd,
|
||||
null /* screenshotFd */,
|
||||
new BugreportParams(BugreportParams.BUGREPORT_MODE_TELEPHONY),
|
||||
executor,
|
||||
callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the currently running bugreport.
|
||||
*
|
||||
* <p>Apps are only able to cancel their own bugreports. App A cannot cancel a bugreport started
|
||||
* by app B.
|
||||
*
|
||||
* <p>Requires permission: {@link android.Manifest.permission#DUMP} or that the calling app has
|
||||
* carrier privileges (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}) on
|
||||
* any active subscription.
|
||||
*
|
||||
* @throws SecurityException if trying to cancel another app's bugreport in progress
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.DUMP)
|
||||
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
|
||||
public void cancelBugreport() {
|
||||
try {
|
||||
mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
|
||||
@@ -209,23 +259,26 @@ public final class BugreportManager {
|
||||
* Requests a bugreport.
|
||||
*
|
||||
* <p>This requests the platform/system to take a bugreport and makes the final bugreport
|
||||
* available to the user. The user may choose to share it with another app, but the bugreport
|
||||
* is never given back directly to the app that requested it.
|
||||
* available to the user. The user may choose to share it with another app, but the bugreport is
|
||||
* never given back directly to the app that requested it.
|
||||
*
|
||||
* @param params {@link BugreportParams} that specify what kind of a bugreport should
|
||||
* be taken, please note that not all kinds of bugreport allow for a
|
||||
* progress notification
|
||||
* @param shareTitle title on the final share notification
|
||||
* @param params {@link BugreportParams} that specify what kind of a bugreport should be taken,
|
||||
* please note that not all kinds of bugreport allow for a progress notification
|
||||
* @param shareTitle title on the final share notification
|
||||
* @param shareDescription description on the final share notification
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.DUMP)
|
||||
public void requestBugreport(@NonNull BugreportParams params, @Nullable CharSequence shareTitle,
|
||||
public void requestBugreport(
|
||||
@NonNull BugreportParams params,
|
||||
@Nullable CharSequence shareTitle,
|
||||
@Nullable CharSequence shareDescription) {
|
||||
try {
|
||||
String title = shareTitle == null ? null : shareTitle.toString();
|
||||
String description = shareDescription == null ? null : shareDescription.toString();
|
||||
ActivityManager.getService().requestBugReportWithDescription(title, description,
|
||||
params.getMode());
|
||||
ActivityManager.getService()
|
||||
.requestBugReportWithDescription(title, description, params.getMode());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -236,8 +289,8 @@ public final class BugreportManager {
|
||||
private final BugreportCallback mCallback;
|
||||
private final boolean mIsScreenshotRequested;
|
||||
|
||||
DumpstateListener(Executor executor, BugreportCallback callback,
|
||||
boolean isScreenshotRequested) {
|
||||
DumpstateListener(
|
||||
Executor executor, BugreportCallback callback, boolean isScreenshotRequested) {
|
||||
mExecutor = executor;
|
||||
mCallback = callback;
|
||||
mIsScreenshotRequested = isScreenshotRequested;
|
||||
@@ -247,9 +300,7 @@ public final class BugreportManager {
|
||||
public void onProgress(int progress) throws RemoteException {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mExecutor.execute(() -> {
|
||||
mCallback.onProgress(progress);
|
||||
});
|
||||
mExecutor.execute(() -> mCallback.onProgress(progress));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
@@ -259,9 +310,7 @@ public final class BugreportManager {
|
||||
public void onError(int errorCode) throws RemoteException {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mExecutor.execute(() -> {
|
||||
mCallback.onError(errorCode);
|
||||
});
|
||||
mExecutor.execute(() -> mCallback.onError(errorCode));
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
@@ -271,9 +320,7 @@ public final class BugreportManager {
|
||||
public void onFinished() throws RemoteException {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mExecutor.execute(() -> {
|
||||
mCallback.onFinished();
|
||||
});
|
||||
mExecutor.execute(() -> mCallback.onFinished());
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
@@ -288,20 +335,19 @@ public final class BugreportManager {
|
||||
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
mainThreadHandler.post(
|
||||
() -> {
|
||||
int message = success ? R.string.bugreport_screenshot_success_toast
|
||||
: R.string.bugreport_screenshot_failure_toast;
|
||||
int message =
|
||||
success
|
||||
? R.string.bugreport_screenshot_success_toast
|
||||
: R.string.bugreport_screenshot_failure_toast;
|
||||
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUiIntensiveBugreportDumpsFinished()
|
||||
throws RemoteException {
|
||||
public void onUiIntensiveBugreportDumpsFinished() throws RemoteException {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mExecutor.execute(() -> {
|
||||
mCallback.onEarlyReportFinished();
|
||||
});
|
||||
mExecutor.execute(() -> mCallback.onEarlyReportFinished());
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.annotation.RequiresPermission;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Binder;
|
||||
import android.os.BugreportParams;
|
||||
@@ -31,6 +32,7 @@ import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -53,11 +55,13 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
|
||||
private final Object mLock = new Object();
|
||||
private final Context mContext;
|
||||
private final AppOpsManager mAppOps;
|
||||
private final TelephonyManager mTelephonyManager;
|
||||
private final ArraySet<String> mBugreportWhitelistedPackages;
|
||||
|
||||
BugreportManagerServiceImpl(Context context) {
|
||||
mContext = context;
|
||||
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||
mAppOps = context.getSystemService(AppOpsManager.class);
|
||||
mTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
mBugreportWhitelistedPackages =
|
||||
SystemConfig.getInstance().getBugreportWhitelistedPackages();
|
||||
}
|
||||
@@ -67,11 +71,14 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
|
||||
public void startBugreport(int callingUidUnused, String callingPackage,
|
||||
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
|
||||
int bugreportMode, IDumpstateListener listener, boolean isScreenshotRequested) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "startBugreport");
|
||||
Objects.requireNonNull(callingPackage);
|
||||
Objects.requireNonNull(bugreportFd);
|
||||
Objects.requireNonNull(listener);
|
||||
validateBugreportMode(bugreportMode);
|
||||
|
||||
int callingUid = Binder.getCallingUid();
|
||||
enforcePermission(callingPackage, callingUid, bugreportMode
|
||||
== BugreportParams.BUGREPORT_MODE_TELEPHONY /* checkCarrierPrivileges */);
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
ensureIsPrimaryUser();
|
||||
@@ -79,13 +86,6 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
int callingUid = Binder.getCallingUid();
|
||||
mAppOps.checkPackage(callingUid, callingPackage);
|
||||
|
||||
if (!mBugreportWhitelistedPackages.contains(callingPackage)) {
|
||||
throw new SecurityException(
|
||||
callingPackage + " is not whitelisted to use Bugreport API");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
startBugreportLocked(callingUid, callingPackage, bugreportFd, screenshotFd,
|
||||
bugreportMode, listener, isScreenshotRequested);
|
||||
@@ -93,12 +93,10 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
@RequiresPermission(android.Manifest.permission.DUMP)
|
||||
@RequiresPermission(android.Manifest.permission.DUMP) // or carrier privileges
|
||||
public void cancelBugreport(int callingUidUnused, String callingPackage) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
|
||||
"cancelBugreport");
|
||||
int callingUid = Binder.getCallingUid();
|
||||
mAppOps.checkPackage(callingUid, callingPackage);
|
||||
enforcePermission(callingPackage, callingUid, true /* checkCarrierPrivileges */);
|
||||
|
||||
synchronized (mLock) {
|
||||
IDumpstate ds = getDumpstateBinderServiceLocked();
|
||||
@@ -134,6 +132,34 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
private void enforcePermission(
|
||||
String callingPackage, int callingUid, boolean checkCarrierPrivileges) {
|
||||
mAppOps.checkPackage(callingUid, callingPackage);
|
||||
|
||||
// To gain access through the DUMP permission, the OEM has to allow this package explicitly
|
||||
// via sysconfig and privileged permissions.
|
||||
if (mBugreportWhitelistedPackages.contains(callingPackage)
|
||||
&& 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.
|
||||
if (checkCarrierPrivileges
|
||||
&& mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
|
||||
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message =
|
||||
callingPackage
|
||||
+ " does not hold the DUMP permission or is not bugreport-whitelisted "
|
||||
+ (checkCarrierPrivileges ? "and does not have carrier privileges " : "")
|
||||
+ "to request a bugreport";
|
||||
Slog.w(TAG, message);
|
||||
throw new SecurityException(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the current user is the primary user.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user