通过设备获取bugreport
通过命令获取bugreport
debug$ adb bugreport bugreport.zip
/data/user_de/0/com.android.shell/files/bugreports/bugrep...le pulled, 0 skipped. 29.6 MB/s (8659982 bytes in 0.279s)
Bug report copied to bugreport.zip
ChkBugReport
UML
源码
Settings
public class BugreportPreference extends CustomDialogPreferenceCompat {
@Override
protected void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
final Context context = getContext();
if (mFullTitle.isChecked()) {
Log.v(TAG, "Taking full bugreport right away");
FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
SettingsEnums.ACTION_BUGREPORT_FROM_SETTINGS_FULL);
try {
ActivityManager.getService().requestFullBugReport(); // 完整报告
} catch (RemoteException e) {
Log.e(TAG, "error taking bugreport (bugreportType=Full)", e);
}
} else {
Log.v(TAG, "Taking interactive bugreport right away");
FeatureFactory.getFactory(context).getMetricsFeatureProvider().action(context,
SettingsEnums.ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE);
try {
ActivityManager.getService().requestInteractiveBugReport(); // 互动式报告
} catch (RemoteException e) {
Log.e(TAG, "error taking bugreport (bugreportType=Interactive)", e);
}
}
}
}
}
AMS
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
private static final String INTENT_BUGREPORT_REQUESTED =
"com.android.internal.intent.action.BUGREPORT_REQUESTED";
private static final String SHELL_APP_PACKAGE = "com.android.shell";
/**
* Takes a bugreport using bug report API ({@code BugreportManager}) with no pre-set
* title and description
*/
@Override
public void requestBugReport(@BugreportParams.BugreportMode int bugreportType) {
requestBugReportWithDescription(null, null, bugreportType);
}
/**
* Takes a bugreport using bug report API ({@code BugreportManager}) which gets
* triggered by sending a broadcast to Shell.
*/
@Override
public void requestBugReportWithDescription(@Nullable String shareTitle,
@Nullable String shareDescription, int bugreportType) {
String type = null;
switch (bugreportType) {
case BugreportParams.BUGREPORT_MODE_FULL: // 完整错误报告
type = "bugreportfull";
break;
case BugreportParams.BUGREPORT_MODE_INTERACTIVE: // 交互式错误报告
type = "bugreportplus";
break;
case BugreportParams.BUGREPORT_MODE_REMOTE: // 远程错误报告
type = "bugreportremote";
break;
case BugreportParams.BUGREPORT_MODE_WEAR: // 穿戴设备
type = "bugreportwear";
break;
case BugreportParams.BUGREPORT_MODE_TELEPHONY: // 电话相关报告
type = "bugreporttelephony";
break;
case BugreportParams.BUGREPORT_MODE_WIFI: // Wifi相关的错误报告
type = "bugreportwifi";
break;
default:
throw new IllegalArgumentException(
"Provided bugreport type is not correct, value: "
+ bugreportType);
}
// Always log caller, even if it does not have permission to dump.
Slog.i(TAG, type + " requested by UID " + Binder.getCallingUid());
enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
if (!TextUtils.isEmpty(shareTitle)) {
if (shareTitle.length() > MAX_BUGREPORT_TITLE_SIZE) {
String errorStr = "shareTitle should be less than "
+ MAX_BUGREPORT_TITLE_SIZE + " characters";
throw new IllegalArgumentException(errorStr);
}
if (!TextUtils.isEmpty(shareDescription)) {
if (shareDescription.length() > MAX_BUGREPORT_DESCRIPTION_SIZE) {
String errorStr = "shareDescription should be less than "
+ MAX_BUGREPORT_DESCRIPTION_SIZE + " characters";
throw new IllegalArgumentException(errorStr);
}
}
Slog.d(TAG, "Bugreport notification title " + shareTitle
+ " description " + shareDescription);
}
// Create intent to trigger Bugreport API via Shell
Intent triggerShellBugreport = new Intent();
triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED);
triggerShellBugreport.setPackage(SHELL_APP_PACKAGE);
triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType);
triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
if (shareTitle != null) {
triggerShellBugreport.putExtra(EXTRA_TITLE, shareTitle);
}
if (shareDescription != null) {
triggerShellBugreport.putExtra(EXTRA_DESCRIPTION, shareDescription);
}
final long identity = Binder.clearCallingIdentity();
try {
// Send broadcast to shell to trigger bugreport using Bugreport API
mContext.sendBroadcast(triggerShellBugreport); // 发送广播给com.android.shell进程
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
* Takes a telephony bugreport with title and description
*/
@Override
public void requestTelephonyBugReport(String shareTitle, String shareDescription) {
requestBugReportWithDescription(shareTitle, shareDescription,
BugreportParams.BUGREPORT_MODE_TELEPHONY);
}
/**
* Takes a minimal bugreport of Wifi-related state with pre-set title and description
*/
@Override
public void requestWifiBugReport(String shareTitle, String shareDescription) {
requestBugReportWithDescription(shareTitle, shareDescription,
BugreportParams.BUGREPORT_MODE_WIFI);
}
/**
* Takes an interactive bugreport with a progress notification
*/
@Override
public void requestInteractiveBugReport() {
requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_INTERACTIVE);
}
/**
* Takes an interactive bugreport with a progress notification. Also, shows the given title and
* description on the final share notification
*/
@Override
public void requestInteractiveBugReportWithDescription(String shareTitle,
String shareDescription) {
requestBugReportWithDescription(shareTitle, shareDescription,
BugreportParams.BUGREPORT_MODE_INTERACTIVE);
}
/**
* Takes a bugreport with minimal user interference
*/
@Override
public void requestFullBugReport() {
requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_FULL);
}
/**
* Takes a bugreport remotely
*/
@Override
public void requestRemoteBugReport() {
requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_REMOTE);
}
}
Shell
AndroidManifest.xml
<receiver
android:name=".BugreportRequestedReceiver"
android:permission="android.permission.TRIGGER_SHELL_BUGREPORT">
<intent-filter>
<action android:name="com.android.internal.intent.action.BUGREPORT_REQUESTED" />
</intent-filter>
</receiver>
BugreportRequestedReceiver.java
public class BugreportRequestedReceiver extends BroadcastReceiver {
private static final String TAG = "BugreportRequestedReceiver";
@Override
@RequiresPermission(android.Manifest.permission.TRIGGER_SHELL_BUGREPORT)
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive(): " + dumpIntent(intent));
// Delegate intent handling to service.
Intent serviceIntent = new Intent(context, BugreportProgressService.class);
Log.d(TAG, "onReceive() ACTION: " + serviceIntent.getAction());
serviceIntent.setAction(intent.getAction());
serviceIntent.putExtra(EXTRA_ORIGINAL_INTENT, intent);
context.startService(serviceIntent);
}
}
BugreportProgressService.java
public class BugreportProgressService extends Service {
@Override
public void onCreate() {
mContext = getApplicationContext();
mMainThreadHandler = new Handler(Looper.getMainLooper());
mServiceHandler = new ServiceHandler("BugreportProgressServiceMainThread");
mScreenshotHandler = new ScreenshotHandler("BugreportProgressServiceScreenshotThread");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "onStartCommand(): " + dumpIntent(intent));
if (intent != null) {
if (!intent.hasExtra(EXTRA_ORIGINAL_INTENT) && !intent.hasExtra(EXTRA_ID)) {
return START_NOT_STICKY;
}
// Handle it in a separate thread.
final Message msg = mServiceHandler.obtainMessage();
msg.what = MSG_SERVICE_COMMAND;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
// If service is killed it cannot be recreated because it would not know which
// dumpstate IDs it would have to watch.
return START_NOT_STICKY;
}
private final class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (action) {
case INTENT_BUGREPORT_REQUESTED:
startBugreportAPI(intent);
break;
}
}
}
private void startBugreportAPI(Intent intent) {
BugreportInfo info = new BugreportInfo(mContext, baseName, name,
shareTitle, shareDescription, bugreportType, mBugreportsDir);
ParcelFileDescriptor bugreportFd = info.getBugreportFd();
mBugreportManager = (BugreportManager) mContext.getSystemService(
Context.BUGREPORT_SERVICE);
final Executor executor = ActivityThread.currentActivityThread().getExecutor();
Log.i(TAG, "bugreport type = " + bugreportType
+ " bugreport file fd: " + bugreportFd
+ " screenshot file fd: " + screenshotFd);
BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(info);
try {
synchronized (mLock) {
mBugreportManager.startBugreport(bugreportFd, screenshotFd,
new BugreportParams(bugreportType), executor, bugreportCallback);
bugreportCallback.trackInfoWithIdLocked();
}
} catch (RuntimeException e) {
Log.i(TAG, "Error in generating bugreports: ", e);
// The binder call didn't go through successfully, so need to close the fds.
// If the calls went through API takes ownership.
FileUtils.closeQuietly(bugreportFd);
if (screenshotFd != null) {
FileUtils.closeQuietly(screenshotFd);
}
}
}
}
BugreportManagerService.java
public final class BugreportManager {
private final IDumpstate mBinder;
public BugreportManager(@NonNull Context context, IDumpstate binder) {
mContext = context;
mBinder = binder;
}
@RequiresPermission(android.Manifest.permission.DUMP)
public void startBugreport(@NonNull ParcelFileDescriptor bugreportFd,
@Nullable ParcelFileDescriptor screenshotFd,
@NonNull BugreportParams params,
@NonNull @CallbackExecutor Executor executor,
@NonNull BugreportCallback callback) {
try {
Preconditions.checkNotNull(bugreportFd);
Preconditions.checkNotNull(params);
Preconditions.checkNotNull(executor);
Preconditions.checkNotNull(callback);
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);
}
DumpstateListener dsListener = new DumpstateListener(executor, callback,
isScreenshotRequested);
// Note: mBinder can get callingUid from the binder transaction.
mBinder.startBugreport(-1 /* callingUid */,
mContext.getOpPackageName(),
bugreportFd.getFileDescriptor(),
screenshotFd.getFileDescriptor(),
params.getMode(), dsListener, isScreenshotRequested);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (FileNotFoundException e) {
Log.wtf(TAG, "Not able to find /dev/null file: ", e);
} finally {
// We can close the file descriptors here because binder would have duped them.
IoUtils.closeQuietly(bugreportFd);
if (screenshotFd != null) {
IoUtils.closeQuietly(screenshotFd);
}
}
}
}
// 系统服务
public class BugreportManagerService extends SystemService {
private static final String TAG = "BugreportManagerService";
private BugreportManagerServiceImpl mService;
public BugreportManagerService(Context context) {
super(context);
}
@Override
public void onStart() {
mService = new BugreportManagerServiceImpl(getContext());
publishBinderService(Context.BUGREPORT_SERVICE, mService); // bugreport service
}
}
class BugreportManagerServiceImpl extends IDumpstate.Stub {
@Override
@RequiresPermission(android.Manifest.permission.DUMP)
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);
final long identity = Binder.clearCallingIdentity();
try {
ensureIsPrimaryUser();
} finally {
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);
}
}
@GuardedBy("mLock")
private void startBugreportLocked(int callingUid, String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener, boolean isScreenshotRequested) {
if (isDumpstateBinderServiceRunningLocked()) {
Slog.w(TAG, "'dumpstate' is already running. Cannot start a new bugreport"
+ " while another one is currently in progress.");
reportError(listener,
IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
return;
}
IDumpstate ds = startAndGetDumpstateBinderServiceLocked();
if (ds == null) {
Slog.w(TAG, "Unable to get bugreport service");
reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
return;
}
// Wrap the listener so we can intercept binder events directly.
IDumpstateListener myListener = new DumpstateListener(listener, ds);
try {
ds.startBugreport(callingUid, callingPackage,
bugreportFd, screenshotFd, bugreportMode, myListener, isScreenshotRequested);
} catch (RemoteException e) {
// bugreportd service is already started now. We need to kill it to manage the
// lifecycle correctly. If we don't subsequent callers will get
// BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS error.
// Note that listener will be notified by the death recipient below.
cancelBugreport();
}
}
// root 12488 1 12403708 6692 0 0 S dumpstate
@GuardedBy("mLock")
private IDumpstate startAndGetDumpstateBinderServiceLocked() {
// Start bugreport service.
SystemProperties.set("ctl.start", BUGREPORT_SERVICE); // bugreportd process
IDumpstate ds = null;
boolean timedOut = false;
int totalTimeWaitedMillis = 0;
int seedWaitTimeMillis = 500;
while (!timedOut) {
ds = getDumpstateBinderServiceLocked();
if (ds != null) {
Slog.i(TAG, "Got bugreport service handle.");
break;
}
SystemClock.sleep(seedWaitTimeMillis);
Slog.i(TAG,
"Waiting to get dumpstate service handle (" + totalTimeWaitedMillis + "ms)");
totalTimeWaitedMillis += seedWaitTimeMillis;
seedWaitTimeMillis *= 2;
timedOut = totalTimeWaitedMillis > DEFAULT_BUGREPORT_SERVICE_TIMEOUT_MILLIS;
}
if (timedOut) {
Slog.w(TAG,
"Timed out waiting to get dumpstate service handle ("
+ totalTimeWaitedMillis + "ms)");
}
return ds;
}
@GuardedBy("mLock")
@Nullable
private IDumpstate getDumpstateBinderServiceLocked() {
// Note that the binder service on the native side is "dumpstate".
return IDumpstate.Stub.asInterface(ServiceManager.getService("dumpstate"));
}
}
adb bugreport
命令执行入口 frameworks/native/cmds/bugreport/bugreport.cpp
#include <cutils/properties.h>
#include <cutils/sockets.h>
// This program will trigger the dumpstate service to start a call to
// dumpstate, then connect to the dumpstate local client to read the
// output. All of the dumpstate output is written to stdout, including
// any errors encountered while reading/writing the output.
int main() {
fprintf(stderr, "=============================================================================\n");
fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
fprintf(stderr, "=============================================================================\n\n\n");
// Start the dumpstate service.
// 启动dumpstate服务
property_set("ctl.start", "dumpstate");
// Socket will not be available until service starts.
int s = -1;
for (int i = 0; i < 20; i++) {
// socket 连接
s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED,
SOCK_STREAM);
if (s >= 0)
break;
// Try again in 1 second.
sleep(1);
}
if (s == -1) {
printf("Failed to connect to dumpstate service: %s\n", strerror(errno));
return 1;
}
// 当3分钟没有数据可读,则超时停止并退出
// Set a timeout so that if nothing is read in 3 minutes, we'll stop
// reading and quit. No timeout in dumpstate is longer than 60 seconds,
// so this gives lots of leeway in case of unforeseen time outs.
struct timeval tv;
tv.tv_sec = 3 * 60;
tv.tv_usec = 0;
if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
}
while (1) {
char buffer[65536];
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(s, buffer, sizeof(buffer)));
if (bytes_read == 0) {
break;
} else if (bytes_read == -1) {
// EAGAIN really means time out, so change the errno.
// EAGAIN 意味着timeout, Bugreport读异常终止
if (errno == EAGAIN) {
errno = ETIMEDOUT;
}
printf("\nBugreport read terminated abnormally (%s).\n", strerror(errno));
break;
}
ssize_t bytes_to_send = bytes_read;
ssize_t bytes_written;
// 不断循环将读取到的数据输出到stdout
do {
bytes_written = TEMP_FAILURE_RETRY(write(STDOUT_FILENO,
buffer + bytes_read - bytes_to_send,
bytes_to_send));
if (bytes_written == -1) {
printf("Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
bytes_read, bytes_to_send, strerror(errno));
return 1;
}
bytes_to_send -= bytes_written;
} while (bytes_written != 0 && bytes_to_send > 0);
}
close(s);
return 0;
}
dumpstate
真正执行命令的进程 frameworks/native/cmds/dumpstate/
android/frameworks/native/cmds/dumpstate$ tree
.
├── Android.bp
├── Android.mk
├── AndroidTest.xml
├── binder
│ └── android
│ └── os
│ ├── IDumpstate.aidl
│ ├── IDumpstateListener.aidl
│ └── IDumpstateToken.aidl
├── bugreport-format.md
├── dumpstate.cpp
├── dumpstate.h
├── DumpstateInternal.cpp
├── DumpstateInternal.h
├── dumpstate.rc
├── DumpstateSectionReporter.cpp
├── DumpstateSectionReporter.h
├── DumpstateService.cpp
├── DumpstateService.h
├── DumpstateUtil.cpp
├── DumpstateUtil.h
├── main.cpp
├── README.md
Android.mk
cc_library_shared {
name: "libdumpstateaidl",
defaults: ["dumpstate_cflag_defaults"],
shared_libs: [
"libbinder",
"libutils",
],
aidl: {
local_include_dirs: ["binder"],
export_aidl_headers: true,
},
srcs: [
":dumpstate_aidl",
],
export_include_dirs: ["binder"],
}
filegroup {
name: "dumpstate_aidl",
srcs: [
"binder/android/os/IDumpstateListener.aidl",
"binder/android/os/IDumpstate.aidl",
],
path: "binder",
}
cc_binary {
name: "dumpstate",
defaults: ["dumpstate_defaults"],
srcs: [
"dumpstate.cpp",
"main.cpp",
],
required: [
"atrace",
"df",
"getprop",
"ip",
"iptables",
"ip6tables",
"kill",
"librank",
"logcat",
"lpdump",
"lpdumpd",
"lsmod",
"lsof",
"netstat",
"printenv",
"procrank",
"screencap",
"showmap",
"ss",
"storaged",
"top",
"uptime",
"vdc",
"vril-dump",
],
init_rc: ["dumpstate.rc"],
}
dumpstate.rc
on boot
# Allow bugreports access to eMMC 5.0 stats
chown root mount /sys/kernel/debug/mmc0/mmc0:0001/ext_csd
chmod 0440 /sys/kernel/debug/mmc0/mmc0:0001/ext_csd
service dumpstate /system/bin/dumpstate -s
class main
socket dumpstate stream 0660 shell log
disabled
oneshot
# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
# it is finished.
service dumpstatez /system/bin/dumpstate -S -d -z
socket dumpstate stream 0660 shell log
class main
disabled
oneshot
# bugreportd starts dumpstate binder service and makes it wait for a listener to connect.
service bugreportd /system/bin/dumpstate -w
class main
disabled
oneshot
dumpstate_aidl
package android.os;
import android.os.IDumpstateListener;
/**
* Binder interface for the currently running dumpstate process.
* {@hide}
*/
interface IDumpstate {
// NOTE: If you add to or change these modes, please also change the corresponding enums
// in system server, in BugreportParams.java.
// These modes encapsulate a set of run time options for generating bugreports.
// Takes a bugreport without user interference.
const int BUGREPORT_MODE_FULL = 0;
// Interactive bugreport, i.e. triggered by the user.
const int BUGREPORT_MODE_INTERACTIVE = 1;
// Remote bugreport triggered by DevicePolicyManager, for e.g.
const int BUGREPORT_MODE_REMOTE = 2;
// Bugreport triggered on a wear device.
const int BUGREPORT_MODE_WEAR = 3;
// Bugreport limited to only telephony info.
const int BUGREPORT_MODE_TELEPHONY = 4;
// Bugreport limited to only wifi info.
const int BUGREPORT_MODE_WIFI = 5;
// Default mode.
const int BUGREPORT_MODE_DEFAULT = 6;
/*
* Starts a bugreport in the background.
*
*<p>Shows the user a dialog to get consent for sharing the bugreport with the calling
* application. If they deny {@link IDumpstateListener#onError} will be called. If they
* consent and bugreport generation is successful artifacts will be copied to the given fds and
* {@link IDumpstateListener#onFinished} will be called. If there
* are errors in bugreport generation {@link IDumpstateListener#onError} will be called.
*
* @param callingUid UID of the original application that requested the report.
* @param callingPackage package of the original application that requested the report.
* @param bugreportFd the file to which the zipped bugreport should be written
* @param screenshotFd the file to which screenshot should be written
* @param bugreportMode the mode that specifies other run time options; must be one of above
* @param listener callback for updates; optional
* @param isScreenshotRequested indicates screenshot is requested or not
*/
void startBugreport(int callingUid, @utf8InCpp String callingPackage,
FileDescriptor bugreportFd, FileDescriptor screenshotFd,
int bugreportMode, IDumpstateListener listener,
boolean isScreenshotRequested);
/*
* Cancels the bugreport currently in progress.
*/
void cancelBugreport();
}
/**
* Listener for dumpstate events.
*
* <p>When bugreport creation is complete one of {@code onError} or {@code onFinished} is called.
*
* <p>These methods are synchronous by design in order to make dumpstate's lifecycle simpler
* to handle.
*
* {@hide}
*/
interface IDumpstateListener {
/**
* Called when there is a progress update.
*
* @param progress the progress in [0, 100]
*/
oneway void onProgress(int progress);
// NOTE: If you add to or change these error codes, please also change the corresponding enums
// in system server, in BugreportManager.java.
/* Options specified are invalid or incompatible */
const int BUGREPORT_ERROR_INVALID_INPUT = 1;
/* Bugreport encountered a runtime error */
const int BUGREPORT_ERROR_RUNTIME_ERROR = 2;
/* User denied consent to share the bugreport with the specified app */
const int BUGREPORT_ERROR_USER_DENIED_CONSENT = 3;
/* The request to get user consent timed out */
const int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4;
/* There is currently a bugreport running. The caller should try again later. */
const int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5;
/**
* Called on an error condition with one of the error codes listed above.
* This is not an asynchronous method since it can race with dumpstate exiting, thus triggering
* death recipient.
*/
void onError(int errorCode);
/**
* Called when taking bugreport finishes successfully.
*/
oneway void onFinished();
/**
* Called when screenshot is taken.
*/
oneway void onScreenshotTaken(boolean success);
/**
* Called when ui intensive bugreport dumps are finished.
*/
oneway void onUiIntensiveBugreportDumpsFinished(String callingPackage);
}
main.cpp
int main(int argc, char* argv[]) {
if (ShouldStartServiceAndWait(argc, argv)) {
int ret;
if ((ret = android::os::DumpstateService::Start()) != android::OK) {
MYLOGE("Unable to start 'dumpstate' service: %d", ret);
exit(1);
}
MYLOGI("'dumpstate' service started and will wait for a call to startBugreport()");
// Waits forever for an incoming connection.
// TODO(b/111441001): should this time out?
android::IPCThreadState::self()->joinThreadPool();
return 0;
} else {
return run_main(argc, argv);
}
}
DumpstateService.cpp
struct DumpstateInfo {
public:
Dumpstate* ds = nullptr;
int32_t calling_uid = -1;
std::string calling_package;
};
// Creates a bugreport and exits, thus preserving the oneshot nature of the service.
// Note: takes ownership of data.
[[noreturn]] static void* dumpstate_thread_main(void* data) {
std::unique_ptr<DumpstateInfo> ds_info(static_cast<DumpstateInfo*>(data));
ds_info->ds->Run(ds_info->calling_uid, ds_info->calling_package); // 进入dumpstate.cpp
MYLOGD("Finished taking a bugreport. Exiting.\n");
exit(0);
}
DumpstateService::DumpstateService() : ds_(nullptr) {
}
char const* DumpstateService::getServiceName() {
return "dumpstate";
}
status_t DumpstateService::Start() {
IPCThreadState::self()->disableBackgroundScheduling(true);
status_t ret = BinderService<DumpstateService>::publish();
if (ret != android::OK) {
return ret;
}
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
return android::OK;
}
binder::Status DumpstateService::startBugreport(int32_t calling_uid,
const std::string& calling_package,
android::base::unique_fd bugreport_fd,
android::base::unique_fd screenshot_fd,
int bugreport_mode,
const sp<IDumpstateListener>& listener,
bool is_screenshot_requested) {
MYLOGI("startBugreport() with mode: %d\n", bugreport_mode);
// Ensure there is only one bugreport in progress at a time.
std::lock_guard<std::mutex> lock(lock_);
if (ds_ != nullptr) {
MYLOGE("Error! There is already a bugreport in progress. Returning.");
if (listener != nullptr) {
listener->onError(IDumpstateListener::BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
}
return exception(binder::Status::EX_SERVICE_SPECIFIC,
"There is already a bugreport in progress");
}
// From here on, all conditions that indicate we are done with this incoming request should
// result in exiting the service to free it up for next invocation.
if (listener == nullptr) {
MYLOGE("Invalid input: no listener");
exit(0);
}
if (bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_FULL &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_REMOTE &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WEAR &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_TELEPHONY &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_WIFI &&
bugreport_mode != Dumpstate::BugreportMode::BUGREPORT_DEFAULT) {
MYLOGE("Invalid input: bad bugreport mode: %d", bugreport_mode);
signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
}
std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
options->Initialize(static_cast<Dumpstate::BugreportMode>(bugreport_mode), bugreport_fd,
screenshot_fd, is_screenshot_requested);
if (bugreport_fd.get() == -1 || (options->do_screenshot && screenshot_fd.get() == -1)) {
MYLOGE("Invalid filedescriptor");
signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
}
ds_ = &(Dumpstate::GetInstance());
ds_->SetOptions(std::move(options));
ds_->listener_ = listener;
DumpstateInfo* ds_info = new DumpstateInfo();
ds_info->ds = ds_;
ds_info->calling_uid = calling_uid;
ds_info->calling_package = calling_package;
pthread_t thread;
// Initialize dumpstate
ds_->Initialize();
status_t err = pthread_create(&thread, nullptr, dumpstate_thread_main, ds_info); // 开始执行dumpstate指令
if (err != 0) {
delete ds_info;
ds_info = nullptr;
MYLOGE("Could not create a thread");
signalErrorAndExit(listener, IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
}
return binder::Status::ok();
}
Dumpstate.cpp
// TODO: temporary variables and functions used during C++ refactoring
static Dumpstate& ds = Dumpstate::GetInstance();
static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
const CommandOptions& options = CommandOptions::DEFAULT,
bool verbose_duration = false) {
return ds.RunCommand(title, full_command, options, verbose_duration);
}
Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
// 给客户端的回调
if (listener_ != nullptr) {
switch (status) {
case Dumpstate::RunStatus::OK:
listener_->onFinished();
break;
case Dumpstate::RunStatus::HELP:
break;
case Dumpstate::RunStatus::INVALID_INPUT:
listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
break;
case Dumpstate::RunStatus::ERROR:
listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
break;
case Dumpstate::RunStatus::USER_CONSENT_DENIED:
listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
break;
case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
break;
}
}
return status;
}
Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
const std::string& calling_package) {
LogDumpOptions(*options_);
if (!options_->ValidateOptions()) {
MYLOGE("Invalid options specified\n");
return RunStatus::INVALID_INPUT;
}
/* set as high priority, and protect from OOM killer */
setpriority(PRIO_PROCESS, 0, -20);
FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
if (oom_adj) {
fputs("-1000", oom_adj);
fclose(oom_adj);
} else {
/* fallback to kernels <= 2.6.35 */
oom_adj = fopen("/proc/self/oom_adj", "we");
if (oom_adj) {
fputs("-17", oom_adj);
fclose(oom_adj);
}
}
if (version_ == VERSION_DEFAULT) {
version_ = VERSION_CURRENT;
}
if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
VERSION_SPLIT_ANR.c_str());
return RunStatus::INVALID_INPUT;
}
if (options_->show_header_only) {
PrintHeader();
return RunStatus::OK;
}
MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
calling_uid, calling_package.c_str());
// Redirect output if needed
bool is_redirecting = options_->OutputToFile();
// TODO: temporarily set progress until it's part of the Dumpstate constructor
std::string stats_path =
is_redirecting
? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
: "";
progress_.reset(new Progress(stats_path));
if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
} else {
// Wake lock will be released automatically on process death
MYLOGD("Wake lock acquired.\n");
}
register_sig_handler();
// TODO(b/111441001): maybe skip if already started?
if (options_->do_start_service) {
MYLOGI("Starting 'dumpstate' service\n");
android::status_t ret;
if ((ret = android::os::DumpstateService::Start()) != android::OK) {
MYLOGE("Unable to start DumpstateService: %d\n", ret);
}
}
if (PropertiesHelper::IsDryRun()) {
MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
}
MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
do_early_screenshot_ = options_->do_progress_updates;
// If we are going to use a socket, do it as early as possible
// to avoid timeouts from bugreport.
if (options_->use_socket) {
if (!redirect_to_socket(stdout, "dumpstate")) {
return ERROR;
}
}
if (options_->use_control_socket) {
MYLOGD("Opening control socket\n");
control_socket_fd_ = open_socket("dumpstate");
if (control_socket_fd_ == -1) {
return ERROR;
}
options_->do_progress_updates = 1;
}
if (is_redirecting) {
PrepareToWriteToFile();
if (options_->do_progress_updates) {
// clang-format off
std::vector<std::string> am_args = {
"--receiver-permission", "android.permission.DUMP",
};
// clang-format on
// Send STARTED broadcast for apps that listen to bugreport generation events
SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
if (options_->use_control_socket) {
dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
}
}
}
/* read /proc/cmdline before dropping root */
FILE *cmdline = fopen("/proc/cmdline", "re");
if (cmdline) {
fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
fclose(cmdline);
}
if (options_->do_vibrate) {
Vibrate(150);
}
if (options_->do_zip_file && zip_file != nullptr) {
if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
strerror(errno));
}
}
int dup_stdout_fd;
int dup_stderr_fd;
if (is_redirecting) {
// Redirect stderr to log_path_ for debugging.
TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
return ERROR;
}
if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
strerror(errno));
}
// Redirect stdout to tmp_path_. This is the main bugreport entry and will be
// moved into zip file later, if zipping.
TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
// TODO: why not write to a file instead of stdout to overcome this problem?
/* TODO: rather than generating a text file now and zipping it later,
it would be more efficient to redirect stdout to the zip entry
directly, but the libziparchive doesn't support that option yet. */
if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
return ERROR;
}
if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
tmp_path_.c_str(), strerror(errno));
}
}
// Don't buffer stdout
setvbuf(stdout, nullptr, _IONBF, 0);
// NOTE: there should be no stdout output until now, otherwise it would break the header.
// In particular, DurationReport objects should be created passing 'title, NULL', so their
// duration is logged into MYLOG instead.
PrintHeader();
// TODO(b/158737089) reduce code repetition in if branches
if (options_->telephony_only) {
MaybeTakeEarlyScreenshot();
onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
DumpstateTelephonyOnly(calling_package);
DumpstateBoard();
} else if (options_->wifi_only) {
MaybeTakeEarlyScreenshot();
onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
DumpstateWifiOnly();
} else if (options_->limited_only) {
MaybeTakeEarlyScreenshot();
onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
DumpstateLimitedOnly();
} else {
// 首先调用dumpsys 以保留系统状态
// Invoke critical dumpsys first to preserve system state, before doing anything else.
RunDumpsysCritical();
// Take screenshot and get consent only after critical dumpsys has finished.
MaybeTakeEarlyScreenshot();
onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
MaybeCheckUserConsent(calling_uid, calling_package);
// 获取默认bugreport默认case
// Dump state for the default case. This also drops root.
RunStatus s = DumpstateDefaultAfterCritical();
if (s != RunStatus::OK) {
if (s == RunStatus::USER_CONSENT_DENIED) {
HandleUserConsentDenied();
}
return s;
}
}
/* close output if needed */
if (is_redirecting) {
TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
}
// Zip the (now complete) .tmp file within the internal directory.
if (options_->OutputToFile()) {
FinalizeFile();
}
// Share the final file with the caller if the user has consented or Shell is the caller.
Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
if (CalledByApi()) {
status = CopyBugreportIfUserConsented(calling_uid);
if (status != Dumpstate::RunStatus::OK &&
status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
// Do an early return if there were errors. We make an exception for consent
// timing out because it's possible the user got distracted. In this case the
// bugreport is not shared but made available for manual retrieval.
MYLOGI("User denied consent. Returning\n");
return status;
}
if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
MYLOGI(
"Did not receive user consent yet."
" Will not copy the bugreport artifacts to caller.\n");
const String16 incidentcompanion("incidentcompanion");
sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
if (ics != nullptr) {
MYLOGD("Canceling user consent request via incidentcompanion service\n");
android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
consent_callback_.get());
} else {
MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
}
}
}
/* vibrate a few but shortly times to let user know it's finished */
if (options_->do_vibrate) {
for (int i = 0; i < 3; i++) {
Vibrate(75);
usleep((75 + 50) * 1000);
}
}
MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
progress_->GetInitialMax());
progress_->Save();
MYLOGI("done (id %d)\n", id_);
if (is_redirecting) {
TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
}
if (options_->use_control_socket && control_socket_fd_ != -1) {
MYLOGD("Closing control socket\n");
close(control_socket_fd_);
}
tombstone_data_.clear();
anr_data_.clear();
return (consent_callback_ != nullptr &&
consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
? USER_CONSENT_TIMED_OUT
: RunStatus::OK;
}
/*
* Dumps state for the default case; drops root after it's no longer necessary.
*
* Returns RunStatus::OK if everything went fine.
* Returns RunStatus::ERROR if there was an error.
* Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
* with the caller.
*/
Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
// Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
// buffer.
// 抓取日志
DoLogcat();
// Capture timestamp after first logcat to use in next logcat
time_t logcat_ts = time(nullptr);
/* collect stack traces from Dalvik and native processes (needs root) */
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
/* Run some operations that require root. */
ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
ds.AddDir(RECOVERY_DIR, true);
ds.AddDir(RECOVERY_DATA_DIR, true);
ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
ds.AddDir(LOGPERSIST_DATA_DIR, false);
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(PROFILE_DATA_DIR_CUR, true);
ds.AddDir(PROFILE_DATA_DIR_REF, true);
ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
}
ds.AddDir(PREREBOOT_DATA_DIR, false);
add_mountinfo();
DumpIpTablesAsRoot();
DumpDynamicPartitionInfo();
ds.AddDir(OTA_METADATA_DIR, true);
// Capture any IPSec policies in play. No keys are exposed here.
RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
// Dump IPsec stats. No keys are exposed here.
DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
// Run ss as root so we can see socket marks.
RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
// Run iotop as root to show top 100 IO threads
RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
// Gather shared memory buffer info if the product implements it
struct stat st;
if (!stat("/product/bin/dmabuf_dump", &st)) {
RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
}
DumpFile("PSI cpu", "/proc/pressure/cpu");
DumpFile("PSI memory", "/proc/pressure/memory");
DumpFile("PSI io", "/proc/pressure/io");
if (!DropRootUser()) {
return Dumpstate::RunStatus::ERROR;
}
RETURN_IF_USER_DENIED_CONSENT();
Dumpstate::RunStatus status = dumpstate();
// Capture logcat since the last time we did it.
DoSystemLogcat(logcat_ts);
return status;
}
// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
// via the consent they are shown. Ignores other errors that occur while running various
// commands. The consent checking is currently done around long running tasks, which happen to
// be distributed fairly evenly throughout the function.
static Dumpstate::RunStatus dumpstate() {
DurationReporter duration_reporter("DUMPSTATE");
// Dump various things. Note that anything that takes "long" (i.e. several seconds) should
// check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
// in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
RunCommand("UPTIME", {"uptime"});
DumpBlockStatFiles();
DumpFile("MEMORY INFO", "/proc/meminfo");
RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
"pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
DumpFile("SLAB INFO", "/proc/slabinfo");
DumpFile("ZONEINFO", "/proc/zoneinfo");
DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
DumpFile("BUDDYINFO", "/proc/buddyinfo");
DumpExternalFragmentationInfo();
DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
RunCommand("PROCESSES AND THREADS",
{"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
CommandOptions::AS_ROOT);
DumpHals();
RunCommand("PRINTENV", {"printenv"});
RunCommand("NETSTAT", {"netstat", "-nW"});
struct stat s;
if (stat("/proc/modules", &s) != 0) {
MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
} else {
RunCommand("LSMOD", {"lsmod"});
}
if (__android_logger_property_get_bool(
"ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
DoKernelLogcat();
} else {
do_dmesg();
}
RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
/* Dump Bluetooth HCI logs */
ds.AddDir("/data/misc/bluetooth/logs", true);
if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
MYLOGI("taking late screenshot\n");
ds.TakeScreenshot();
}
AddAnrTraceFiles();
// NOTE: tombstones are always added as separate entries in the zip archive
// and are not interspersed with the main report.
const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
"TOMBSTONE", true /* add_to_zip */);
if (!tombstones_dumped) {
printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
}
DumpPacketStats();
RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
DoKmsg();
DumpIpAddrAndRules();
dump_route_tables();
RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
RunCommand("SYSTEM PROPERTIES", {"getprop"});
RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
/* Binder state is expensive to look at as it uses a lot of memory. */
std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
"/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
DumpFile("BINDER STATS", binder_logs_dir + "/stats");
DumpFile("BINDER STATE", binder_logs_dir + "/state");
/* Add window and surface trace files. */
if (!PropertiesHelper::IsUserBuild()) {
ds.AddDir(WMTRACE_DATA_DIR, false);
}
ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
/* Migrate the ril_dumpstate to a device specific dumpstate? */
int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
if (rilDumpstateTimeout > 0) {
// su does not exist on user builds, so try running without it.
// This way any implementations of vril-dump that do not require
// root can run on user builds.
CommandOptions::CommandOptionsBuilder options =
CommandOptions::WithTimeout(rilDumpstateTimeout);
if (!PropertiesHelper::IsUserBuild()) {
options.AsRoot();
}
RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
}
printf("========================================================\n");
printf("== Android Framework Services\n");
printf("========================================================\n");
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
printf("========================================================\n");
printf("== Checkins\n");
printf("========================================================\n");
RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
printf("========================================================\n");
printf("== Running Application Activities\n");
printf("========================================================\n");
// The following dumpsys internally collects output from running apps, so it can take a long
// time. So let's extend the timeout.
const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
printf("== Running Application Services (platform)\n");
printf("========================================================\n");
RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
printf("== Running Application Services (non-platform)\n");
printf("========================================================\n");
RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
printf("== Running Application Providers (platform)\n");
printf("========================================================\n");
RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
printf("== Running Application Providers (non-platform)\n");
printf("========================================================\n");
RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
DUMPSYS_COMPONENTS_OPTIONS);
printf("========================================================\n");
printf("== Dropbox crashes\n");
printf("========================================================\n");
RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
printf("========================================================\n");
printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
ds.progress_->GetMax(), ds.progress_->GetInitialMax());
printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
printf("========================================================\n");
printf("== Obtaining statsd metadata\n");
printf("========================================================\n");
// This differs from the usual dumpsys stats, which is the stats report data.
RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
// Add linker configuration directory
ds.AddDir(LINKERCONFIG_DIR, true);
RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
return Dumpstate::RunStatus::OK;
}
bugreport.zip
生成报告路径: /data/user_de/0/com.android.shell/files/bugreports/
bugreport$ tree -L 2
.
├── bugreport-qssi-RKQ1.200903.002-2020-12-13-14-28-06.txt
├── dumpstate_log.txt
├── FS
│ ├── data
│ ├── linkerconfig
│ └── proc
├── lshal-debug
│ ├── android.hardware.audio.effect@6.0::IEffectsFactory_default.txt
│ ├── android.hardware.bluetooth@1.0::IBluetoothHci_default.txt
│ ├── android.hardware.drm@1.3::IDrmFactory_clearkey.txt
│ ├── android.hardware.health@2.1::IHealth_default.txt
│ ├── android.hardware.media.c2@1.1::IComponentStore_software.txt
│ ├── android.hardware.sensors@2.0::ISensors_default.txt
│ └── android.hardware.wifi@1.4::IWifi_default.txt
├── main_entry.txt
├── proto
│ ├── activity_CRITICAL.proto
│ ├── activity.proto
│ ├── incident_report.proto
│ ├── SurfaceFlinger_CRITICAL.proto
│ └── window_CRITICAL.proto
├── version.txt
├── visible_windows
│ ├── 6ab5864 StatusBar
│ └── d2fcfdc com.android.settings
└── visible_windows.zip
交互式生成错误报告
--------- beginning of main
12-13 15:59:10.127 11924 11924 I dumpstate: 'dumpstate' service started and will wait for a call to startBugreport()
12-13 15:59:10.579 11924 11925 I dumpstate: startBugreport() with mode: 1
12-13 15:59:10.598 11924 11927 I dumpstate: do_zip_file: 1 do_vibrate: 1 use_socket: 0 use_control_socket: 0 do_screenshot: 0 is_remote_mode: 0 show_header_only: 0 do_start_service: 1 telephony_only: 0 wifi_only: 0 do_progress_updates: 1 fd: 9 bugreport_mode: BUGREPORT_INTERACTIVE dumpstate_hal_mode: INTERACTIVE limited_only: 0 args:
12-13 15:59:10.603 11924 11927 D dumpstate: dumpstate calling_uid = 2000 ; calling package = com.android.shell
12-13 15:59:10.604 11924 11927 D dumpstate: Loading stats from /bugreports/dumpstate-stats.txt
12-13 15:59:10.605 11924 11927 I dumpstate: Average max progress: 8016 in 3 runs; estimated max: 8016
12-13 15:59:10.615 11924 11927 D dumpstate: Wake lock acquired.
12-13 15:59:10.616 11924 11927 I dumpstate: Starting 'dumpstate' service
12-13 15:59:10.619 11924 11927 I dumpstate: dumpstate info: id=4, args='', bugreport_mode= BUGREPORT_INTERACTIVE bugreport format version: 2.0
12-13 15:59:10.625 11924 11927 D dumpstate: Bugreport dir: [[fd:9]] Base name: [bugreport-qssi-RKQ1.200903.002] Suffix: [2020-12-13-15-59-10] Log path: [/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10-dumpstate_log-11924.txt] Temporary path: [/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10.tmp] Screenshot path: []
12-13 15:59:10.625 11924 11927 D dumpstate: Creating initial .zip file (/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10-zip.tmp)
12-13 15:59:10.629 11924 11927 D dumpstate: Adding zip text entry version.txt
12-13 15:59:10.632 11924 11927 I dumpstate: Sending broadcast: '/system/bin/cmd activity broadcast --user 0 --receiver-foreground --receiver-include-background -a com.android.internal.intent.action.BUGREPORT_STARTED --receiver-permission android.permission.DUMP'
12-13 15:59:10.752 11924 11927 D dumpstate: Setting progress: 20/8016 (0%)
12-13 15:59:10.754 11924 11927 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 150 dumpstate'
12-13 15:59:10.882 11924 11927 D dumpstate: Setting progress: 30/8016 (0%)
12-13 15:59:10.893 11924 11927 D dumpstate: Module metadata package name: com.android.modulemetadata
12-13 15:59:17.440 11924 11927 D dumpstate: Setting progress: 80/8016 (0%)
12-13 15:59:17.442 11924 11927 D dumpstate: Duration of 'SYSTEM LOG': 6.00s
12-13 15:59:17.921 11924 11927 D dumpstate: Duration of 'EVENT LOG': 0.48s
12-13 15:59:18.028 11924 11927 D dumpstate: Duration of 'STATS LOG': 0.11s
12-13 15:59:18.278 11924 11927 D dumpstate: Duration of 'RADIO LOG': 0.25s
12-13 15:59:18.474 11924 11927 E dumpstate: *** command 'logcat -L -b all -v threadtime -v printable -v uid -d *:v' failed: exit code 1
12-13 15:59:18.559 11924 11927 I dumpstate: libdebuggerd_client: started dumping process 544
12-13 15:59:18.795 11924 11927 I dumpstate: libdebuggerd_client: done dumping process 544
.................................................................................................
12-13 15:59:41.066 11924 11927 I dumpstate: libdebuggerd_client: started dumping process 16448
12-13 15:59:41.236 11924 11927 I dumpstate: libdebuggerd_client: done dumping process 16448
12-13 15:59:41.252 11924 11927 I dumpstate: libdebuggerd_client: started dumping process 19886
12-13 15:59:41.449 11924 11927 I dumpstate: libdebuggerd_client: done dumping process 19886
12-13 15:59:41.461 11924 11927 I dumpstate: libdebuggerd_client: started dumping process 20036
12-13 15:59:41.665 11924 11927 I dumpstate: libdebuggerd_client: done dumping process 20036
12-13 15:59:41.668 11924 11927 D dumpstate: Duration of 'DUMP TRACES': 23.19s
12-13 15:59:41.687 11924 11927 D dumpstate: Adding dir /cache/recovery (recursive: 1)
12-13 15:59:41.688 11924 11927 D dumpstate: Adding dir /data/misc/recovery (recursive: 1)
12-13 15:59:41.693 11924 11927 D dumpstate: Adding dir /data/misc/update_engine_log (recursive: 1)
12-13 15:59:41.699 11924 11927 D dumpstate: Adding dir /data/misc/logd (recursive: 0)
12-13 15:59:41.700 11924 11927 D dumpstate: Adding dir /data/misc/profiles/cur (recursive: 1)
12-13 15:59:41.778 11924 11927 D dumpstate: Adding dir /data/misc/profiles/ref (recursive: 1)
12-13 15:59:41.807 11924 11927 D dumpstate: Adding dir /data/misc/prereboot (recursive: 0)
12-13 15:59:42.201 11924 11927 D dumpstate: MOUNT INFO: 53 entries added to zip file
12-13 15:59:44.086 11924 11927 D dumpstate: Duration of 'LPDUMP': 1.16s
12-13 15:59:45.213 11924 11927 D dumpstate: Duration of 'DEVICE-MAPPER': 1.13s
12-13 15:59:45.214 11924 11927 D dumpstate: Adding dir /metadata/ota (recursive: 1)
12-13 15:59:46.367 11924 11927 D dumpstate: Duration of 'DETAILED SOCKET STATE': 1.08s
12-13 15:59:48.462 11924 11927 D dumpstate: Duration of 'IOTOP': 2.09s
12-13 15:59:54.327 11924 11927 D dumpstate: Duration of 'CPU INFO': 5.48s
12-13 16:00:14.338 11924 11927 E dumpstate: *** command '/system/xbin/su root procrank' timed out after 20.009s (killing pid 12241)
12-13 16:00:17.971 11924 11927 D dumpstate: Duration of 'PROCRANK': 23.64s
12-13 16:00:21.380 11924 11927 D dumpstate: Duration of 'PROCESSES AND THREADS': 2.94s
12-13 16:00:31.391 11924 11927 E dumpstate: *** command '/system/xbin/su root librank' timed out after 10.009s (killing pid 12363)
12-13 16:00:41.393 11924 11927 E dumpstate: could not kill command '/system/xbin/su root librank' (pid 12363) even with SIGKILL.
12-13 16:00:41.394 11924 11927 D dumpstate: Duration of 'LIBRANK': 20.01s
12-13 16:00:45.850 11924 11927 E dumpstate: *** command '/system/xbin/su root lshal -lVSietrpc --types=b,c,l,z' timed out after 4.442s (killing pid 12455)
12-13 16:00:45.907 11924 11927 D dumpstate: Duration of 'HARDWARE HALS': 4.51s
12-13 16:01:27.746 11924 11927 D dumpstate: Duration of 'DUMP HALS': 46.35s
12-13 16:01:34.299 11924 11927 D dumpstate: Duration of 'LIST OF OPEN FILES': 5.93s
12-13 16:01:36.769 11924 11927 D dumpstate: Setting progress: 805/8016 (10%)
12-13 16:01:45.735 11924 11927 D dumpstate: Setting progress: 1605/8016 (20%)
12-13 16:01:54.484 11924 11927 D dumpstate: Setting progress: 2405/8016 (30%)
12-13 16:02:03.818 11924 11927 D dumpstate: Setting progress: 3215/8016 (40%)
12-13 16:02:13.306 11924 11927 D dumpstate: Setting progress: 4015/8016 (50%)
12-13 16:02:22.923 11924 11927 D dumpstate: Setting progress: 4815/8016 (60%)
12-13 16:02:32.876 11924 11927 D dumpstate: Setting progress: 5615/8016 (70%)
12-13 16:02:44.813 11924 11927 D dumpstate: Setting progress: 6415/8016 (80%)
12-13 16:02:50.879 11924 11927 D dumpstate: Duration of 'for_each_pid(SMAPS OF ALL PROCESSES)': 76.58s
12-13 16:02:51.936 11924 11927 D dumpstate: Duration of 'for_each_tid(BLOCKED PROCESS WAIT-CHANNELS)': 1.06s
12-13 16:02:52.133 11924 11927 D dumpstate: Adding dir /data/misc/bluetooth/logs (recursive: 1)
12-13 16:02:52.133 11924 11927 D dumpstate: AddAnrTraceDir(): dump_traces_file=/data/anr/dumptrace_qAMyGl, anr_traces_dir=/data/anr
12-13 16:02:52.133 11924 11927 D dumpstate: Dumping current ANR traces (/data/anr/dumptrace_qAMyGl) to the main bugreport entry
12-13 16:02:52.159 11924 11927 W dumpstate: Error unlinking temporary trace path /data/anr/dumptrace_qAMyGl: Permission denied
12-13 16:02:55.100 11924 11927 D dumpstate: Duration of 'DUMP ROUTE TABLES': 1.55s
12-13 16:02:55.401 11924 11927 D dumpstate: Setting progress: 7215/8016 (90%)
12-13 16:03:08.992 11924 11927 D dumpstate: Duration of 'DUMPSYS HIGH': 13.59s
12-13 16:03:09.585 11924 11927 D dumpstate: Adding dir /data/misc/wmtrace (recursive: 0)
12-13 16:03:09.586 11924 11927 D dumpstate: Adding dir /data/misc/snapshotctl_log (recursive: 0)
12-13 16:03:09.590 11924 11927 E dumpstate: No IDumpstateDevice implementation
12-13 16:03:09.590 11924 11927 E dumpstate: Failed to unlink file (/data/user_de/0/com.android.shell/files/bugreports/dumpstate_board.bin): No such file or directory
12-13 16:03:09.590 11924 11927 E dumpstate: Failed to unlink file (/data/user_de/0/com.android.shell/files/bugreports/dumpstate_board.txt): No such file or directory
12-13 16:03:09.978 11924 11924 W Binder:11924_3: type=1400 audit(0.0:561): avc: denied { use } for path="pipe:[1255084]" dev="pipefs" ino=1255084 scontext=u:r:hal_power_default:s0 tcontext=u:r:dumpstate:s0 tclass=fd permissive=0
12-13 16:03:18.518 11924 11924 W Binder:11924_3: type=1400 audit(0.0:562): avc: denied { use } for path="pipe:[1258953]" dev="pipefs" ino=1258953 scontext=u:r:system_suspend:s0 tcontext=u:r:dumpstate:s0 tclass=fd permissive=0
12-13 16:03:19.853 11924 11927 D dumpstate: Duration of 'DUMPSYS': 10.26s
12-13 16:03:29.073 11924 11927 D dumpstate: Duration of 'CHECKIN MEMINFO': 8.70s
12-13 16:03:35.362 11924 11927 D dumpstate: Duration of 'APP SERVICES PLATFORM': 5.56s
12-13 16:03:36.374 11924 11927 D dumpstate: Duration of 'APP PROVIDERS PLATFORM': 0.68s
12-13 16:03:36.821 11924 11927 D dumpstate: Adding dir /linkerconfig (recursive: 1)
12-13 16:04:13.545 11924 11927 D dumpstate: Duration of 'INCIDENT REPORT': 36.70s
12-13 16:04:13.546 11924 11927 D dumpstate: Duration of 'DUMPSTATE': 265.07s
12-13 16:04:14.279 11924 11927 D dumpstate: Duration of 'SYSTEM LOG': 0.73s
12-13 16:04:14.280 11924 11927 D dumpstate: Adding main entry (bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10.txt) from /data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10.tmp to .zip bugreport
12-13 16:04:14.280 11924 11927 D dumpstate: dumpstate id 4 finished around 2020/12/13 16:04:14 (304 s)
12-13 16:04:18.108 11924 11927 D dumpstate: Adding zip text entry main_entry.txt
12-13 16:04:18.110 11924 11927 D dumpstate: Removing temporary file /data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10.tmp
12-13 16:04:18.141 11924 11927 D dumpstate: Going to copy file (/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-15-59-10-zip.tmp) to 9
12-13 16:04:18.229 11924 11927 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:04:18.469 11924 11927 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:04:18.712 11924 11927 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:04:18.970 11924 11927 D dumpstate: Final progress: 7920/8016 (estimated 8016)
12-13 16:04:18.972 11924 11927 I dumpstate: Saving stats (total=31968, runs=4, average=7992) on /bugreports/dumpstate-stats.txt
12-13 16:04:18.976 11924 11927 I dumpstate: done (id 4)
12-13 16:04:19.024 11924 11927 D dumpstate: Finished taking a bugreport. Exiting.
生成完整报告
--------- beginning of main
12-13 16:09:42.064 17920 17920 I dumpstate: 'dumpstate' service started and will wait for a call to startBugreport()
12-13 16:09:42.515 17920 17922 I dumpstate: startBugreport() with mode: 0
12-13 16:09:42.538 17920 17923 I dumpstate: do_zip_file: 1 do_vibrate: 1 use_socket: 0 use_control_socket: 0 do_screenshot: 1 is_remote_mode: 0 show_header_only: 0 do_start_service: 0 telephony_only: 0 wifi_only: 0 do_progress_updates: 0 fd: 9 bugreport_mode: BUGREPORT_FULL dumpstate_hal_mode: FULL limited_only: 0 args:
12-13 16:09:42.542 17920 17923 D dumpstate: dumpstate calling_uid = 2000 ; calling package = com.android.shell
12-13 16:09:42.542 17920 17923 D dumpstate: Loading stats from /bugreports/dumpstate-stats.txt
12-13 16:09:42.543 17920 17923 I dumpstate: Average max progress: 7992 in 4 runs; estimated max: 7992
12-13 16:09:42.557 17920 17923 D dumpstate: Wake lock acquired.
12-13 16:09:42.558 17920 17923 I dumpstate: dumpstate info: id=5, args='', bugreport_mode= BUGREPORT_FULL bugreport format version: 2.0
12-13 16:09:42.563 17920 17923 D dumpstate: Bugreport dir: [[fd:9]] Base name: [bugreport-qssi-RKQ1.200903.002] Suffix: [2020-12-13-16-09-42] Log path: [/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-dumpstate_log-17920.txt] Temporary path: [/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42.tmp] Screenshot path: [/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-png.tmp]
12-13 16:09:42.563 17920 17923 D dumpstate: Creating initial .zip file (/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-zip.tmp)
12-13 16:09:42.566 17920 17923 D dumpstate: Adding zip text entry version.txt
12-13 16:09:42.570 17920 17923 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 150 dumpstate'
12-13 16:09:42.681 17920 17923 D dumpstate: Module metadata package name: com.android.modulemetadata
12-13 16:09:43.435 17920 17923 D dumpstate: Duration of 'DUMPSYS CRITICAL': 0.68s
12-13 16:09:46.286 17920 17923 D dumpstate: Duration of 'SYSTEM LOG': 2.80s
12-13 16:09:46.757 17920 17923 D dumpstate: Duration of 'EVENT LOG': 0.47s
12-13 16:09:46.851 17920 17923 D dumpstate: Duration of 'STATS LOG': 0.09s
12-13 16:09:47.150 17920 17923 D dumpstate: Duration of 'RADIO LOG': 0.30s
12-13 16:09:47.387 17920 17923 E dumpstate: *** command 'logcat -L -b all -v threadtime -v printable -v uid -d *:v' failed: exit code 1
12-13 16:09:47.496 17920 17923 I dumpstate: libdebuggerd_client: started dumping process 544
12-13 16:09:47.714 17920 17923 I dumpstate: libdebuggerd_client: done dumping process 544
....................................................................................................................
12-13 16:10:14.869 17920 17923 I dumpstate: libdebuggerd_client: started dumping process 20036
12-13 16:10:15.046 17920 17923 I dumpstate: libdebuggerd_client: done dumping process 20036
12-13 16:10:15.049 17920 17923 D dumpstate: Duration of 'DUMP TRACES': 27.66s
12-13 16:10:15.071 17920 17923 D dumpstate: Adding dir /cache/recovery (recursive: 1)
12-13 16:10:15.073 17920 17923 D dumpstate: Adding dir /data/misc/recovery (recursive: 1)
12-13 16:10:15.080 17920 17923 D dumpstate: Adding dir /data/misc/update_engine_log (recursive: 1)
12-13 16:10:15.083 17920 17923 D dumpstate: Adding dir /data/misc/logd (recursive: 0)
12-13 16:10:15.084 17920 17923 D dumpstate: Adding dir /data/misc/profiles/cur (recursive: 1)
12-13 16:10:15.168 17920 17923 D dumpstate: Adding dir /data/misc/profiles/ref (recursive: 1)
12-13 16:10:15.199 17920 17923 D dumpstate: Adding dir /data/misc/prereboot (recursive: 0)
12-13 16:10:15.553 17920 17923 D dumpstate: MOUNT INFO: 52 entries added to zip file
12-13 16:10:17.303 17920 17923 D dumpstate: Duration of 'LPDUMP': 1.16s
12-13 16:10:18.463 17920 17923 D dumpstate: Duration of 'DEVICE-MAPPER': 1.16s
12-13 16:10:18.463 17920 17923 D dumpstate: Adding dir /metadata/ota (recursive: 1)
12-13 16:10:19.624 17920 17923 D dumpstate: Duration of 'DETAILED SOCKET STATE': 1.08s
12-13 16:10:21.604 17920 17923 D dumpstate: Duration of 'IOTOP': 1.98s
12-13 16:10:26.764 17920 17923 D dumpstate: Duration of 'CPU INFO': 4.84s
12-13 16:10:46.775 17920 17923 E dumpstate: *** command '/system/xbin/su root procrank' timed out after 20.009s (killing pid 18252)
12-13 16:10:49.948 17920 17923 D dumpstate: Duration of 'PROCRANK': 23.18s
12-13 16:10:52.788 17920 17923 D dumpstate: Duration of 'PROCESSES AND THREADS': 2.34s
12-13 16:11:02.800 17920 17923 E dumpstate: *** command '/system/xbin/su root librank' timed out after 10.009s (killing pid 18389)
12-13 16:11:12.805 17920 17923 E dumpstate: could not kill command '/system/xbin/su root librank' (pid 18389) even with SIGKILL.
12-13 16:11:12.808 17920 17923 D dumpstate: Duration of 'LIBRANK': 20.02s
12-13 16:11:16.811 17920 17923 E dumpstate: *** command '/system/xbin/su root lshal -lVSietrpc --types=b,c,l,z' timed out after 3.971s (killing pid 18476)
12-13 16:11:17.345 17920 17923 D dumpstate: Duration of 'HARDWARE HALS': 4.54s
12-13 16:12:00.612 17920 17923 D dumpstate: Duration of 'DUMP HALS': 47.80s
12-13 16:12:06.605 17920 17923 D dumpstate: Duration of 'LIST OF OPEN FILES': 5.35s
12-13 16:13:25.766 17920 17923 D dumpstate: Duration of 'for_each_pid(SMAPS OF ALL PROCESSES)': 79.16s
12-13 16:13:26.659 17920 17923 D dumpstate: Duration of 'for_each_tid(BLOCKED PROCESS WAIT-CHANNELS)': 0.89s
12-13 16:13:26.855 17920 17923 D dumpstate: Adding dir /data/misc/bluetooth/logs (recursive: 1)
12-13 16:13:26.855 17920 17923 I dumpstate: taking late screenshot
12-13 16:13:27.670 17920 17923 D dumpstate: Screenshot saved on /data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-png.tmp
12-13 16:13:27.671 17920 17923 D dumpstate: AddAnrTraceDir(): dump_traces_file=/data/anr/dumptrace_2oVVjc, anr_traces_dir=/data/anr
12-13 16:13:27.671 17920 17923 D dumpstate: Dumping current ANR traces (/data/anr/dumptrace_2oVVjc) to the main bugreport entry
12-13 16:13:27.685 17920 17923 W dumpstate: Error unlinking temporary trace path /data/anr/dumptrace_2oVVjc: Permission denied
12-13 16:13:30.940 17920 17923 D dumpstate: Duration of 'DUMP ROUTE TABLES': 1.80s
12-13 16:13:44.155 17920 17923 D dumpstate: Duration of 'DUMPSYS HIGH': 12.92s
12-13 16:13:44.765 17920 17923 D dumpstate: Adding dir /data/misc/wmtrace (recursive: 0)
12-13 16:13:44.765 17920 17923 D dumpstate: Adding dir /data/misc/snapshotctl_log (recursive: 0)
12-13 16:13:44.771 17920 17923 E dumpstate: No IDumpstateDevice implementation
12-13 16:13:44.772 17920 17923 E dumpstate: Failed to unlink file (/data/user_de/0/com.android.shell/files/bugreports/dumpstate_board.bin): No such file or directory
12-13 16:13:44.772 17920 17923 E dumpstate: Failed to unlink file (/data/user_de/0/com.android.shell/files/bugreports/dumpstate_board.txt): No such file or directory
12-13 16:13:45.358 17920 17920 W Binder:17920_3: type=1400 audit(0.0:574): avc: denied { use } for path="pipe:[1386776]" dev="pipefs" ino=1386776 scontext=u:r:hal_power_default:s0 tcontext=u:r:dumpstate:s0 tclass=fd permissive=0
12-13 16:13:54.268 17920 17920 W Binder:17920_3: type=1400 audit(0.0:575): avc: denied { use } for path="pipe:[1374086]" dev="pipefs" ino=1374086 scontext=u:r:system_suspend:s0 tcontext=u:r:dumpstate:s0 tclass=fd permissive=0
12-13 16:13:55.715 17920 17923 D dumpstate: Duration of 'DUMPSYS': 10.94s
12-13 16:14:04.611 17920 17923 D dumpstate: Duration of 'CHECKIN MEMINFO': 8.25s
12-13 16:14:11.429 17920 17923 D dumpstate: Duration of 'APP SERVICES PLATFORM': 6.13s
12-13 16:14:12.331 17920 17923 D dumpstate: Duration of 'APP PROVIDERS PLATFORM': 0.54s
12-13 16:14:12.844 17920 17923 D dumpstate: Adding dir /linkerconfig (recursive: 1)
12-13 16:14:52.943 17920 17923 D dumpstate: Duration of 'INCIDENT REPORT': 40.07s
12-13 16:14:52.943 17920 17923 D dumpstate: Duration of 'DUMPSTATE': 271.33s
12-13 16:14:53.739 17920 17923 D dumpstate: Duration of 'SYSTEM LOG': 0.80s
12-13 16:14:53.739 17920 17923 D dumpstate: Adding main entry (bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42.txt) from /data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42.tmp to .zip bugreport
12-13 16:14:53.739 17920 17923 D dumpstate: dumpstate id 5 finished around 2020/12/13 16:14:53 (311 s)
12-13 16:14:57.497 17920 17923 D dumpstate: Adding zip text entry main_entry.txt
12-13 16:14:57.499 17920 17923 D dumpstate: Removing temporary file /data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42.tmp
12-13 16:14:57.530 17920 17923 D dumpstate: Going to copy file (/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-zip.tmp) to 9
12-13 16:14:57.616 17920 17923 D dumpstate: Going to copy file (/data/user_de/0/com.android.shell/files/bugreports/bugreport-qssi-RKQ1.200903.002-2020-12-13-16-09-42-png.tmp) to 10
12-13 16:14:57.618 17920 17923 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:14:57.827 17920 17923 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:14:58.042 17920 17923 I dumpstate: Vibrate: 'cmd vibrator vibrate -f 75 dumpstate'
12-13 16:14:58.326 17920 17923 D dumpstate: Final progress: 7980/7992 (estimated 7992)
12-13 16:14:58.328 17920 17923 I dumpstate: Saving stats (total=39948, runs=5, average=7989) on /bugreports/dumpstate-stats.txt
12-13 16:14:58.331 17920 17923 I dumpstate: done (id 5)
12-13 16:14:58.369 17920 17923 D dumpstate: Finished taking a bugreport. Exiting.