Android dropbox介绍

Posted Kevin张俊杰

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android dropbox介绍相关的知识,希望对你有一定的参考价值。

简介

系统服务dropbox以文件形式记录了系统各种异常信息,例如app crashnative crashanrkernel panic等等。

ADB查询

adb shell dumpsys dropbox

app接口

源码10.0

1、DropBoxManager dropbox = (DropBoxManager) getSystemService(Context.DROPBOX_SERVICE)
例如,dropbox.addText可实现把需要记录的数据丢给dropbox进行存储

2、监听广播android.intent.action.DROPBOX_ENTRY_ADDED,可知系统发生了异常
注意权限:android.permission.READ_LOGS --- 平台签名或priv-app

dropbox启动

  1. SystemServer:run
    SystemServer启动服务

    private void startOtherServices() 
        ···
        mSystemServiceManager.startService(DropBoxManagerService.class);
        ···
    
    
  2. DropBoxManagerService继承SystemService,启动顺序:构造方法 -->onStart

    a) 构造方法

    public DropBoxManagerService(final Context context, File path) 
        super(context);
        mDropBoxDir = path;//dropbox路径/data/system/dropbox
        mContentResolver = getContext().getContentResolver();
        mHandler = new Handler() 
            @Override
            public void handleMessage(Message msg) 
                if (msg.what == MSG_SEND_BROADCAST) 
                    getContext().sendBroadcastAsUser((Intent)msg.obj, UserHandle.SYSTEM,
                            android.Manifest.permission.READ_LOGS);
                
            
        ;
    
    

    b) onStart启动

    public void onStart() 
        // 监听低内存,保证dropbox不占用更多空间
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
        getContext().registerReceiver(mReceiver, filter);
    
        mContentResolver.registerContentObserver(
            Settings.Global.CONTENT_URI, true,
            new ContentObserver(new Handler()) 
                @Override
                public void onChange(boolean selfChange) 
                    mReceiver.onReceive(getContext(), (Intent) null);
                
            );
    
        //注册dropbox服务
        publishBinderService(Context.DROPBOX_SERVICE, mStub);
    
    
  3. 接口运用,发送广播DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED
    dropbox.add

     public void add(DropBoxManager.Entry entry) 
        ···
        try 
            ···
            final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
            dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag);
            dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time);
            if (!mBooted) 
                dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
            
            ···
            mHandler.sendMessage(mHandler.obtainMessage(MSG_SEND_BROADCAST, dropboxIntent));
         catch (IOException e) 
            Slog.e(TAG, "Can't write: " + tag, e);
         finally 
            IoUtils.closeQuietly(output);
            IoUtils.closeQuietly(input);
            entry.close();
            if (temp != null) temp.delete();
        
    
    

dropbox日志路径

/data/system/dropbox

adb shell ls -al /data/system/dropbox
total 432
drwx------  2 system system  4096 2021-12-23 06:02 .
drwxrwxr-x 16 system system  4096 2021-12-23 06:01 ..
-rw-------  1 system system   335 2022-01-25 14:40 SYSTEM_BOOT@1640210494810.txt
-rw-------  1 system system   334 2022-01-25 15:05 SYSTEM_BOOT@1640210494823.txt
-rw-------  1 system system   334 2021-12-23 06:01 SYSTEM_BOOT@1640210496077.txt
-rw-------  1 system system 19264 2022-01-25 14:40 SYSTEM_RECOVERY_KMSG@1640210494811.txt.gz
-rw-------  1 system system 19191 2022-01-25 15:05 SYSTEM_RECOVERY_KMSG@1640210494824.txt.gz
-rw-------  1 system system  5661 2022-01-25 14:40 SYSTEM_RECOVERY_LOG@1640210494809.txt.gz
-rw-------  1 system system  5076 2022-01-25 15:05 SYSTEM_RECOVERY_LOG@1640210494822.txt.gz
-rw-------  1 system system    30 2022-01-25 14:40 storage_trim@1640210494803.txt
-rw-------  1 system system  4192 2022-01-25 14:40 system_app_strictmode@1640210494804.txt.gz

记录的系统错误

系统正常启动后的自检工作

  1. SYSTEM_BOOT
    开机一次,记录一次

  2. SYSTEM_RESTART
    如果system_server在设备运行过程中异常,则会有记录

  3. SYSTEM_LAST_KMSG
    kernel异常。
    pstore是persistent storage的缩写,内核发生异常通过此把异常日志记录下来,方便定位问题。
    ramoops指的是采用ram保存oops信息(kernel 异常信息)的一个功能,利用pstore技术实现。

    kernel异常信息保存地:
    panic
    /proc/last_kmsg
    
    oops
    /sys/fs/pstore/console-ramoops
    /sys/fs/pstore/console-ramoops-0
    
  4. SYSTEM_TOMBSTONE
    TOMBSTONE是Android用来记录native进程崩溃的core dump日志, 系统服务在启动完成后会增加一个Observer来侦测tombstone日志文件的变化, 每当生成新的tombstone文件, 就会增加一条 SYSTEM_TOMBSTONE记录到DropBoxManager中。

  5. SYSTEM_RECOVERY_LOG/SYSTEM_RECOVERY_KMSG

    SYSTEM_RECOVERY_KMSG:recovery kerenl日志
    SYSTEM_RECOVERY_LOG:recovery 升级或恢复出厂设置等等日志
    
  6. SYSTEM_FSCK
    文件系统完整性校验日志

  7. SYSTEM_AUDIT
    kernel 异常信息的查漏补缺日志
    BootReceiver.java

     	private void logBootEvents(Context ctx) throws IOException 
            final DropBoxManager db = (DropBoxManager) ctx.getSystemService(Context.DROPBOX_SERVICE);
            final String headers = getBootHeadersToLogAndUpdate();
            final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
    
            String recovery = RecoverySystem.handleAftermath(ctx);
            if (recovery != null && db != null) 
                db.addText("SYSTEM_RECOVERY_LOG", headers + recovery);
            
    
            String lastKmsgFooter = "";
            if (bootReason != null) 
                lastKmsgFooter = new StringBuilder(512)
                    .append("\\n")
                    .append("Boot info:\\n")
                    .append("Last boot reason: ").append(bootReason).append("\\n")
                    .toString();
            
    
            HashMap<String, Long> timestamps = readTimestamps();
    
            if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) 
                if (StorageManager.inCryptKeeperBounce()) 
                    // Encrypted, first boot to get PIN/pattern/password so data is tmpfs
                    // Don't set ro.runtime.firstboot so that we will do this again
                    // when data is properly mounted
                 else 
                    String now = Long.toString(System.currentTimeMillis());
                    SystemProperties.set("ro.runtime.firstboot", now);
                
                if (db != null) db.addText("SYSTEM_BOOT", headers);
    
                // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
                // kernel panic日志,例如异常重启
                addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
                        "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
                addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
                        "/sys/fs/pstore/console-ramoops", -LOG_SIZE, "SYSTEM_LAST_KMSG");
                addFileWithFootersToDropBox(db, timestamps, headers, lastKmsgFooter,
                        "/sys/fs/pstore/console-ramoops-0", -LOG_SIZE, "SYSTEM_LAST_KMSG");
                
                //recovery日志。例如OTA升级或恢复出厂设置的时候
                addFileToDropBox(db, timestamps, headers, "/cache/recovery/log", -LOG_SIZE,
                        "SYSTEM_RECOVERY_LOG");
                addFileToDropBox(db, timestamps, headers, "/cache/recovery/last_kmsg",
                        -LOG_SIZE, "SYSTEM_RECOVERY_KMSG");
                
                //kernel日志的查漏补缺备份
                addAuditErrorsToDropBox(db, timestamps, headers, -LOG_SIZE, "SYSTEM_AUDIT");
             else 
                if (db != null) db.addText("SYSTEM_RESTART", headers);
            
            // log always available fs_stat last so that logcat collecting tools can wait until
            // fs_stat to get all file system metrics.
            logFsShutdownTime();
            logFsMountTime();
            //fsck文件系统校验日志收集
            //fsck(file system consistency check)是Unix和类Unix系统上用于检查文件系统完整性的工具
            addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
            logSystemServerShutdownTimeMetrics();
    
            // Scan existing tombstones (in case any new ones appeared)
            //native进程崩溃日志收集
            File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
            for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) 
                if (tombstoneFiles[i].isFile()) 
                    addFileToDropBox(db, timestamps, headers, tombstoneFiles[i].getPath(),
                            LOG_SIZE, "SYSTEM_TOMBSTONE");
                
            
    
            writeTimestamps(timestamps);
    
            // Start watching for new tombstone files; will record them as they occur.
            // This gets registered with the singleton file observer thread.
            // /data/tombstones目录监听收集
            sTombstoneObserver = new FileObserver(TOMBSTONE_DIR.getPath(), FileObserver.CREATE) 
                @Override
                public void onEvent(int event, String path) 
                    HashMap<String, Long> timestamps = readTimestamps();
                    try 
                        File file = new File(TOMBSTONE_DIR, path);
                        if (file.isFile() && file.getName().startsWith("tombstone_")) 
                            addFileToDropBox(db, timestamps, headers, file.getPath(), LOG_SIZE,
                                    TAG_TOMBSTONE);
                        
                     catch (IOException e) 
                        Slog.e(TAG, "Can't log tombstone", e);
                    
                    writeTimestamps(timestamps);
                
            ;
    
            sTombstoneObserver.startWatching();
        
    

java/native crash--- crash/native_crash

java/native层异常的区分在于eventType:crash/native_crash

ActivityManagerService

void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName,
        ApplicationErrorReport.CrashInfo crashInfo) 
    //event事件的日志记录:EventLogTags.AM_CRASH --> am_crash
    EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
            UserHandle.getUserId(Binder.getCallingUid()), processName,
            r == null ? -1 : r.info.flags,
            crashInfo.exceptionClassName,
            crashInfo.exceptionMessage,
            crashInfo.throwFileName,
            crashInfo.throwLineNumber);

    ···
    //加入到dropbox
    addErrorToDropBox(
            eventType, r, processName, null, null, null, null, null, null, crashInfo);
    //其他业务处理
    mAppErrors.crashApplication(r, crashInfo);

java层:handleApplicationCrashInner("crash", r, processName, crashInfo);
native层: mAm.handleApplicationCrashInner("native_crash", mApp, mApp.processName, ci);

anr 异常— anr

这里涉及广播、Service、Provider等组件的anr以及触摸按键事件的anr

ProcessRecord

void appNotResponding(String activityShortComponentName, ApplicationInfo aInfo,
        String parentShortComponentName, WindowProcessController parentProcess,
        boolean aboveSystem, String annotation) 
    ···
    //event事件的日志记录:EventLogTags.AM_ANR --> am_anr
    EventLog.writeEvent(EventLogTags.AM_ANR, userId, pid, processName, info.flags,
                annotation);
    ···
    //加入到dropbox
    mService.addErrorToDropBox("anr", this, processName, activityShortComponentName,
            parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null);
    ···

wtf(What a Terrible Failure)— wtf

android.util.Log.wtf(String, String),应用可调用布局异常点

ActivityManagerService

ProcessRecord handleApplicationWtfInner(int callingUid, int callingPid, IBinder app, String tag,
        final ApplicationErrorReport.CrashInfo crashInfo) 
    final ProcessRecord r = findAppProcess(app, "WTF");
    final String processName = app == null ? "system_server"
            : (r == null ? "unknown" : r.processName);
    //event事件的日志记录:EventLogTags.AM_WTF --> am_wtf
    EventLog.writeEvent(EventLogTags.AM_WTF, UserHandle.getUserId(callingUid), callingPid,
            processName, r == null ? -1 : r.info.flags, tag, crashInfo.exceptionMessage);
    ···
    //加入到dropbox
    addErrorToDropBox("wtf", r, processName, null, null, null, tag, null, null, crashInfo);

    return r;

注意:
当系统设置Settings.Global.WTF_IS_FATAL为1时,发送wtf可kill应用

strict mode—**_strictmode

严格模式,主要为性能监测使用

StrictMode (严格模式), 顾名思义, 就是在比正常模式检测得更严格, 通常用来监测不应当在主线程执行的网络, 文件等操作。任何 StrictMode 违例都会被 ActivityManagerService 在 DropBoxManager 中记录为一次 strict_mode 违例。

ActivityManagerService

public void handleApplicationStrictModeViolation(
        IBinder app,
        int penaltyMask,
        StrictMode.ViolationInfo info) 
    ···
    //需要满足触发dropbox的条件
    if ((penaltyMask & StrictMode.PENALTY_DROPBOX) != 0) 
        Integer stackFingerprint = info.hashCode();
        boolean logIt = true;
        ···
        if (logIt) //执行dropbox业务
            logStrictModeViolationToDropBox(r, info);
        
    

    ···


private void logStrictModeViolationToDropBox(
        ProcessRecord process,
        StrictMode.ViolationInfo info) 
    if (info == null) 
        return;
    
    //收集信息,tag:***_strictmode
    ···省略···
    
    //加入到dropbox
    IoThread.getHandler().post(() -> 
        dbox.addText(dropboxTag, res);
    );
 

lowmem—低内存报告

ActivityManagerService

final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) 
    // If there are no longer any background processes running,
    // and the app that died was not running instrumentation,
    // then tell everyone we are now low on memory.
    if (!mProcessList.haveBackgroundProcessLocked()) 
        ···
        //event事件的日志记录:EventLogTags.AM_LOW_MEMORY --> am_low_memory
        EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mProcessList.getLruSizeLocked());
        ···
        if (doReport) //如果报告,最后调入reportMemUsage
            Message msg = mHandler.obtainMessage(REPORT_MEM_USAGE_MSG, memInfos);
            mHandler.sendMessage(msg);
        
        ···
    


void reportMemUsage(ArrayList<ProcessMemInfo> memInfos) 
    ···
    addErrorToDropBox("lowmem", null, "system_server", null,
            null, null, tag.toString(), dropBuilder.toString(), null, null);
    ···

watchdog

如果 WatchDog 监测到系统进程(system_server)出现问题, 会增加一条 watchdog 记录到 DropBoxManager 中, 并终止系统进程的执行。

WatchDog

 public void run() 
        ···
        while (true) 
            ···
            //event事件的日志记录:EventLogTags.WATCHDOG --> watchdog
            EventLog.writeEvent(EventLogTags.WATCHDOG, name.isEmpty() ? subject : name);<

以上是关于Android dropbox介绍的主要内容,如果未能解决你的问题,请参考以下文章

appium 已解决Android,每次启动手机中都会安装Appium settings和Unclock的方法

Android之dropbox 分析

Dropbox无法连接怎么办

302 使用 Dropbox 短超链接在 Android 中从 http 重定向到 https

android之AndroidX介绍

在 android app 中访问 Dropbox、google drive、microsoft onedrive 等中的云共享文件