Profile.java revision 3d238a7a19b1010578709c63f86e12b2bce0e4fc
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 com.android.gallery3d.common.Utils;
203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.Handler;
223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.HandlerThread;
233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.os.Process;
243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport android.util.Log;
253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.ArrayList;
273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changimport java.util.Random;
283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// The Profile class is used to collect profiling information for a thread. It
303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// samples stack traces for a thread periodically. enable() and disable() is
313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// used to enable and disable profiling for the calling thread. The profiling
323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// information can then be dumped to a file using the dumpToFile() method.
333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang//
343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// The disableAll() method can be used to disable profiling for all threads and
353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// can be called in onPause() to ensure all profiling is disabled when an
363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang// activity is paused.
373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Changpublic class Profile {
383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static final String TAG = "Profile";
393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static final int NS_PER_MS = 1000000;
403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This is a watchdog entry for one thread.
423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // For every cycleTime period, we dump the stack of the thread.
433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static class WatchEntry {
443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        Thread thread;
453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        // Both are in milliseconds
473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        int cycleTime;
483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        int wakeTime;
493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        boolean isHolding;
513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        ArrayList<String[]> holdingStacks = new ArrayList<String[]>();
523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This is a watchdog thread which dumps stacks of other threads periodically.
553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static Watchdog sWatchdog = new Watchdog();
563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    private static class Watchdog {
583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private ArrayList<WatchEntry> mList = new ArrayList<WatchEntry>();
593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private HandlerThread mHandlerThread;
603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Handler mHandler;
613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Runnable mProcessRunnable = new Runnable() {
623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            public void run() {
633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                synchronized (Watchdog.this) {
643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    processList();
653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        };
683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private Random mRandom = new Random();
693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private ProfileData mProfileData = new ProfileData();
703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public Watchdog() {
723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandlerThread = new HandlerThread("Watchdog Handler",
733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    Process.THREAD_PRIORITY_FOREGROUND);
743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandlerThread.start();
753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler = new Handler(mHandlerThread.getLooper());
763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void addWatchEntry(Thread thread, int cycleTime) {
793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry e = new WatchEntry();
803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.thread = thread;
813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.cycleTime = cycleTime;
823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int firstDelay = 1 + mRandom.nextInt(cycleTime);
833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            e.wakeTime = (int) (System.nanoTime() / NS_PER_MS) + firstDelay;
843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mList.add(e);
853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void removeWatchEntry(Thread thread) {
893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < mList.size(); i++) {
903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (mList.get(i).thread == thread) {
913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    mList.remove(i);
923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    break;
933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void removeAllWatchEntries() {
993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mList.clear();
1003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            processList();
1013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private void processList() {
1043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler.removeCallbacks(mProcessRunnable);
1053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (mList.size() == 0) return;
1063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int currentTime = (int) (System.nanoTime() / NS_PER_MS);
1083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            int nextWakeTime = 0;
1093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (WatchEntry entry : mList) {
1113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (currentTime > entry.wakeTime) {
1123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    entry.wakeTime += entry.cycleTime;
1133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    Thread thread = entry.thread;
1143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    sampleStack(entry);
1153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
1163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (entry.wakeTime > nextWakeTime) {
1183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                    nextWakeTime = entry.wakeTime;
1193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                }
1203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            long delay = nextWakeTime - currentTime;
1233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mHandler.postDelayed(mProcessRunnable, delay);
1243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private void sampleStack(WatchEntry entry) {
1273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            Thread thread = entry.thread;
1283d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            StackTraceElement[] stack = thread.getStackTrace();
1293d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            String[] lines = new String[stack.length];
1303d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < stack.length; i++) {
1313d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                lines[i] = stack[i].toString();
1323d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1333d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry.isHolding) {
1343d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                entry.holdingStacks.add(lines);
1353d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            } else {
1363d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                mProfileData.addSample(lines);
1373d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1383d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1393d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1403d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        private WatchEntry findEntry(Thread thread) {
1413d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < mList.size(); i++) {
1423d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                WatchEntry entry = mList.get(i);
1433d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                if (entry.thread == thread) return entry;
1443d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1453d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            return null;
1463d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1473d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1483d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void dumpToFile(String filename) {
1493d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mProfileData.dumpToFile(filename);
1503d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1513d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1523d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void reset() {
1533d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            mProfileData.reset();
1543d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1553d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1563d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void hold(Thread t) {
1573d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1583d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1593d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // This can happen if the profiling is disabled (probably from
1603d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // another thread). Same check is applied in commit() and drop()
1613d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            // below.
1623d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1633d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1643d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = true;
1653d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1663d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1673d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void commit(Thread t) {
1683d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1693d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1703d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            ArrayList<String[]> stacks = entry.holdingStacks;
1713d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            for (int i = 0; i < stacks.size(); i++) {
1723d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang                mProfileData.addSample(stacks.get(i));
1733d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            }
1743d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = false;
1753d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.holdingStacks.clear();
1763d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1773d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1783d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        public synchronized void drop(Thread t) {
1793d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            WatchEntry entry = findEntry(t);
1803d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            if (entry == null) return;
1813d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.isHolding = false;
1823d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang            entry.holdingStacks.clear();
1833d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        }
1843d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1853d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1863d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Enable profiling for the calling thread. Periodically (every cycleTimeInMs
1873d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // milliseconds) sample the stack trace of the calling thread.
1883d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void enable(int cycleTimeInMs) {
1893d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        Thread t = Thread.currentThread();
1903d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.addWatchEntry(t, cycleTimeInMs);
1913d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1923d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1933d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Disable profiling for the calling thread.
1943d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void disable() {
1953d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.removeWatchEntry(Thread.currentThread());
1963d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
1973d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
1983d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Disable profiling for all threads.
1993d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void disableAll() {
2003d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.removeAllWatchEntries();
2013d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2023d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2033d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Dump the profiling data to a file.
2043d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void dumpToFile(String filename) {
2053d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.dumpToFile(filename);
2063d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2073d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2083d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Reset the collected profiling data.
2093d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void reset() {
2103d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.reset();
2113d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2123d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2133d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // Hold the future samples coming from current thread until commit() or
2143d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // drop() is called, and those samples are recorded or ignored as a result.
2153d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    // This must called after enable() to be effective.
2163d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void hold() {
2173d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.hold(Thread.currentThread());
2183d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2193d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2203d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void commit() {
2213d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.commit(Thread.currentThread());
2223d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2233d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang
2243d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    public static void drop() {
2253d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang        sWatchdog.drop(Thread.currentThread());
2263d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang    }
2273d238a7a19b1010578709c63f86e12b2bce0e4fcChih-Chung Chang}
228