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

Commit 34fb4ac1 authored by Gavin Corkery's avatar Gavin Corkery Committed by Android (Google) Code Review
Browse files

Merge "Add retrieveBugreport API"

parents e845c142 dc452e08
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -32138,9 +32138,11 @@ package android.os {
    method public void onEarlyReportFinished();
    method public void onError(int);
    method public void onFinished();
    method public void onFinished(@NonNull String);
    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_NO_BUGREPORT_TO_RETRIEVE = 6; // 0x6
    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
+2 −0
Original line number Diff line number Diff line
@@ -9934,6 +9934,7 @@ package android.os {
  public final class BugreportManager {
    method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void preDumpUiData();
    method @RequiresPermission(android.Manifest.permission.DUMP) public void requestBugreport(@NonNull android.os.BugreportParams, @Nullable CharSequence, @Nullable CharSequence);
    method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread public void retrieveBugreport(@NonNull String, @NonNull android.os.ParcelFileDescriptor, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
    method @RequiresPermission(android.Manifest.permission.DUMP) @WorkerThread 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);
  }
@@ -9942,6 +9943,7 @@ package android.os {
    ctor public BugreportParams(int, int);
    method public int getFlags();
    method public int getMode();
    field public static final int BUGREPORT_FLAG_DEFER_CONSENT = 2; // 0x2
    field public static final int BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA = 1; // 0x1
    field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
    field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
+98 −10
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.os;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FloatRange;
import android.annotation.IntDef;
@@ -69,7 +70,10 @@ public final class BugreportManager {
     * An interface describing the callback for bugreport progress and status.
     *
     * <p>Callers will receive {@link #onProgress} calls as the bugreport progresses, followed by a
     * terminal call to either {@link #onFinished} or {@link #onError}.
     * terminal call to either {@link #onFinished} or {@link #onError}. Note that
     * {@link #onFinished(String)} will only be invoked when calling {@code startBugreport} with the
     * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} flag set. Otherwise,
     * {@link #onFinished()} will be invoked.
     *
     * <p>If an issue is encountered while starting the bugreport asynchronously, callers will
     * receive an {@link #onError} call without any {@link #onProgress} callbacks.
@@ -88,7 +92,8 @@ public final class BugreportManager {
                    BUGREPORT_ERROR_RUNTIME,
                    BUGREPORT_ERROR_USER_DENIED_CONSENT,
                    BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
                    BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
                    BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS,
                    BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE
                })
        public @interface BugreportErrorCode {}

@@ -115,6 +120,10 @@ public final class BugreportManager {
        public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS =
                IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS;

        /** There is no bugreport to retrieve for the caller. */
        public static final int BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE =
                IDumpstateListener.BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE;

        /**
         * Called when there is a progress update.
         *
@@ -137,9 +146,25 @@ public final class BugreportManager {
         */
        public void onError(@BugreportErrorCode int errorCode) {}

        /** Called when taking bugreport finishes successfully. */
        /** Called when taking bugreport finishes successfully.
         *
         * <p>This callback will be invoked if the
         * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} flag is not set. Otherwise, the
         * {@link #onFinished(String)} callback will be invoked.
         */
        public void onFinished() {}

        /** Called when taking bugreport finishes successfully.
         *
         * <p>This callback will only be invoked if the
         * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} flag is set. Otherwise, the
         * {@link #onFinished()} callback will be invoked.
         *
         * @param bugreportFile the absolute path of the generated bugreport file.

         */
        public void onFinished(@NonNull String bugreportFile) {}

        /**
         * Called when it is ready for calling app to show UI, showing any extra UI before this
         * callback can interfere with bugreport generation.
@@ -178,7 +203,9 @@ public final class BugreportManager {
     * 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.
     * consents to sharing with the calling app. If
     * {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT} is set, user consent will be deferred
     * and no files will be copied to the given file descriptors.
     *
     * <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
     *
@@ -205,7 +232,9 @@ public final class BugreportManager {
            Preconditions.checkNotNull(executor);
            Preconditions.checkNotNull(callback);

            boolean isScreenshotRequested = screenshotFd != null;
            boolean deferConsent =
                    (params.getFlags() & BugreportParams.BUGREPORT_FLAG_DEFER_CONSENT) != 0;
            boolean isScreenshotRequested = screenshotFd != null || deferConsent;
            if (screenshotFd == null) {
                // Binder needs a valid File Descriptor to be passed
                screenshotFd =
@@ -213,7 +242,7 @@ public final class BugreportManager {
                                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
            }
            DumpstateListener dsListener =
                    new DumpstateListener(executor, callback, isScreenshotRequested);
                    new DumpstateListener(executor, callback, isScreenshotRequested, deferConsent);
            // Note: mBinder can get callingUid from the binder transaction.
            mBinder.startBugreport(
                    -1 /* callingUid */,
@@ -237,6 +266,58 @@ public final class BugreportManager {
        }
    }

    /**
     * Retrieves a previously generated bugreport.
     *
     * <p>The previously generated bugreport must have been generated by calling {@link
     * #startBugreport(ParcelFileDescriptor, ParcelFileDescriptor, BugreportParams,
     * Executor, BugreportCallback)} with the {@link BugreportParams#BUGREPORT_FLAG_DEFER_CONSENT}
     * flag set. The bugreport file returned by the {@link BugreportCallback#onFinished(String)}
     * callback for a previously generated bugreport must be passed to this method. A caller may
     * only retrieve bugreports that they have previously requested.
     *
     * <p>The bugreport artifacts will be copied over to the given file descriptor only if the user
     * consents to sharing with the calling app.
     *
     * <p>{@link BugreportManager} takes ownership of {@code bugreportFd} and {@code screenshotFd}.
     *
     * <p>The caller may only request to retrieve a given bugreport once. Subsequent calls will fail
     * with error code {@link BugreportCallback#BUGREPORT_ERROR_NO_BUGREPORT_TO_RETRIEVE}.
     *
     * @param bugreportFile the identifier for a bugreport that was previously generated for this
     *      caller using {@code startBugreport}.
     * @param bugreportFd file to copy over the previous bugreport. This should be opened in
     *      write-only, append mode.
     * @param executor the executor to execute callback methods.
     * @param callback callback for progress and status updates.
     * @hide
     */
    @SystemApi
    @RequiresPermission(Manifest.permission.DUMP)
    @WorkerThread
    public void retrieveBugreport(
            @NonNull String bugreportFile,
            @NonNull ParcelFileDescriptor bugreportFd,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull BugreportCallback callback
    ) {
        try {
            Preconditions.checkNotNull(bugreportFile);
            Preconditions.checkNotNull(bugreportFd);
            Preconditions.checkNotNull(executor);
            Preconditions.checkNotNull(callback);
            DumpstateListener dsListener = new DumpstateListener(executor, callback, false, false);
            mBinder.retrieveBugreport(Binder.getCallingUid(), mContext.getOpPackageName(),
                    bugreportFd.getFileDescriptor(),
                    bugreportFile,
                    dsListener);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } finally {
            IoUtils.closeQuietly(bugreportFd);
        }
    }

    /**
     * Starts a connectivity bugreport.
     *
@@ -316,7 +397,7 @@ public final class BugreportManager {
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.DUMP)
    @RequiresPermission(Manifest.permission.DUMP)
    public void requestBugreport(
            @NonNull BugreportParams params,
            @Nullable CharSequence shareTitle,
@@ -335,12 +416,15 @@ public final class BugreportManager {
        private final Executor mExecutor;
        private final BugreportCallback mCallback;
        private final boolean mIsScreenshotRequested;
        private final boolean mIsConsentDeferred;

        DumpstateListener(
                Executor executor, BugreportCallback callback, boolean isScreenshotRequested) {
                Executor executor, BugreportCallback callback, boolean isScreenshotRequested,
                boolean isConsentDeferred) {
            mExecutor = executor;
            mCallback = callback;
            mIsScreenshotRequested = isScreenshotRequested;
            mIsConsentDeferred = isConsentDeferred;
        }

        @Override
@@ -364,10 +448,14 @@ public final class BugreportManager {
        }

        @Override
        public void onFinished() throws RemoteException {
        public void onFinished(String bugreportFile) throws RemoteException {
            final long identity = Binder.clearCallingIdentity();
            try {
                if (mIsConsentDeferred) {
                    mExecutor.execute(() -> mCallback.onFinished(bugreportFile));
                } else {
                    mExecutor.execute(() -> mCallback.onFinished());
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
+13 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.SystemApi;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;

/**
 * Parameters that specify what kind of bugreport should be taken.
@@ -125,7 +126,8 @@ public final class BugreportParams {
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "BUGREPORT_FLAG_" }, value = {
            BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA
            BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA,
            BUGREPORT_FLAG_DEFER_CONSENT
    })
    public @interface BugreportFlag {}

@@ -135,4 +137,14 @@ public final class BugreportParams {
     */
    public static final int BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA =
            IDumpstate.BUGREPORT_FLAG_USE_PREDUMPED_UI_DATA;

    /**
     * Flag for deferring user consent.
     *
     * <p>This flag should be used in cases where it may not be possible for the user to respond
     * to a consent dialog immediately, such as when the user is driving. The generated bugreport
     * may be retrieved at a later time using {@link BugreportManager#retrieveBugreport(
     * String, ParcelFileDescriptor, Executor, BugreportManager.BugreportCallback)}.
     */
    public static final int BUGREPORT_FLAG_DEFER_CONSENT = IDumpstate.BUGREPORT_FLAG_DEFER_CONSENT;
}
+1 −1
Original line number Diff line number Diff line
@@ -677,7 +677,7 @@ public class BugreportReceiverTest {
        if (mScreenshotFd != null) {
            writeScreenshotFile(mScreenshotFd, SCREENSHOT_CONTENT);
        }
        mIDumpstateListener.onFinished();
        mIDumpstateListener.onFinished("");
        getInstrumentation().waitForIdleSync();
    }

Loading