public BlockCanaryInternals() { stackSampler = new StackSampler(Looper.getMainLooper().getThread(), sContext.provideDumpInterval()); cpuSampler = new CpuSampler(sContext.provideDumpInterval()); setMonitor( new LooperMonitor( new LooperMonitor.BlockListener() { @Override public void onBlockEvent( long realTimeStart, long realTimeEnd, long threadTimeStart, long threadTimeEnd) { // Get recent thread-stack entries and cpu usage ArrayList<String> threadStackEntries = stackSampler.getThreadStackEntries(realTimeStart, realTimeEnd); if (!threadStackEntries.isEmpty()) { BlockInfo blockInfo = BlockInfo.newInstance() .setMainThreadTimeCost( realTimeStart, realTimeEnd, threadTimeStart, threadTimeEnd) .setCpuBusyFlag(cpuSampler.isCpuBusy(realTimeStart, realTimeEnd)) .setRecentCpuRate(cpuSampler.getCpuRateInfo()) .setThreadStackEntries(threadStackEntries) .flushString(); LogWriter.save(blockInfo.toString()); if (getContext().displayNotification() && mInterceptorChain.size() != 0) { for (BlockInterceptor interceptor : mInterceptorChain) { interceptor.onBlock(getContext().provideContext(), blockInfo); } } } } }, getContext().provideBlockThreshold())); LogWriter.cleanObsolete(); }