DropBoxManagerService

559 阅读3分钟

Android DropBoxManagerService初探

背景

随着Android的发展,市场上也出现各种形态的搭载Android系统的设备。然而对于开发者而言,永远预想不到用户能搞一些什么骚操作,将你的程序搞出问题,那么我们只能依赖问题监控去定位分析了。

如果你需要同时监控整个Android设备rom的稳定性(系统异常 + 各种应用的异常),那么市场上常见的异常监控的SDK就无法满足我们的需求了。那么对于这样的问题我们该怎么办呢?

Android系统中是否实现

在Android系统设计时候Google的工程师也考虑到了这个问题,从而在framework和native层种下了一个跟踪器 — DropBox。DropBox是Android 在Froyo(API level 8) 引入的用来持续化存储系统数据的机制,主要用于记录Android运行过程中,内核,系统进程,用户进程等出现严重问题时的log。DropBoxManagerService是一个独立的服务。

DropBoxManagerService分析

DropboxManagerService Initialize Flow and Usage Overview

Initialize Flow and Usage Overview

onBootPhase启动的流程

android系统-onBootPhase启动的流程

DropboxManagerService 服务处理请求

DropboxManagerService 服务处理请求

Crash Flow

DropBox日志文件会记录在/data/system/dropbox目录中。DropBox涵盖了绝大多数的异常和非法操作的相关信息。当一个Crash发生后,大概流程: Crash Flow

DropBox File 生成流程

DropBoxManagerService (DBMS)是一个系统服务。它的启动就在system_server启动的时候。在SystemService的startOtherService中启动。

mSystemServiceManager.startService(DropBoxManagerService.class);

ActivityManagerService.java

/**
 * Used by {@link com.android.internal.os.RuntimeInit} to report when an application crashes.
 * The application process will exit immediately after this call returns.
 * @param app object of the crashing app, null for the system server
 * @param crashInfo describing the exception
 */
public void handleApplicationCrash(IBinder app,
                                   ApplicationErrorReport.ParcelableCrashInfo crashInfo) {
    ProcessRecord r = findAppProcess(app, "Crash");
    final String processName = app == null ? "system_server"
            : (r == null ? "unknown" : r.processName);

    handleApplicationCrashInner("crash", r, processName, crashInfo);
}
/* Native crash reporting uses this inner version because it needs to be somewhat
 * decoupled from the AM-managed cleanup lifecycle
 */
void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName,
                                 ApplicationErrorReport.CrashInfo crashInfo) {
    ...
    ...

    addErrorToDropBox(
            eventType, r, processName, null, null, null, null, null, null, crashInfo,
            new Float(loadingProgress), incrementalMetrics, null);

    mAppErrors.crashApplication(r, crashInfo);
}
/**
 * Write a description of an error (crash, WTF, ANR) to the drop box.
 * @param eventType to include in the drop box tag ("crash", "wtf", etc.)
 * @param process which caused the error, null means the system server
 * @param activityShortComponentName which triggered the error, null if unknown
 * @param parentShortComponentName activity related to the error, null if unknown
 * @param parentProcess parent process
 * @param subject line related to the error, null if absent
 * @param report in long form describing the error, null if absent
 * @param dataFile text file to include in the report, null if none
 * @param crashInfo giving an application stack trace, null if absent
 * @param loadingProgress the loading progress of an installed package, range in [0, 1].
 * @param incrementalMetrics metrics for apps installed on Incremental.
 * @param errorId a unique id to append to the dropbox headers.
 */
public void addErrorToDropBox(String eventType,
                              ProcessRecord process, String processName, String activityShortComponentName,
                              String parentShortComponentName, ProcessRecord parentProcess,
                              String subject, final String report, final File dataFile,
                              final ApplicationErrorReport.CrashInfo crashInfo,
                              @Nullable Float loadingProgress, @Nullable IncrementalMetrics incrementalMetrics,
                              @Nullable UUID errorId) {
    // NOTE -- this must never acquire the ActivityManagerService lock,
    // otherwise the watchdog may be prevented from resetting the system.

    // Bail early if not published yet
    if (ServiceManager.getService(Context.DROPBOX_SERVICE) == null) return;
    final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class);

    ...
    ...
    dbox.addText(dropboxTag, sb.toString());
    
    ...
    ...
}

DropBoxManager.java

/**
 * Stores human-readable text.  The data may be discarded eventually (or even
 * immediately) if space is limited, or ignored entirely if the tag has been
 * blocked (see {@link #isTagEnabled}).
 *
 * @param tag describing the type of entry being stored
 * @param data value to store
 */
public void addText(@NonNull String tag, @NonNull String data) {
    addData(tag, data.getBytes(StandardCharsets.UTF_8), IS_TEXT);
}

/**
 * Stores binary data, which may be ignored or discarded as with {@link #addText}.
 *
 * @param tag describing the type of entry being stored
 * @param data value to store
 * @param flags describing the data
 */
public void addData(@NonNull String tag, @Nullable byte[] data, @Flags int flags) {
    ...
    // IDropBoxManagerService mService
    mService.addData(tag, data, flags);
    ...
}

DropBoxManagerService.java

public void addData(String tag, byte[] data, int flags) {
    addEntry(tag, new ByteArrayInputStream(data), data.length, flags);
}

public void addEntry(String tag, EntrySource entry, int flags) {
    ...
    // Call sendBroadcast after returning from this call to avoid deadlock. In particular
    // the caller may be holding the WindowManagerService lock but sendBroadcast requires a
    // lock in ActivityManagerService. ActivityManagerService has been caught holding that
    // very lock while waiting for the WindowManagerService lock.
    if (mLowPriorityTags != null && mLowPriorityTags.contains(tag)) {
        // Rate limit low priority Dropbox entries
        mHandler.maybeDeferBroadcast(tag, time);
    } else {
        mHandler.sendBroadcast(tag, time);
    }
    ...
}

这个流程system_service启动的时候,启动DBMS。当有Crash/anr/wtf等等问题产生时,调用AMS的addErrorToDropBox方式,生成一个对应的Entry对象,

Crash Type

dropbox文件名格式为dropboxTag@xxx.txt,xxx代表时间戳,例如 system_server_crash@1465650845355.txt ,则记录该文件时间戳为1465650845355. 文件后缀除了.txt,还有压缩格式.txt.gz. 对于dropboxTag是由processClass + eventType组合而成.

  • processClass分为:system_server, system_app, data_app;
  • eventType分为:crash, anr, wtf, native_cras, lowmem, watchdog
dropboxTag含义
system_server_anrsystem进程无响应
system_server_watchdogsystem进程发生watchdog
system_server_crashsystem进程崩溃
system_server_native_crashsystem进程native出现崩溃
system_server_wtfsystem进程发生严重错误
system_server_lowmemsystem进程内存不足
system_app_crash系统app崩溃
system_app_anr系统app无响应
data_app_crash普通app崩溃
data_app_anr普通app无响应

DropBoxFile 内容

SYSTEM_TOMBSTONE SYSTEM_TOMBSTONE.png

system_app_anr system_app_anr.png

data_app_crash data_app_crash.png