Watchdog 源码分析

来源:互联网 发布:网络文凭如何取得 编辑:程序博客网 时间:2024/05/16 05:59
public class Watchdog extends Thread {    static final String TAG = "Watchdog";    // Set this to true to use debug default values.    static final boolean DB = false;    // Set this to true to have the watchdog record kernel thread stacks when it fires    static final boolean RECORD_KERNEL_THREADS = true;    static final long DEFAULT_TIMEOUT = DB ? 10*1000 : 60*1000;    static final long CHECK_INTERVAL = DEFAULT_TIMEOUT / 2;    // These are temporally ordered: larger values as lateness increases    static final int COMPLETED = 0;    static final int WAITING = 1;    static final int WAITED_HALF = 2;    static final int OVERDUE = 3;    static final int TIME_SF_WAIT = 20000;    // Which native processes to dump into dropbox's stack traces    public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] {        "/system/bin/mediaserver",        "/system/bin/sdcard",        "/system/bin/surfaceflinger"    };    static Watchdog sWatchdog;    ExceptionLog exceptionHWT;    private ServerSocket mServerSocket = null;    private static final int PROT = 23233;    private Socket mSocket = null;    /* This handler will be used to post message back onto the main thread */    final ArrayList<HandlerChecker> mHandlerCheckers = new ArrayList<>();    final HandlerChecker mMonitorChecker;    ContentResolver mResolver;    ActivityManagerService mActivity;    int mPhonePid;    IActivityController mController;    boolean mAllowRestart = true;    public long GetSFStatus() {        if (exceptionHWT != null) {         return exceptionHWT.SFMatterJava(0, 0);        } else {        return 0;    }    }    public static int GetSFReboot() {        return SystemProperties.getInt("service.sf.reboot", 0);    }    public static void SetSFReboot() {        int OldTime = SystemProperties.getInt("service.sf.reboot", 0);        OldTime = OldTime + 1;        if (OldTime > 9) OldTime = 9;        SystemProperties.set("service.sf.reboot", String.valueOf(OldTime));    }    /**     * Used for checking status of handle threads and scheduling monitor callbacks.     */    public final class HandlerChecker implements Runnable {        private final Handler mHandler;        public final String mName;        private final long mWaitMax;        public final ArrayList<Monitor> mMonitors = new ArrayList<Monitor>();        private boolean mCompleted;        private Monitor mCurrentMonitor;        private long mStartTime;        HandlerChecker(Handler handler, String name, long waitMaxMillis) {            mHandler = handler;            mName = name;            mWaitMax = waitMaxMillis;            mCompleted = true;        }        public void addMonitor(Monitor monitor) {            Log.d("hecheng_watchdog", "addMonitor");            mMonitors.add(monitor);        }        //检测本 handlerChecker 线程是否ok        public void scheduleCheckLocked() {            if (mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) {                // If the target looper has recently been polling, then                // there is no reason to enqueue our checker on it since that                // is as good as it not being deadlocked.  This avoid having                // to do a context switch to check the thread.  Note that we                // only do this if mCheckReboot is false and we have no                // monitors, since those would need to be executed at this point.                mCompleted = true;                return;            }            //如果其一次检测没有完成返回。            if (!mCompleted) {                // we already have a check in flight, so no need                return;            }            mCompleted = false;            mCurrentMonitor = null;            //给被监控的进程发送消息            //监控线程受到消息后会调用 HandlerChecker的run 方法。            //mStartTime 记录本handlerChecker 开始检测的时间            mStartTime = SystemClock.uptimeMillis();            mHandler.postAtFrontOfQueue(this);        }        //判断当前handlerChcker是否超时        public boolean isOverdueLocked() {            return (!mCompleted) && (SystemClock.uptimeMillis() > mStartTime + mWaitMax);        }        //如果没有COMPLETED,获取其超时时间,并返回对应的值        //超时时间小于指定时间的一般(一般为30s),返回WAITING, 系统会继续等待不做处理        //超时时间大于 30s 小于指定时间,返回WAITED_HALF, 系统会dump出运行所有进程堆栈,然后继续等待        //超过超时时间返回OVEROUE,系统会dump堆栈,并重启        public int getCompletionStateLocked() {            if (mCompleted) {                return COMPLETED;            } else {                long latency = SystemClock.uptimeMillis() - mStartTime;                if (latency < mWaitMax/2) {                    return WAITING;                } else if (latency < mWaitMax) {                    return WAITED_HALF;                }            }            return OVERDUE;        }        public Thread getThread() {            return mHandler.getLooper().getThread();        }        public String getName() {            return mName;        }        public String describeBlockedStateLocked() {            if (mCurrentMonitor == null) {                return "Blocked in handler on " + mName + " (" + getThread().getName() + ")";            } else {                return "Blocked in monitor " + mCurrentMonitor.getClass().getName()                        + " on " + mName + " (" + getThread().getName() + ")";            }        }        //调用到此处说明,此线程的handler 是通畅的可以正常接受消息        @Override        public void run() {            //监控 此线程内添加的monitor 对象,是否存在死锁情况,            final int size = mMonitors.size();            for (int i = 0 ; i < size ; i++) {                synchronized (Watchdog.this) {                    mCurrentMonitor = mMonitors.get(i);                }                mCurrentMonitor.monitor();            }            //此线程内的monitor 不存在死锁情况,handlerChecker基本上就通过了。            Log.d("hecheng_watchdog", "Thread is " + mName + ", size is " + size);            synchronized (Watchdog.this) {                mCompleted = true;                mCurrentMonitor = null;            }        }    }    final class RebootRequestReceiver extends BroadcastReceiver {        @Override        public void onReceive(Context c, Intent intent) {            if (intent.getIntExtra("nowait", 0) != 0) {                rebootSystem("Received ACTION_REBOOT broadcast");                return;            }            if (intent.getIntExtra("hangdump", 0) != 0) {                Slog.i(TAG, "Receiver hangdump start!\n");                runHangdump();                return;            }            Slog.w(TAG, "Unsupported ACTION_REBOOT broadcast: " + intent);        }    }    /** Monitor for checking the availability of binder threads. The monitor will block until     * there is a binder thread available to process in coming IPCs to make sure other processes     * can still communicate with the service.     */    private static final class BinderThreadMonitor implements Watchdog.Monitor {        @Override        public void monitor() {            Binder.blockUntilThreadAvailable();        }    }    public interface Monitor {        void monitor();    }    public static Watchdog getInstance() {        if (sWatchdog == null) {            sWatchdog = new Watchdog();        }        return sWatchdog;    }    private Watchdog() {        super("watchdog");        // Initialize handler checkers for each common thread we want to check.  Note        // that we are not currently checking the background thread, since it can        // potentially hold longer running operations with no guarantees about the timeliness        // of operations there.        // The shared foreground thread is the main checker.  It is where we        // will also dispatch monitor checks and do other work.        //watchdog 检测多个线程,超时时间是 60秒,        //HandlerChecker 是通过检测handler 来检测线程是否堵塞        //TODO        mMonitorChecker = new HandlerChecker(FgThread.getHandler(),                "foreground thread", DEFAULT_TIMEOUT);        mHandlerCheckers.add(mMonitorChecker);        // Add checker for main thread.  We only do a quick check since there        // can be UI running on the thread.        mHandlerCheckers.add(new HandlerChecker(new Handler(Looper.getMainLooper()),                "main thread", DEFAULT_TIMEOUT));        // Add checker for shared UI thread.        mHandlerCheckers.add(new HandlerChecker(UiThread.getHandler(),                "ui thread", DEFAULT_TIMEOUT));        // And also check IO thread.        mHandlerCheckers.add(new HandlerChecker(IoThread.getHandler(),                "i/o thread", DEFAULT_TIMEOUT));        mHandlerCheckers.add(new HandlerChecker(DisplayThread.getHandler(),                "display thread", DEFAULT_TIMEOUT));        if (SystemProperties.get("ro.have_aee_feature").equals("1")) {            exceptionHWT = new ExceptionLog();            runHangdumpServer();        }    }    public void setLight() {        Slog.i(TAG, "runHangdump-server-start setLight!\n");        Light tNotificationLight = null;        LightsManager tLights =  LocalServices.getService(LightsManager.class);        tNotificationLight = tLights.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS);        tNotificationLight.setFlashing(0xFF0000FF, Light.LIGHT_FLASH_NONE,                                   1000, 1000);        Slog.i(TAG, "runHangdump-server-start setLight end!\n");    }    public void runHangdump() {        Slog.i(TAG, "runHangdump-server-start thread!\n");        new Thread(new Runnable() {            @Override            public void run() {                Slog.i(TAG, "runHangdump-server hangdump thread start!\n");                final ArrayList<HandlerChecker> blockedCheckers;                String subject;                exceptionHWT.WDTMatterJava(52325);                setLight();                // trace and wait another half.                if (exceptionHWT != null) exceptionHWT.WDTMatterJava(60);                dumpAllBackTraces(true);                Slog.i(TAG, "runHangdump-server thread dumpAllBackTraces first end!\n");                SystemClock.sleep(30000);                Slog.i(TAG, "runHangdump-server thread get subject start!\n");                blockedCheckers = getBlockedCheckersLocked();                subject = describeCheckersLocked(blockedCheckers);                EventLog.writeEvent(EventLogTags.WATCHDOG, subject);                Slog.i(TAG, "runHangdump-server thread get subject end!\n");                if (exceptionHWT != null) exceptionHWT.WDTMatterJava(60);                dumpAllBackTraces(true);                Slog.i(TAG, "runHangdump-server thread dumpAllBackTraces second end!\n");                SystemClock.sleep(2000);                Slog.i(TAG, "runHangdump-server thread get dumpKernelStackTraces start!\n");                dumpKernelStackTraces();                // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log                doSysRq('w');                doSysRq('l');                Slog.i(TAG, "runHangdump-server thread get dumpKernelStackTraces end!\n");                Slog.i(TAG, "runHangdump-server thread start addErrorToDropbox!\n");                mActivity.addErrorToDropBox("watchdog", null, "system_server", null, null, subject, null, null, null);                Slog.i(TAG, "runHangdump-server thread addErrorToDropBox end!subject:" + "subject!" + "\n");                SystemClock.sleep(2000);                if (exceptionHWT != null) {                    Slog.i(TAG, "runHangdump-server exceptionHWT start!\n");                    exceptionHWT.WDTMatterJava(52323);                }            }        }).start();    }    public void runHangdumpServer() {        Slog.i(TAG, "runHangdumpServer start!\n");        new Thread(new Runnable() {            @Override            public void run() {                Slog.i(TAG, "runHangdumpServer thread!\n");                try{                    if (mServerSocket == null) {                        Slog.i(TAG, "runHangdumpServer ServerSocket(prot):" + PROT + "!\n");                        mServerSocket= new ServerSocket(PROT);                        while(true){                            Slog.i(TAG, "runHangdumpServer accept!\n");                            mSocket = mServerSocket.accept();                            InputStream inputStream = mSocket.getInputStream();                            OutputStream outputStream = mSocket.getOutputStream();                            DataInputStream mDataInputStream = new DataInputStream(new BufferedInputStream(inputStream));                            byte[] data = new byte[16];                            int len = mDataInputStream.read(data);                            String msg = new String(data, "UTF-8");                            Slog.i(TAG, "runHangdumpServer thread msg: " + msg + "\n");                            while(msg!=null){                                Slog.i(TAG, "runHangdumpServer write!\n");                                outputStream.write("hello runHangdumpServer ok!\n".getBytes());                                outputStream.flush();                                if (msg.equals("start_hangdump_j")) {                                    Slog.i(TAG, "runHangdumpServer thread_j start!\n");                                    runHangdump();                                } else if (msg.equals("start_hangdump_c")) {                                    Slog.i(TAG, "runHangdumpServer thread_c start!\n");                                    runHangdump();                                }                                break;                            }                        }                    }                } catch(Exception e){                    Slog.w(TAG, "mServerSocket exception", e);                } finally {                    Slog.i(TAG, "mServerSocket finally!\n");                    try {                        mSocket.close();                        mSocket = null;                        mServerSocket.close();                        mServerSocket = null;                    } catch (IOException e) {                        Slog.w(TAG, "mServerSocket IOException", e);                    }                }            }        }).start();    }    public void init(Context context, ActivityManagerService activity) {        mResolver = context.getContentResolver();        mActivity = activity;        context.registerReceiver(new RebootRequestReceiver(),                new IntentFilter(Intent.ACTION_REBOOT),                android.Manifest.permission.REBOOT, null);        if(exceptionHWT!= null){                exceptionHWT.WDTMatterJava(0);        }    }    public void processStarted(String name, int pid) {        synchronized (this) {            if ("com.android.phone".equals(name)) {                mPhonePid = pid;            }        }    }    public void setActivityController(IActivityController controller) {        synchronized (this) {            mController = controller;        }    }    public void setAllowRestart(boolean allowRestart) {        synchronized (this) {            mAllowRestart = allowRestart;        }    }    //addMonitor  添加 fg线程内的对象monitor,在检测fg线程时,并检测其添加的对象,是否存在死锁。    //检测顺序为,先检测fg线程的handler是否可以正常接受信息,然后检测其添加的monitor 是否存在死锁    public void addMonitor(Monitor monitor) {        synchronized (this) {            if (isAlive()) {                throw new RuntimeException("Monitors can't be added once the Watchdog is running");            }            mMonitorChecker.addMonitor(monitor);        }    }    //addThread 添加要检测的 线程,默认时间为60s,可以指定时间时间    public void addThread(Handler thread) {        addThread(thread, DEFAULT_TIMEOUT);    }    public void addThread(Handler thread, long timeoutMillis) {        synchronized (this) {            if (isAlive()) {                throw new RuntimeException("Threads can't be added once the Watchdog is running");            }            final String name = thread.getLooper().getThread().getName();            mHandlerCheckers.add(new HandlerChecker(thread, name, timeoutMillis));        }    }    /**     * Perform a full reboot of the system.     */    void rebootSystem(String reason) {        Slog.i(TAG, "Rebooting system because: " + reason);        IPowerManager pms = (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE);        try {            pms.reboot(false, reason, false);        } catch (RemoteException ex) {        }    }    //检测所有的handlerChecker,看其中是否存在超时的现象。    private int evaluateCheckerCompletionLocked() {        int state = COMPLETED;        //遍历检测handlerChecker 看是否存在超时现象。        for (int i=0; i<mHandlerCheckers.size(); i++) {            HandlerChecker hc = mHandlerCheckers.get(i);            state = Math.max(state, hc.getCompletionStateLocked());//getCompletionStateLocked 检测对应的线程的handlerChecker是否超时        }        return state;    }    private ArrayList<HandlerChecker> getBlockedCheckersLocked() {        ArrayList<HandlerChecker> checkers = new ArrayList<HandlerChecker>();        for (int i=0; i<mHandlerCheckers.size(); i++) {            HandlerChecker hc = mHandlerCheckers.get(i);            if (hc.isOverdueLocked()) {                checkers.add(hc);            }        }        return checkers;    }    private String describeCheckersLocked(ArrayList<HandlerChecker> checkers) {        StringBuilder builder = new StringBuilder(128);        for (int i=0; i<checkers.size(); i++) {            if (builder.length() > 0) {                builder.append(", ");            }            builder.append(checkers.get(i).describeBlockedStateLocked());        }        return builder.toString();    }/*    private void CputimeEnable(String bootevent){     try {            FileOutputStream fcputime = new FileOutputStream("/proc/mtprof/cputime");            fcputime.write(bootevent.getBytes());            fcputime.close();        } catch (FileNotFoundException e) {            Slog.e(TAG, "cputime entry can not found!", e);        } catch (java.io.IOException e) {            Slog.e(TAG, "cputime entry open fail", e);        }    }*/    //watchdog 监控开始    @Override    public void run() {        boolean waitedHalf = false;        boolean mNeedDump = false;        boolean mSFHang = false;        while (true) {            final ArrayList<HandlerChecker> blockedCheckers;            String subject;            mSFHang = false;            if (exceptionHWT != null) {                exceptionHWT.WDTMatterJava(60);            }            if (mNeedDump) {                        // We've waited half the deadlock-detection interval.  Pull a stack                // trace and wait another half.                if (exceptionHWT != null) exceptionHWT.WDTMatterJava(60);                dumpAllBackTraces(true);                mNeedDump = false;            }            final boolean allowRestart;            int debuggerWasConnected = 0;            Slog.w(TAG, "SWT Watchdog before synchronized:" + SystemClock.uptimeMillis());            synchronized (this) {                Slog.w(TAG, "SWT Watchdog after synchronized:" + SystemClock.uptimeMillis());                long timeout = CHECK_INTERVAL;                long SFHangTime;                // Make sure we (re)spin the checkers that have become idle within                // this wait-and-check interval                //TODO 遍历所有的handlerChecker, 向他们发送消息看线程是否ok。                //如果handlerChecker的前一次检测没有完成,那么此handlerchecker 线程跳过本次检测。                for (int i=0; i<mHandlerCheckers.size(); i++) {                    HandlerChecker hc = mHandlerCheckers.get(i);                    Log.d("hecheng_watchdog", "hc is " + hc.mName + ", mMonitors size is " + hc.mMonitors.size());                    hc.scheduleCheckLocked();                }                if (debuggerWasConnected > 0) {                    debuggerWasConnected--;                }                // NOTE: We use uptimeMillis() here because we do not want to increment the time we                // wait while asleep. If the device is asleep then the thing that we are waiting                // to timeout on is asleep as well and won't have a chance to run, causing a false                // positive on when to kill things.                //CputimeEnable(new String("1"));                long start = SystemClock.uptimeMillis();                //设置此循环是为了防止,被异常唤醒,确保wait 时间为 30s                while (timeout > 0) {                    if (Debug.isDebuggerConnected()) {                        debuggerWasConnected = 2;                    }                    try {                        Slog.w(TAG, "SWT Watchdog before wait timeout:" + timeout);                        Slog.w(TAG, "SWT Watchdog before wait current time:" + SystemClock.uptimeMillis());                        Slog.w(TAG, "SWT Watchdog before wait start:" + start);                        Slog.w(TAG, "SWT Watchdog before wait CHECK_INTERVAL:" + CHECK_INTERVAL);                        wait(timeout);                        Slog.w(TAG, "SWT Watchdog after wait current time:" + SystemClock.uptimeMillis());                    } catch (InterruptedException e) {                        Log.wtf(TAG, e);                    }                    if (Debug.isDebuggerConnected()) {                        debuggerWasConnected = 2;                    }                    //CHECK_INTERVAL 30s, 那么相当于watchdog  30 秒检测一次                    timeout = CHECK_INTERVAL - (SystemClock.uptimeMillis() - start);                }                //MTK enhance                SFHangTime = GetSFStatus();                Slog.w(TAG, "**Get SF Time **" + SFHangTime);                if (SFHangTime > TIME_SF_WAIT * 2) {                    Slog.v(TAG, "**SF hang Time **" + SFHangTime);                    mSFHang = true;                } //@@                else {                    //检测是否存在超时的线程                    final int waitState = evaluateCheckerCompletionLocked();                    //COMPLETED  无超时进程                    //WAITING  有等待进程,0< 等待时间< 超时时间/2                    //WAITED_HALF  有等待进程,超时时间/2 < 等待时间 < 超时时间                    if (waitState == COMPLETED) {                        Slog.v(TAG, "**COMPLETED **");                        // The monitors have returned; reset                        waitedHalf = false;                        //CputimeEnable(new String("0"));                        continue;                    } else if (waitState == WAITING) {                        Slog.v(TAG, "**WAITING **");                        // still waiting but within their configured intervals; back off and recheck                       // CputimeEnable(new String("0"));                        continue;                    } else if (waitState == WAITED_HALF) {                        Slog.v(TAG, "**WAITED_HALF **");                        if (!waitedHalf) {                            Slog.v(TAG, "**waitedHalf **");                            // We've waited half the deadlock-detection interval.  Pull a stack                            // trace and wait another half.                            mNeedDump = true;                            waitedHalf = true;                        }                        continue;                    }                    }                //handlerChecker 超时                //something is overdue!                blockedCheckers = getBlockedCheckersLocked();//获取所有超时的handlerChecker                subject = describeCheckersLocked(blockedCheckers);// 获取String ,看是 handler time out, 还是  monitor time out.                allowRestart = mAllowRestart;            }            //CputimeEnable(new String("0"));            // If we got here, that means that the system is most likely hung.            // First collect stack traces from all threads of the system process.            // Then kill this process so that the system will restart.            Slog.e(TAG, "**SWT happen **" + subject);            if (mSFHang && subject.isEmpty()) {                subject = "surfaceflinger  hang.";            }            EventLog.writeEvent(EventLogTags.WATCHDOG, subject);            if (exceptionHWT != null) exceptionHWT.WDTMatterJava(60);            dumpAllBackTraces(false);            // Give some extra time to make sure the stack traces get written.            // The system's been hanging for a minute, another second or two won't hurt much.            SystemClock.sleep(2000);            // Pull our own kernel thread stacks as well if we're configured for that            if (RECORD_KERNEL_THREADS) {                dumpKernelStackTraces();            }            // Trigger the kernel to dump all blocked threads, and backtraces on all CPUs to the kernel log            doSysRq('w');            doSysRq('l');            /// 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() {                        mActivity.addErrorToDropBox(                                "watchdog", null, "system_server", null, null,                                name, null, stack, null);                    }                };            dropboxThread.start();            try {                dropboxThread.join(2000);  // wait up to 2 seconds for it to return.            } catch (InterruptedException ignored) {}            */            Slog.v(TAG, "** save all info before killnig system server **");            mActivity.addErrorToDropBox("watchdog", null, "system_server", null, null, subject, null, null, null);            IActivityController controller;            synchronized (this) {                controller = mController;            }            if ((mSFHang == false) && (controller != null)) {                Slog.i(TAG, "Reporting stuck state to activity controller");                try {                    Binder.setDumpDisabled("Service dumps disabled due to hung system process.");                    Slog.i(TAG, "Binder.setDumpDisabled");                    // 1 = keep waiting, -1 = kill system                    int res = controller.systemNotResponding(subject);                    if (res >= 0) {                        Slog.i(TAG, "Activity controller requested to coninue to wait");                        waitedHalf = false;                        continue;                    }                    Slog.i(TAG, "Activity controller requested to reboot");                } catch (RemoteException e) {                }            }            // Only kill the process if the debugger is not attached.            if (Debug.isDebuggerConnected()) {                debuggerWasConnected = 2;            }            if (debuggerWasConnected >= 2) {                Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");            } else if (debuggerWasConnected > 0) {                Slog.w(TAG, "Debugger was connected: Watchdog is *not* killing the system process");            } else if (!allowRestart) {                Slog.w(TAG, "Restart not allowed: Watchdog is *not* killing the system process");            } else {                Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject);                for (int i=0; i<blockedCheckers.size(); i++) {                    Slog.w(TAG, blockedCheckers.get(i).getName() + " stack trace:");                    StackTraceElement[] stackTrace                            = blockedCheckers.get(i).getThread().getStackTrace();                    for (StackTraceElement element: stackTrace) {                        Slog.w(TAG, "    at " + element);                    }                }                SystemClock.sleep(25000);                /// @}                Slog.w(TAG, "*** GOODBYE!");                // MTK enhance                if (mSFHang)                {                    Slog.w(TAG, "SF hang!");                    if (GetSFReboot() > 3)                    {                        Slog.w(TAG, "SF hang reboot time larger than 3 time, reboot device!");                        rebootSystem("Maybe SF driver hang,reboot device.");                    }                    else                    {                        SetSFReboot();                    }                }                //@                Process.killProcess(Process.myPid());                System.exit(10);            }            waitedHalf = false;        }    }    private void doSysRq(char c) {        try {            FileWriter sysrq_trigger = new FileWriter("/proc/sysrq-trigger");            sysrq_trigger.write(c);            sysrq_trigger.close();        } catch (IOException e) {            Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e);        }    }    private File dumpKernelStackTraces() {        String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);        if (tracesPath == null || tracesPath.length() == 0) {            return null;        }        native_dumpKernelStacks(tracesPath);        return new File(tracesPath);    }    private native void native_dumpKernelStacks(String tracesPath);    /**     * M: WDT debug enhancement     */    private File dumpAllBackTraces(boolean clearTraces) {        /*debug flag for dump all thread backtrace for ANR*/        ArrayList<Integer> pids = new ArrayList<Integer>();        /// M: WDT debug enhancement        /// it's better to dump all running processes backtraces        /// and integrate with AEE @{        // pids.add(Process.myPid());        //if (mPhonePid > 0) pids.add(mPhonePid);        // Pass !waitedHalf so that just in case we somehow wind up here without having        mActivity.getRunningProcessPids(pids);        File stack = ActivityManagerService.dumpStackTraces(true, pids, null, null, NATIVE_STACKS_OF_INTEREST);        return stack;    }}

0 0