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

Commit 0dcbf784 authored by Nandana Dutt's avatar Nandana Dutt Committed by android-build-merger
Browse files

Merge "Follow API guidelines in BugreportManager"

am: 37aee80c

Change-Id: I2bb33876a9318cc347600726e9277cf71db9c75d
parents 62e8b4eb 37aee80c
Loading
Loading
Loading
Loading
+62 −37
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.os;
package android.os;


import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -27,6 +28,7 @@ import android.os.IBinder.DeathRecipient;
import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;


/**
/**
 * Class that provides a privileged API to capture and consume bugreports.
 * Class that provides a privileged API to capture and consume bugreports.
@@ -47,47 +49,46 @@ public class BugreportManager {
    }
    }


    /**
    /**
     * An interface describing the listener for bugreport progress and status.
     * An interface describing the callback for bugreport progress and status.
     */
     */
    public interface BugreportListener {
    public abstract static class BugreportCallback {
        /**
        /** @hide */
         * Called when there is a progress update.
         * @param progress the progress in [0.0, 100.0]
         */
        void onProgress(float progress);

        @Retention(RetentionPolicy.SOURCE)
        @Retention(RetentionPolicy.SOURCE)
        @IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
        @IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
                BUGREPORT_ERROR_INVALID_INPUT,
                BUGREPORT_ERROR_INVALID_INPUT,
                BUGREPORT_ERROR_RUNTIME
                BUGREPORT_ERROR_RUNTIME,
                BUGREPORT_ERROR_USER_DENIED_CONSENT,
                BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT
        })
        })


        /** Possible error codes taking a bugreport can encounter */
        /** Possible error codes taking a bugreport can encounter */
        @interface BugreportErrorCode {}
        public @interface BugreportErrorCode {}


        /** The input options were invalid */
        /** The input options were invalid */
        int BUGREPORT_ERROR_INVALID_INPUT = IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;
        public static final int BUGREPORT_ERROR_INVALID_INPUT =
                IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT;


        /** A runtime error occured */
        /** A runtime error occured */
        int BUGREPORT_ERROR_RUNTIME = IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;
        public static final int BUGREPORT_ERROR_RUNTIME =
                IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR;


        /** User denied consent to share the bugreport */
        /** User denied consent to share the bugreport */
        int BUGREPORT_ERROR_USER_DENIED_CONSENT =
        public static final int BUGREPORT_ERROR_USER_DENIED_CONSENT =
                IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT;
                IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT;


        /** The request to get user consent timed out. */
        /** The request to get user consent timed out. */
        int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT =
        public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT =
                IDumpstateListener.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT;
                IDumpstateListener.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT;


        /**
         * Called when there is a progress update.
         * @param progress the progress in [0.0, 100.0]
         */
        public void onProgress(float progress) {}

        /**
        /**
         * Called when taking bugreport resulted in an error.
         * Called when taking bugreport resulted in an error.
         *
         *
         * @param errorCode the error that occurred. Possible values are
         *     {@code BUGREPORT_ERROR_INVALID_INPUT},
         *     {@code BUGREPORT_ERROR_RUNTIME},
         *     {@code BUGREPORT_ERROR_USER_DENIED_CONSENT},
         *     {@code BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT}.
         *
         * <p>If {@code BUGREPORT_ERROR_USER_DENIED_CONSENT} is passed, then the user did not
         * <p>If {@code BUGREPORT_ERROR_USER_DENIED_CONSENT} is passed, then the user did not
         * consent to sharing the bugreport with the calling app.
         * consent to sharing the bugreport with the calling app.
         *
         *
@@ -95,19 +96,19 @@ public class BugreportManager {
         * out, but the bugreport could be available in the internal directory of dumpstate for
         * out, but the bugreport could be available in the internal directory of dumpstate for
         * manual retrieval.
         * manual retrieval.
         */
         */
        void onError(@BugreportErrorCode int errorCode);
        public void onError(@BugreportErrorCode int errorCode) {}


        /**
        /**
         * Called when taking bugreport finishes successfully.
         * Called when taking bugreport finishes successfully.
         */
         */
        void onFinished();
        public void onFinished() {}
    }
    }


    /**
    /**
     * Starts a bugreport.
     * Starts a bugreport.
     *
     *
     * <p>This starts a bugreport in the background. However the call itself can take several
     * <p>This starts a bugreport in the background. However the call itself can take several
     * seconds to return in the worst case. {@code listener} will receive progress and status
     * seconds to return in the worst case. {@code callback} will receive progress and status
     * updates.
     * updates.
     *
     *
     * <p>The bugreport artifacts will be copied over to the given file descriptors only if the
     * <p>The bugreport artifacts will be copied over to the given file descriptors only if the
@@ -118,19 +119,23 @@ public class BugreportManager {
     * @param screenshotFd file to write the screenshot, if necessary. This should be opened
     * @param screenshotFd file to write the screenshot, if necessary. This should be opened
     *     in write-only, append mode.
     *     in write-only, append mode.
     * @param params options that specify what kind of a bugreport should be taken
     * @param params options that specify what kind of a bugreport should be taken
     * @param listener callback for progress and status updates
     * @param callback callback for progress and status updates
     */
     */
    @RequiresPermission(android.Manifest.permission.DUMP)
    @RequiresPermission(android.Manifest.permission.DUMP)
    public void startBugreport(@NonNull FileDescriptor bugreportFd,
    public void startBugreport(@NonNull ParcelFileDescriptor bugreportFd,
            @Nullable FileDescriptor screenshotFd,
            @Nullable ParcelFileDescriptor screenshotFd,
            @NonNull BugreportParams params, @NonNull BugreportListener listener) {
            @NonNull BugreportParams params,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull BugreportCallback callback) {
        // TODO(b/111441001): Enforce android.Manifest.permission.DUMP if necessary.
        // TODO(b/111441001): Enforce android.Manifest.permission.DUMP if necessary.
        DumpstateListener dsListener = new DumpstateListener(listener);
        DumpstateListener dsListener = new DumpstateListener(executor, callback);

        try {
        try {
            // Note: mBinder can get callingUid from the binder transaction.
            // Note: mBinder can get callingUid from the binder transaction.
            mBinder.startBugreport(-1 /* callingUid */,
            mBinder.startBugreport(-1 /* callingUid */,
                    mContext.getOpPackageName(), bugreportFd, screenshotFd,
                    mContext.getOpPackageName(),
                    (bugreportFd != null ? bugreportFd.getFileDescriptor() : new FileDescriptor()),
                    (screenshotFd != null
                            ? screenshotFd.getFileDescriptor() : new FileDescriptor()),
                    params.getMode(), dsListener);
                    params.getMode(), dsListener);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
@@ -151,10 +156,12 @@ public class BugreportManager {


    private final class DumpstateListener extends IDumpstateListener.Stub
    private final class DumpstateListener extends IDumpstateListener.Stub
            implements DeathRecipient {
            implements DeathRecipient {
        private final BugreportListener mListener;
        private final Executor mExecutor;
        private final BugreportCallback mCallback;


        DumpstateListener(@Nullable BugreportListener listener) {
        DumpstateListener(Executor executor, @Nullable BugreportCallback callback) {
            mListener = listener;
            mExecutor = executor;
            mCallback = callback;
        }
        }


        @Override
        @Override
@@ -164,19 +171,37 @@ public class BugreportManager {


        @Override
        @Override
        public void onProgress(int progress) throws RemoteException {
        public void onProgress(int progress) throws RemoteException {
            mListener.onProgress(progress);
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> {
                    mCallback.onProgress(progress);
                });
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
        }


        @Override
        @Override
        public void onError(int errorCode) throws RemoteException {
        public void onError(int errorCode) throws RemoteException {
            mListener.onError(errorCode);
            final long identity = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> {
                    mCallback.onError(errorCode);
                });
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
        }


        @Override
        @Override
        public void onFinished() throws RemoteException {
        public void onFinished() throws RemoteException {
            final long identity = Binder.clearCallingIdentity();
            try {
            try {
                mListener.onFinished();
                mExecutor.execute(() -> {
                    mCallback.onFinished();
                });
            } finally {
            } finally {
                Binder.restoreCallingIdentity(identity);
                // The bugreport has finished. Let's shutdown the service to minimize its footprint.
                // The bugreport has finished. Let's shutdown the service to minimize its footprint.
                cancelBugreport();
                cancelBugreport();
            }
            }