Android之dropbox 分析

簡(jiǎn)介

系統(tǒng)服務(wù)dropbox以文件形式記錄了系統(tǒng)各種異常信息,例如app crash、native crash、anr夺衍、kernel panic等等

adb查詢(xún)

adb shell dumpsys dropbox

app接口

源碼
10.0

1.DropBoxManager dropbox = (DropBoxManager) getSystemService(Context.DROPBOX_SERVICE)
例如出革,dropbox.addText 可實(shí)現(xiàn)把需要記錄的數(shù)據(jù)丟給dropbox進(jìn)行存儲(chǔ)

2.監(jiān)聽(tīng)廣播android.intent.action.DROPBOX_ENTRY_ADDED泳叠,可知系統(tǒng)發(fā)生了異常
注意權(quán)限:android.permission.READ_LOGS  -- 平臺(tái)簽名或priv-app

dropbox啟動(dòng)

1.SystemServer:run冲粤。SystemServer啟動(dòng)服務(wù)
private void startOtherServices() {
    ···
    mSystemServiceManager.startService(DropBoxManagerService.class);
    ···
}

2.DropBoxManagerService繼承SystemService,啟動(dòng)順序:構(gòu)造方法 -->onStart
    a)構(gòu)造方法
    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啟動(dòng)
    public void onStart() {
        // 監(jiān)聽(tīng)低內(nèi)存菜拓,保證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);
                }
            });

        //注冊(cè)dropbox服務(wù)
        publishBinderService(Context.DROPBOX_SERVICE, mStub);
    }

3.接口運(yùn)用,發(fā)送廣播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

C:\Users\99418>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

記錄的系統(tǒng)錯(cuò)誤
1.系統(tǒng)正常啟動(dòng)后的自檢工作
1)SYSTEM_BOOT
開(kāi)機(jī)一次笛厦,記錄一次

2)SYSTEM_RESTART
如果system_server在設(shè)備運(yùn)行過(guò)程中異常纳鼎,則會(huì)有記錄

3)SYSTEM_LAST_KMSG
kernel異常。
pstore是persistent storage的縮寫(xiě),內(nèi)核發(fā)生異常通過(guò)此把異常日志記錄下來(lái)喷橙,方便定位問(wèn)題啥么。
ramoops指的是采用ram保存oops信息(kernel 異常信息)的一個(gè)功能,利用pstore技術(shù)實(shí)現(xiàn)贰逾。

kernel異常信息保存地:
panic
/proc/last_kmsg

oops
/sys/fs/pstore/console-ramoops
/sys/fs/pstore/console-ramoops-0

4)SYSTEM_TOMBSTONE
TOMBSTONE 是 Android 用來(lái)記錄 native 進(jìn)程崩潰的 core dump 日志, 系統(tǒng)服務(wù)在啟動(dòng)完成后會(huì)增加一個(gè) Observer 來(lái)偵測(cè) tombstone 日志文件的變化, 每當(dāng)生成新的 tombstone 文件, 就會(huì)增加一條 SYSTEM_TOMBSTONE 記錄到 DropBoxManager 中.

5)SYSTEM_RECOVERY_LOG/SYSTEM_RECOVERY_KMSG
SYSTEM_RECOVERY_KMSG:recovery kerenl日志
SYSTEM_RECOVERY_LOG:recovery 升級(jí)或恢復(fù)出廠(chǎng)設(shè)置等等日志

6)SYSTEM_FSCK
文件系統(tǒng)完整性校驗(yàn)日志

7)SYSTEM_AUDIT
kernel 異常信息的查漏補(bǔ)缺日志

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升級(jí)或恢復(fù)出廠(chǎng)設(shè)置的時(shí)候
            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日志的查漏補(bǔ)缺備份
            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文件系統(tǒng)校驗(yàn)日志收集
        //fsck(file system consistency check)是Unix和類(lèi)Unix系統(tǒng)上用于檢查文件系統(tǒng)完整性的工具
        addFsckErrorsToDropBoxAndLogFsStat(db, timestamps, headers, -LOG_SIZE, "SYSTEM_FSCK");
        logSystemServerShutdownTimeMetrics();

        // Scan existing tombstones (in case any new ones appeared)
        //native進(jìn)程崩潰日志收集
        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目錄監(jiān)聽(tīng)收集
        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();
    }

2.java/native crash疙剑。-- crash/native_crash
java/native層異常的區(qū)分在于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);
        //其他業(yè)務(wù)處理
        mAppErrors.crashApplication(r, crashInfo);
    }

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

3.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);
        ···
    }

4.wtf(What a Terrible Failure)嚼蚀。--- wtf
android.util.Log.wtf(String, String),應(yīng)用可調(diào)用布局異常點(diǎn)

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;
    }
注意:
當(dāng)系統(tǒng)設(shè)置Settings.Global.WTF_IS_FATAL為1時(shí)管挟,發(fā)送wtf可kill應(yīng)用

5.strict mode轿曙。---**_strictmode
嚴(yán)格模式,主要為性能監(jiān)測(cè)使用
StrictMode (嚴(yán)格模式), 顧名思義, 就是在比正常模式檢測(cè)得更嚴(yán)格, 通常用來(lái)監(jiān)測(cè)不應(yīng)當(dāng)在主線(xiàn)程執(zhí)行的網(wǎng)絡(luò), 文件等操作. 任何 StrictMode 違例都會(huì)被 ActivityManagerService 在 DropBoxManager 中記錄為一次 strict_mode 違例.

ActivityManagerService

    public void handleApplicationStrictModeViolation(
            IBinder app,
            int penaltyMask,
            StrictMode.ViolationInfo info) {
        ···
        //需要滿(mǎn)足觸發(fā)dropbox的條件
        if ((penaltyMask & StrictMode.PENALTY_DROPBOX) != 0) {
            Integer stackFingerprint = info.hashCode();
            boolean logIt = true;
            ···
            if (logIt) {//執(zhí)行dropbox業(yè)務(wù)
                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);
        });
    } 

6.lowmem导帝。低內(nèi)存報(bào)告

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) {//如果報(bào)告,最后調(diào)入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);
        ···
    }

7.watchdog
如果 WatchDog 監(jiān)測(cè)到系統(tǒng)進(jìn)程(system_server)出現(xiàn)問(wèn)題, 會(huì)增加一條 watchdog 記錄到 DropBoxManager 中, 并終止系統(tǒng)進(jìn)程的執(zhí)行.

WatchDog
    public void run() {
        ···
        while (true) {
            ···
            //event事件的日志記錄:EventLogTags.WATCHDOG --> watchdog
            EventLog.writeEvent(EventLogTags.WATCHDOG, name.isEmpty() ? subject : name);
            ···
            /// M: WDT debug enhancement
            /// need to wait the AEE dumps all info, then kill system server @{
            // Try to add the error to the dropbox, but assuming that the ActivityManager
            // itself may be deadlocked.  (which has happened, causing this statement to
            // deadlock and the watchdog as a whole to be ineffective)
            Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
                    public void run() {
                        //加入到dropbox
                        if (mActivity != null) {
                            mActivity.addErrorToDropBox(
                                    "watchdog", null, "system_server", null, null, null,
                                    name.isEmpty() ? subject : name, cpuInfo, stack, null);
                        }
                        StatsLog.write(StatsLog.SYSTEM_SERVER_WATCHDOG_OCCURRED, subject);
                    }
                };
            dropboxThread.start();
            try {
                dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
            } catch (InterruptedException ignored) {}

            ···
        }
    }

8.其他
1)netstats_error/netstats_dump
NetworkStatsService 負(fù)責(zé)收集并持久化存儲(chǔ)網(wǎng)絡(luò)狀態(tài)的統(tǒng)計(jì)數(shù)據(jù), 當(dāng)遇到明顯的網(wǎng)絡(luò)狀態(tài)錯(cuò)誤時(shí), 它會(huì)增加一條 netstats_error 記錄到 DropBoxManager.

NetworkStatsService
    private static final String TAG_NETSTATS_ERROR = "netstats_error";

    private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
        @Override
        public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
                int rightIndex, String cookie) {
            Log.w(TAG, "Found non-monotonic values; saving to dropbox");

            // record error for debugging
            final StringBuilder builder = new StringBuilder();
            builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
                    + "] - right[" + rightIndex + "]\n");
            builder.append("left=").append(left).append('\n');
            builder.append("right=").append(right).append('\n');

            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
                    builder.toString());
        }

        @Override
        public void foundNonMonotonic(
                NetworkStats stats, int statsIndex, String cookie) {
            Log.w(TAG, "Found non-monotonic values; saving to dropbox");

            final StringBuilder builder = new StringBuilder();
            builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
            builder.append("stats=").append(stats).append('\n');

            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
                    builder.toString());
        }
    }
    
NetworkStatsRecorder
    private static final String TAG_NETSTATS_DUMP = "netstats_dump";

    private void recoverFromWtf() {
        if (DUMP_BEFORE_DELETE) {
            ···
            mDropBox.addData(TAG_NETSTATS_DUMP, os.toByteArray(), 0);
        }
        ···
    }

2)BATTERY_DISCHARGE_INFO
BatteryService 負(fù)責(zé)檢測(cè)充電狀態(tài), 并更新手機(jī)電池信息. 當(dāng)遇到明顯的 discharge 事件, 它會(huì)增加一條 BATTERY_DISCHARGE_INFO 記錄到 DropBoxManager.

    // TODO: Current code doesn't work since "--unplugged" flag in BSS was purposefully removed.
    private void logBatteryStatsLocked() {
        ···
        DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
        ···
        try {
            ··· 
            // add dump file to drop box
            db.addFile("BATTERY_DISCHARGE_INFO", dumpFile, DropBoxManager.IS_TEXT);
        }
        ···
    }

3)storage_benchmark/storage_trim
StorageManagerService 負(fù)責(zé)存儲(chǔ)設(shè)備管理穿铆,例如sdcard或usb mass storage
fstrim提升磁盤(pán)性能您单,緩解Android卡頓

private static final String TAG_STORAGE_BENCHMARK = "storage_benchmark";
private static final String TAG_STORAGE_TRIM = "storage_trim";
    
public void benchmark(String volId, IVoldTaskListener listener) {
    ···
    mVold.benchmark(volId, new IVoldTaskListener.Stub() {
        ···
        final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
        dropBox.addText(TAG_STORAGE_BENCHMARK, scrubPath(path)
                    + " " + ident + " " + create + " " + run + " " + destroy);
    ···
        
    });
}

public void fstrim(int flags, IVoldTaskListener listener) {
    ···
    mVold.fstrim(flags, new IVoldTaskListener.Stub() {
        @Override
        public void onStatus(int status, PersistableBundle extras) {
            ···
            final DropBoxManager dropBox = mContext.getSystemService(DropBoxManager.class);
                dropBox.addText(TAG_STORAGE_TRIM, scrubPath(path) + " " + bytes + " " + time);
            ···
            }
            ···
        });
    ···
}

4)network_watchlist_report
NetworkWatchlistService

WatchlistLoggingHandler

    private static final String DROPBOX_TAG = "network_watchlist_report";

    private void tryAggregateRecords(long lastRecordTime) {
        try {
            ···
            if (mDropBoxManager != null && mDropBoxManager.isTagEnabled(DROPBOX_TAG)) {
                ···
                if (encodedResult != null) {
                    addEncodedReportToDropBox(encodedResult);
                }
            } else {
                ···
            }
            ···
        } finally {
            ···
        }
    }
    
    private void addEncodedReportToDropBox(byte[] encodedReport) {
        mDropBoxManager.addData(DROPBOX_TAG, encodedReport, 0);
    }

5)incident
frameworks/base/cmds/incidentd

Broadcaster.cpp
Status status = dropbox->addFile(String16("incident"), readFd, 0);

6)keymaster
system/security/keystore

operation_proto_handler.cpp
    android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager);
    size_t size = opConfigEvents.ByteSize();
    auto data = std::make_unique<uint8_t[]>(size);
    opConfigEvents.SerializeWithCachedSizesToArray(data.get());
    dropbox->addData(android::String16("keymaster"), data.get(), size, 0);

key_proto_handler.cpp
    android::sp<android::os::DropBoxManager> dropbox(new android::os::DropBoxManager());
    keyConfig.set_was_creation_successful(wasCreationSuccessful);
    size_t size = keyConfig.ByteSize();
    auto data = std::make_unique<uint8_t[]>(size);
    keyConfig.SerializeWithCachedSizesToArray(data.get());
    dropbox->addData(android::String16("keymaster"), data.get(), size, 0);

參考學(xué)習(xí)

http://xiaocong.github.io/blog/2012/11/21/to-introduce-android-dropboxmanager-service/
http://huaqianlee.github.io/2020/11/13/Android/pstore/
http://tjtech.me/analyze-pstore-ramoops-in-android-kernel.html
https://blog.csdn.net/zangdongming/article/details/37729315
https://skytoby.github.io/2019/fstrim/
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市荞雏,隨后出現(xiàn)的幾起案子虐秦,更是在濱河造成了極大的恐慌,老刑警劉巖凤优,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悦陋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡筑辨,警方通過(guò)查閱死者的電腦和手機(jī)俺驶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)挖垛,“玉大人痒钝,你說(shuō)我怎么就攤上這事×《荆” “怎么了送矩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)哪替。 經(jīng)常有香客問(wèn)我栋荸,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任晌块,我火速辦了婚禮爱沟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匆背。我一直安慰自己呼伸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布钝尸。 她就那樣靜靜地躺著括享,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珍促。 梳的紋絲不亂的頭發(fā)上铃辖,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音猪叙,去河邊找鬼娇斩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛穴翩,可吹牛的內(nèi)容都是我干的犬第。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼藏否,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瓶殃!你這毒婦竟也來(lái)了充包?” 一聲冷哼從身側(cè)響起副签,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎基矮,沒(méi)想到半個(gè)月后淆储,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡家浇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年本砰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钢悲。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡点额,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出莺琳,到底是詐尸還是另有隱情还棱,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布惭等,位于F島的核電站珍手,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜琳要,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一寡具、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稚补,春花似錦童叠、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至撰豺,卻和暖如春粪般,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背污桦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工亩歹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人凡橱。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓小作,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親稼钩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子顾稀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 最近工作中需要對(duì)Crash的應(yīng)用進(jìn)行處理,看了下Android有提供相關(guān)的Manager對(duì)各類(lèi)異常進(jìn)行記錄坝撑,也就是...
    Viking_Den閱讀 10,985評(píng)論 1 9
  • 作者:lds(lds2012@gmail.com) 日期:2017-03-24 一. 項(xiàng)目簡(jiǎn)介 ACRA是Goog...
    駱駝騎士閱讀 3,800評(píng)論 0 9
  • monkey: 一:需覆蓋的測(cè)試場(chǎng)景: 1静秆、需覆蓋機(jī)型:oppo vivo 華為 小米(這是寶玩app的用戶(hù)量前4...
    野子木夕閱讀 1,037評(píng)論 0 0
  • 來(lái)到新公司也有一個(gè)月了,最近一直都是在跟進(jìn)公司的項(xiàng)目在友盟和bugly的Crash相關(guān)的問(wèn)題巡李,現(xiàn)在更進(jìn)的項(xiàng)...
    Android開(kāi)發(fā)_Hua閱讀 2,413評(píng)論 0 2
  • 目錄總結(jié) 01.拋出異常導(dǎo)致崩潰分析 02.RuntimeInit類(lèi)分析 03.Looper停止App就退出嗎 0...
    楊充211閱讀 1,739評(píng)論 1 5