blob: cbb3909a55368d2e9d3a81d5b0423926cd63b1e5 [file] [log] [blame]
Nandana Dutt3386fb72018-12-12 17:26:57 +00001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.os;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.annotation.Nullable;
22import android.annotation.RequiresPermission;
23import android.annotation.SystemService;
24import android.content.Context;
25import android.os.IBinder.DeathRecipient;
26
27import java.io.FileDescriptor;
28import java.lang.annotation.Retention;
29import java.lang.annotation.RetentionPolicy;
30
31/**
32 * Class that provides a privileged API to capture and consume bugreports.
33 *
34 * @hide
35 */
36// TODO: Expose API when the implementation is more complete.
37// @SystemApi
38@SystemService(Context.BUGREPORT_SERVICE)
39public class BugreportManager {
40 private final Context mContext;
41 private final IDumpstate mBinder;
42
43 /** @hide */
44 public BugreportManager(@NonNull Context context, IDumpstate binder) {
45 mContext = context;
46 mBinder = binder;
47 }
48
49 /**
50 * An interface describing the listener for bugreport progress and status.
51 */
52 public interface BugreportListener {
53 /**
54 * Called when there is a progress update.
55 * @param progress the progress in [0.0, 100.0]
56 */
57 void onProgress(float progress);
58
59 @Retention(RetentionPolicy.SOURCE)
60 @IntDef(prefix = { "BUGREPORT_ERROR_" }, value = {
61 BUGREPORT_ERROR_INVALID_INPUT,
62 BUGREPORT_ERROR_RUNTIME
63 })
64
65 /** Possible error codes taking a bugreport can encounter */
66 @interface BugreportErrorCode {}
67
68 /** The input options were invalid */
69 int BUGREPORT_ERROR_INVALID_INPUT = 1;
70
71 /** A runtime error occured */
72 int BUGREPORT_ERROR_RUNTIME = 2;
73
74 /**
75 * Called when taking bugreport resulted in an error.
76 *
77 * @param errorCode the error that occurred. Possible values are
78 * {@code BUGREPORT_ERROR_INVALID_INPUT}, {@code BUGREPORT_ERROR_RUNTIME}.
79 */
80 void onError(@BugreportErrorCode int errorCode);
81
82 /**
83 * Called when taking bugreport finishes successfully
84 *
85 * @param durationMs time capturing bugreport took in milliseconds
86 * @param title title for the bugreport; helpful in reminding the user why they took it
87 * @param description detailed description for the bugreport
88 */
89 void onFinished(long durationMs, @NonNull String title,
90 @NonNull String description);
91 }
92
93 /**
94 * Starts a bugreport asynchronously.
95 *
96 * @param bugreportFd file to write the bugreport. This should be opened in write-only,
97 * append mode.
98 * @param screenshotFd file to write the screenshot, if necessary. This should be opened
99 * in write-only, append mode.
100 * @param params options that specify what kind of a bugreport should be taken
101 * @param listener callback for progress and status updates
102 */
103 @RequiresPermission(android.Manifest.permission.DUMP)
104 public void startBugreport(@NonNull FileDescriptor bugreportFd,
105 @Nullable FileDescriptor screenshotFd,
106 @NonNull BugreportParams params, @Nullable BugreportListener listener) {
107 // TODO(b/111441001): Enforce android.Manifest.permission.DUMP if necessary.
108 DumpstateListener dsListener = new DumpstateListener(listener);
109
110 try {
111 mBinder.startBugreport(bugreportFd, screenshotFd, params.getMode(), dsListener);
112 } catch (RemoteException e) {
113 throw e.rethrowFromSystemServer();
114 }
115 }
116
Nandana Dutt3386fb72018-12-12 17:26:57 +0000117 private final class DumpstateListener extends IDumpstateListener.Stub
118 implements DeathRecipient {
119 private final BugreportListener mListener;
120
121 DumpstateListener(@Nullable BugreportListener listener) {
122 mListener = listener;
123 }
124
125 @Override
126 public void binderDied() {
127 // TODO(b/111441001): implement
128 }
129
130 @Override
Nandana Dutt432f8c72019-01-14 17:39:13 +0000131 public void onProgress(int progress) throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000132 mListener.onProgress(progress);
Nandana Dutt432f8c72019-01-14 17:39:13 +0000133 }
134
135 @Override
136 public void onError(int errorCode) throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000137 mListener.onError(errorCode);
Nandana Dutt432f8c72019-01-14 17:39:13 +0000138 }
139
140 @Override
141 public void onFinished(long durationMs, String title, String description)
142 throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000143 mListener.onFinished(durationMs, title, description);
Nandana Dutt432f8c72019-01-14 17:39:13 +0000144 }
145
146 // Old methods; should go away
147 @Override
Nandana Dutt3386fb72018-12-12 17:26:57 +0000148 public void onProgressUpdated(int progress) throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000149 // TODO(b/111441001): remove from interface
Nandana Dutt3386fb72018-12-12 17:26:57 +0000150 }
151
152 @Override
153 public void onMaxProgressUpdated(int maxProgress) throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000154 // TODO(b/111441001): remove from interface
Nandana Dutt3386fb72018-12-12 17:26:57 +0000155 }
156
157 @Override
158 public void onSectionComplete(String title, int status, int size, int durationMs)
159 throws RemoteException {
Nandana Duttc8c77bc2019-01-15 12:48:12 +0000160 // TODO(b/111441001): remove from interface
Nandana Dutt3386fb72018-12-12 17:26:57 +0000161 }
162 }
163}