13d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang/*
23d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Copyright (C) 2012 The Android Open Source Project
33d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang *
43d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License");
53d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * you may not use this file except in compliance with the License.
63d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * You may obtain a copy of the License at
73d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang *
83d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang *      http://www.apache.org/licenses/LICENSE-2.0
93d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang *
103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * Unless required by applicable law or agreed to in writing, software
113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS,
123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * See the License for the specific language governing permissions and
143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang * limitations under the License.
153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang */
163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changpackage com.android.gallery3d.util;
183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.Handler;
203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.HandlerThread;
213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.Process;
223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.ArrayList;
243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.Random;
253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// The Profile class is used to collect profiling information for a thread. It
273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// samples stack traces for a thread periodically. enable() and disable() is
283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// used to enable and disable profiling for the calling thread. The profiling
293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// information can then be dumped to a file using the dumpToFile() method.
303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang//
313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// The disableAll() method can be used to disable profiling for all threads and
323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// can be called in onPause() to ensure all profiling is disabled when an
333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// activity is paused.
343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changpublic class Profile {
357817979db0c52ffeacb951625b1e821eba303285Ahbong Chang    @SuppressWarnings("unused")
363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static final String TAG = "Profile";
373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static final int NS_PER_MS = 1000000;
383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This is a watchdog entry for one thread.
403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // For every cycleTime period, we dump the stack of the thread.
413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static class WatchEntry {
423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        Thread thread;
433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        // Both are in milliseconds
453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        int cycleTime;
463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        int wakeTime;
473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        boolean isHolding;
493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        ArrayList<String[]> holdingStacks = new ArrayList<String[]>();
503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This is a watchdog thread which dumps stacks of other threads periodically.
533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static Watchdog sWatchdog = new Watchdog();
543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static class Watchdog {
563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private ArrayList<WatchEntry> mList = new ArrayList<WatchEntry>();
573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private HandlerThread mHandlerThread;
583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Handler mHandler;
593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Runnable mProcessRunnable = new Runnable() {
607817979db0c52ffeacb951625b1e821eba303285Ahbong Chang            @Override
613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            public void run() {
623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                synchronized (Watchdog.this) {
633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    processList();
643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        };
673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Random mRandom = new Random();
683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private ProfileData mProfileData = new ProfileData();
693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public Watchdog() {
713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandlerThread = new HandlerThread("Watchdog Handler",
723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    Process.THREAD_PRIORITY_FOREGROUND);
733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandlerThread.start();
743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler = new Handler(mHandlerThread.getLooper());
753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void addWatchEntry(Thread thread, int cycleTime) {
783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry e = new WatchEntry();
793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.thread = thread;
803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.cycleTime = cycleTime;
813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int firstDelay = 1 + mRandom.nextInt(cycleTime);
823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.wakeTime = (int) (System.nanoTime() / NS_PER_MS) + firstDelay;
833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mList.add(e);
843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void removeWatchEntry(Thread thread) {
883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < mList.size(); i++) {
893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (mList.get(i).thread == thread) {
903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    mList.remove(i);
913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    break;
923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void removeAllWatchEntries() {
983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mList.clear();
993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
1003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private void processList() {
1033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler.removeCallbacks(mProcessRunnable);
1043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (mList.size() == 0) return;
1053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int currentTime = (int) (System.nanoTime() / NS_PER_MS);
1073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int nextWakeTime = 0;
1083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (WatchEntry entry : mList) {
1103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (currentTime > entry.wakeTime) {
1113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    entry.wakeTime += entry.cycleTime;
1123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    Thread thread = entry.thread;
1133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    sampleStack(entry);
1143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
1153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (entry.wakeTime > nextWakeTime) {
1173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    nextWakeTime = entry.wakeTime;
1183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
1193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            long delay = nextWakeTime - currentTime;
1223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler.postDelayed(mProcessRunnable, delay);
1233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private void sampleStack(WatchEntry entry) {
1263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Thread thread = entry.thread;
1273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            StackTraceElement[] stack = thread.getStackTrace();
1283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            String[] lines = new String[stack.length];
1293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < stack.length; i++) {
1303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                lines[i] = stack[i].toString();
1313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry.isHolding) {
1333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                entry.holdingStacks.add(lines);
1343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            } else {
1353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                mProfileData.addSample(lines);
1363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private WatchEntry findEntry(Thread thread) {
1403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < mList.size(); i++) {
1413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                WatchEntry entry = mList.get(i);
1423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (entry.thread == thread) return entry;
1433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            return null;
1453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void dumpToFile(String filename) {
1483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mProfileData.dumpToFile(filename);
1493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void reset() {
1523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mProfileData.reset();
1533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void hold(Thread t) {
1563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // This can happen if the profiling is disabled (probably from
1593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // another thread). Same check is applied in commit() and drop()
1603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // below.
1613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = true;
1643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void commit(Thread t) {
1673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            ArrayList<String[]> stacks = entry.holdingStacks;
1703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < stacks.size(); i++) {
1713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                mProfileData.addSample(stacks.get(i));
1723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = false;
1743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.holdingStacks.clear();
1753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void drop(Thread t) {
1783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = false;
1813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.holdingStacks.clear();
1823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Enable profiling for the calling thread. Periodically (every cycleTimeInMs
1863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // milliseconds) sample the stack trace of the calling thread.
1873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void enable(int cycleTimeInMs) {
1883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        Thread t = Thread.currentThread();
1893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.addWatchEntry(t, cycleTimeInMs);
1903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Disable profiling for the calling thread.
1933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void disable() {
1943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.removeWatchEntry(Thread.currentThread());
1953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Disable profiling for all threads.
1983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void disableAll() {
1993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.removeAllWatchEntries();
2003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Dump the profiling data to a file.
2033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void dumpToFile(String filename) {
2043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.dumpToFile(filename);
2053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Reset the collected profiling data.
2083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void reset() {
2093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.reset();
2103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Hold the future samples coming from current thread until commit() or
2133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // drop() is called, and those samples are recorded or ignored as a result.
2143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This must called after enable() to be effective.
2153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void hold() {
2163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.hold(Thread.currentThread());
2173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void commit() {
2203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.commit(Thread.currentThread());
2213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void drop() {
2243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.drop(Thread.currentThread());
2253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang}
227