diff --git a/CHANGELOG.md b/CHANGELOG.md index 366a907..008e1d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ You can watch releases [on Maven](https://oss.sonatype.org/content/groups/public/com/github/markzhai/). + +## Version 1.5.1 *(2017-08-19)* + +1. refactor this framework; +2. change class `BlockCanaryContext` to `DefaultBlockInterceptor`. + + ## Version 1.5 *(2017-02-26)* Debug mode stop monitor. diff --git a/README.md b/README.md index bd17983..c7388fa 100644 --- a/README.md +++ b/README.md @@ -51,9 +51,9 @@ public class DemoApplication extends Application { } ``` -Implement your application `BlockCanaryContext` context (strongly recommend you to check all these configs): +Implement your application `BlockInterceptor` context (strongly recommend you to check all these configs, or you can use DefaultBlockInterceptor directly.): ```java -public class AppBlockCanaryContext extends BlockCanaryContext { +public class AppBlockCanaryContext extends BlockInterceptor { /** * Implement in your project. diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java index 895d0d6..8103f08 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryInternals.java @@ -15,13 +15,15 @@ */ package com.github.moduth.blockcanary; -import android.os.Environment; +import android.content.Context; import android.os.Looper; +import com.github.moduth.blockcanary.interceptor.BlockInterceptor; +import com.github.moduth.blockcanary.interceptor.DefaultBlockInterceptor; import com.github.moduth.blockcanary.internal.BlockInfo; +import com.github.moduth.blockcanary.sampler.CpuSampler; +import com.github.moduth.blockcanary.sampler.StackSampler; -import java.io.File; -import java.io.FilenameFilter; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -32,54 +34,62 @@ public final class BlockCanaryInternals { StackSampler stackSampler; CpuSampler cpuSampler; + /** + * Null object pattern + */ + private static final BlockInterceptor NULL_OBJ = new DefaultBlockInterceptor(); + private static BlockCanaryInternals sInstance; - private static BlockCanaryContext sContext; + private static Context sContext; private List mInterceptorChain = new LinkedList<>(); - public BlockCanaryInternals() { - + private 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 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 (mInterceptorChain.size() != 0) { - for (BlockInterceptor interceptor : mInterceptorChain) { - interceptor.onBlock(getContext().provideContext(), blockInfo); - } + getInterceptor(0).provideDumpInterval()); + cpuSampler = new CpuSampler(getInterceptor(0).provideDumpInterval()); + // set Looper printer + monitor = new LooperMonitor(mBlockListener, getInterceptor(0).provideBlockThreshold(), getInterceptor(0).stopWhenDebugging()); + + LogWriter.cleanObsolete(); + } + + + LooperMonitor.BlockListener mBlockListener = new LooperMonitor.BlockListener() { + @Override + public void onBlockEvent(long realTimeStart, long realTimeEnd, long threadTimeStart, long threadTimeEnd) { + // Get recent thread-stack entries and cpu usage + ArrayList threadStackEntries = stackSampler + .getThreadStackEntries(realTimeStart, realTimeEnd); + if (!threadStackEntries.isEmpty()) { + BlockInfo blockInfo = BlockInfo.newInstance() + .setQualifier(getInterceptor(0).provideQualifier()) + .setUid(getInterceptor(0).provideUid()) + .setNetwork(getInterceptor(0).provideNetworkType()) + .setMainThreadTimeCost(realTimeStart, realTimeEnd, threadTimeStart, threadTimeEnd) + .setCpuBusyFlag(cpuSampler.isCpuBusy(realTimeStart, realTimeEnd)) + .setRecentCpuRate(cpuSampler.getCpuRateInfo()) + .setThreadStackEntries(threadStackEntries) + .flushString(); + LogWriter.save(blockInfo.toString()); + + if (mInterceptorChain.size() != 0) { + for (BlockInterceptor interceptor : mInterceptorChain) { + interceptor.onBlock(BlockCanaryInternals.getContext(), blockInfo); } } } - }, getContext().provideBlockThreshold(), getContext().stopWhenDebugging())); + } + }; - LogWriter.cleanObsolete(); - } /** * Get BlockCanaryInternals singleton * * @return BlockCanaryInternals instance */ - static BlockCanaryInternals getInstance() { + public static BlockCanaryInternals getInstance() { if (sInstance == null) { synchronized (BlockCanaryInternals.class) { if (sInstance == null) { @@ -91,69 +101,32 @@ static BlockCanaryInternals getInstance() { } /** - * set {@link BlockCanaryContext} implementation + * set Context * - * @param context context + * @param context You should pass a Application Context */ - public static void setContext(BlockCanaryContext context) { + public static void setContext(Context context) { sContext = context; } - public static BlockCanaryContext getContext() { + public static Context getContext() { return sContext; } void addBlockInterceptor(BlockInterceptor blockInterceptor) { - mInterceptorChain.add(blockInterceptor); - } - - private void setMonitor(LooperMonitor looperPrinter) { - monitor = looperPrinter; - } - - long getSampleDelay() { - return (long) (BlockCanaryInternals.getContext().provideBlockThreshold() * 0.8f); - } - - static String getPath() { - String state = Environment.getExternalStorageState(); - String logPath = BlockCanaryInternals.getContext() - == null ? "" : BlockCanaryInternals.getContext().providePath(); - - if (Environment.MEDIA_MOUNTED.equals(state) - && Environment.getExternalStorageDirectory().canWrite()) { - return Environment.getExternalStorageDirectory().getPath() + logPath; - } - return getContext().provideContext().getFilesDir() + BlockCanaryInternals.getContext().providePath(); - } - - static File detectedBlockDirectory() { - File directory = new File(getPath()); - if (!directory.exists()) { - directory.mkdirs(); + if ( blockInterceptor != null ) { + mInterceptorChain.add(blockInterceptor); } - return directory; } - public static File[] getLogFiles() { - File f = detectedBlockDirectory(); - if (f.exists() && f.isDirectory()) { - return f.listFiles(new BlockLogFileFilter()); + public BlockInterceptor getInterceptor(int pos) { + if ( pos < 0 || mInterceptorChain.size() <= pos ) { + return NULL_OBJ; } - return null; + return mInterceptorChain.get(pos) ; } - private static class BlockLogFileFilter implements FilenameFilter { - - private String TYPE = ".log"; - - BlockLogFileFilter() { - - } - - @Override - public boolean accept(File dir, String filename) { - return filename.endsWith(TYPE); - } + public long getSampleDelay() { + return (long) (getInterceptor(0).provideBlockThreshold() * 0.8f); } } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockInterceptor.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockInterceptor.java deleted file mode 100644 index 26a3df6..0000000 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockInterceptor.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2016 MarkZhai (http://zhaiyifan.cn). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.moduth.blockcanary; - -import android.content.Context; - -import com.github.moduth.blockcanary.internal.BlockInfo; - -interface BlockInterceptor { - void onBlock(Context context, BlockInfo blockInfo); -} diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java index bf4c26d..e21876c 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/HandlerThreadFactory.java @@ -18,7 +18,7 @@ import android.os.Handler; import android.os.HandlerThread; -final class HandlerThreadFactory { +public final class HandlerThreadFactory { private static HandlerThreadWrapper sLoopThread = new HandlerThreadWrapper("loop"); private static HandlerThreadWrapper sWriteLogThread = new HandlerThreadWrapper("writer"); diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java index fab8b72..5737ac3 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/LogWriter.java @@ -15,13 +15,16 @@ */ package com.github.moduth.blockcanary; +import android.os.Environment; import android.util.Log; +import com.github.moduth.blockcanary.interceptor.BlockInterceptor; import com.github.moduth.blockcanary.internal.BlockInfo; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; +import java.io.FilenameFilter; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Locale; @@ -66,7 +69,7 @@ public static void cleanObsolete() { @Override public void run() { long now = System.currentTimeMillis(); - File[] f = BlockCanaryInternals.getLogFiles(); + File[] f = getLogFiles(); if (f != null && f.length > 0) { synchronized (SAVE_DELETE_LOCK) { for (File aF : f) { @@ -83,7 +86,7 @@ public void run() { public static void deleteAll() { synchronized (SAVE_DELETE_LOCK) { try { - File[] files = BlockCanaryInternals.getLogFiles(); + File[] files = getLogFiles(); if (files != null && files.length > 0) { for (File file : files) { file.delete(); @@ -99,7 +102,7 @@ private static String save(String logFileName, String str) { String path = ""; BufferedWriter writer = null; try { - File file = BlockCanaryInternals.detectedBlockDirectory(); + File file = detectedBlockDirectory(); long time = System.currentTimeMillis(); path = file.getAbsolutePath() + "/" + logFileName + "-" @@ -138,6 +141,49 @@ private static String save(String logFileName, String str) { } public static File generateTempZip(String filename) { - return new File(BlockCanaryInternals.getPath() + "/" + filename + ".zip"); + return new File(getPath() + "/" + filename + ".zip"); + } + + + private static String getPath() { + String state = Environment.getExternalStorageState(); + BlockInterceptor interceptor = BlockCanaryInternals.getInstance().getInterceptor(0) ; + String logPath = interceptor == null ? "" : interceptor.providePath(); + + if (Environment.MEDIA_MOUNTED.equals(state) + && Environment.getExternalStorageDirectory().canWrite()) { + return Environment.getExternalStorageDirectory().getPath() + logPath; + } + return BlockCanaryInternals.getContext().getFilesDir() + interceptor.providePath(); + } + + static File detectedBlockDirectory() { + File directory = new File(getPath()); + if (!directory.exists()) { + directory.mkdirs(); + } + return directory; + } + + public static File[] getLogFiles() { + File f = detectedBlockDirectory(); + if (f.exists() && f.isDirectory()) { + return f.listFiles(new BlockLogFileFilter()); + } + return null; + } + + private static class BlockLogFileFilter implements FilenameFilter { + + private String TYPE = ".log"; + + BlockLogFileFilter() { + + } + + @Override + public boolean accept(File dir, String filename) { + return filename.endsWith(TYPE); + } } } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/BlockInterceptor.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/BlockInterceptor.java new file mode 100644 index 0000000..188784d --- /dev/null +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/BlockInterceptor.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2016 MarkZhai (http://zhaiyifan.cn). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.moduth.blockcanary.interceptor; + +import android.content.Context; + +import com.github.moduth.blockcanary.internal.BlockInfo; + +import java.io.File; +import java.util.List; + +public interface BlockInterceptor { + /** + * Block interceptor, developer may provide their own actions. + */ + void onBlock(Context context, BlockInfo blockInfo); + + /** + * Implement in your project. + * + * @return Qualifier which can specify this installation, like version + flavor. + */ + + String provideQualifier(); + + /** + * Implement in your project. + * + * @return user id + */ + String provideUid(); + + /** + * Network type + * + * @return ;@link String} like 2G, 3G, 4G, wifi, etc. + */ + + String provideNetworkType(); + + /** + * Config monitor duration, after this time BlockCanary will stop, use + * with ;@code BlockCanary}'s isMonitorDurationEnd + * + * @return monitor last duration (in hour) + */ + + int provideMonitorDuration(); + + /** + * Config block threshold (in millis), dispatch over this duration is regarded as a BLOCK. You may set it + * from performance of device. + * + * @return threshold in mills + */ + + int provideBlockThreshold(); + + /** + * Thread stack dump interval, use when block happens, BlockCanary will dump on main thread + * stack according to current sample cycle. + *

+ * Because the implementation mechanism of Looper, real dump interval would be longer than + * the period specified here (especially when cpu is busier). + *

+ * + * @return dump interval (in millis) + */ + + int provideDumpInterval(); + + /** + * Path to save log, like "/blockcanary/", will save to sdcard if can. + * + * @return path of log files + */ + + String providePath(); + + /** + * If need notification to notice block. + * + * @return true if need, else if not need. + */ + + boolean displayNotification(); + + /** + * Implement in your project, bundle files into a zip file. + * + * @param src files before compress + * @param dest files compressed + * @return true if compression is successful + */ + + boolean zip(File[] src, File dest); + + /** + * Implement in your project, bundled log files. + * + * @param zippedFile zipped file + */ + void upload(File zippedFile); + + /** + * Packages that developer concern, by default it uses process name, + * put high priority one in pre-order. + * + * @return null if simply concern only package with process name. + */ + + List concernPackages(); + + /** + * Filter stack without any in concern package, used with @;code concernPackages}. + * + * @return true if filter, false it not. + */ + + boolean filterNonConcernStack(); + + /** + * Provide white list, entry in white list will not be shown in ui list. + * + * @return return null if you don't need white-list filter. + */ + List provideWhiteList(); + + /** + * Whether to delete files whose stack is in white list, used with white-list. + * + * @return true if delete, false it not. + */ + boolean deleteFilesInWhiteList(); + + /** + * Whether to stop monitoring when in debug mode. + * + * @return true if stop, false otherwise + */ + boolean stopWhenDebugging(); +} diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryContext.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/DefaultBlockInterceptor.java similarity index 86% rename from blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryContext.java rename to blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/DefaultBlockInterceptor.java index 42dd1f1..99a0183 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/BlockCanaryContext.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/interceptor/DefaultBlockInterceptor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.moduth.blockcanary; +package com.github.moduth.blockcanary.interceptor; import android.content.Context; @@ -26,39 +26,14 @@ /** * User should provide a real implementation of this class to use BlockCanary. */ -public class BlockCanaryContext implements BlockInterceptor { - - private static Context sApplicationContext; - private static BlockCanaryContext sInstance = null; - - public BlockCanaryContext() { - } - - static void init(Context context, BlockCanaryContext blockCanaryContext) { - sApplicationContext = context; - sInstance = blockCanaryContext; - } - - public static BlockCanaryContext get() { - if (sInstance == null) { - throw new RuntimeException("BlockCanaryContext null"); - } else { - return sInstance; - } - } - - /** - * Provide application context. - */ - public Context provideContext() { - return sApplicationContext; - } +public class DefaultBlockInterceptor implements BlockInterceptor { /** * Implement in your project. * * @return Qualifier which can specify this installation, like version + flavor. */ + @Override public String provideQualifier() { return "unknown"; } @@ -68,6 +43,7 @@ public String provideQualifier() { * * @return user id */ + @Deprecated public String provideUid() { return "uid"; } @@ -77,6 +53,7 @@ public String provideUid() { * * @return {@link String} like 2G, 3G, 4G, wifi, etc. */ + @Override public String provideNetworkType() { return "unknown"; } @@ -87,6 +64,7 @@ public String provideNetworkType() { * * @return monitor last duration (in hour) */ + @Override public int provideMonitorDuration() { return -1; } @@ -97,6 +75,7 @@ public int provideMonitorDuration() { * * @return threshold in mills */ + @Override public int provideBlockThreshold() { return 1000; } @@ -111,6 +90,7 @@ public int provideBlockThreshold() { * * @return dump interval (in millis) */ + @Override public int provideDumpInterval() { return provideBlockThreshold(); } @@ -120,6 +100,7 @@ public int provideDumpInterval() { * * @return path of log files */ + @Override public String providePath() { return "/blockcanary/"; } @@ -129,6 +110,7 @@ public String providePath() { * * @return true if need, else if not need. */ + @Override public boolean displayNotification() { return true; } @@ -140,6 +122,7 @@ public boolean displayNotification() { * @param dest files compressed * @return true if compression is successful */ + @Override public boolean zip(File[] src, File dest) { return false; } @@ -149,6 +132,7 @@ public boolean zip(File[] src, File dest) { * * @param zippedFile zipped file */ + @Override public void upload(File zippedFile) { throw new UnsupportedOperationException(); } @@ -159,6 +143,7 @@ public void upload(File zippedFile) { * * @return null if simply concern only package with process name. */ + @Override public List concernPackages() { return null; } @@ -168,6 +153,7 @@ public List concernPackages() { * * @return true if filter, false it not. */ + @Override public boolean filterNonConcernStack() { return false; } @@ -177,6 +163,7 @@ public boolean filterNonConcernStack() { * * @return return null if you don't need white-list filter. */ + @Override public List provideWhiteList() { LinkedList whiteList = new LinkedList<>(); whiteList.add("org.chromium"); @@ -188,6 +175,7 @@ public List provideWhiteList() { * * @return true if delete, false it not. */ + @Override public boolean deleteFilesInWhiteList() { return true; } @@ -205,6 +193,7 @@ public void onBlock(Context context, BlockInfo blockInfo) { * * @return true if stop, false otherwise */ + @Override public boolean stopWhenDebugging() { return true; } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java index 1b07edd..b839ee5 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/BlockInfo.java @@ -63,7 +63,7 @@ public class BlockInfo { public static final String KEY_TOTAL_MEMORY = "totalMemory"; public static final String KEY_FREE_MEMORY = "freeMemory"; - public static String sQualifier; +// public static String sQualifier; public static String sModel; public static String sApiLevel = ""; /** @@ -105,12 +105,9 @@ public class BlockInfo { sCpuCoreNum = PerformanceUtils.getNumCores(); sModel = Build.MODEL; sApiLevel = Build.VERSION.SDK_INT + " " + VERSION.RELEASE; - sQualifier = BlockCanaryInternals.getContext().provideQualifier(); try { TelephonyManager telephonyManager = (TelephonyManager) BlockCanaryInternals - .getContext() - .provideContext() - .getSystemService(Context.TELEPHONY_SERVICE); + .getContext().getSystemService(Context.TELEPHONY_SERVICE); sImei = telephonyManager.getDeviceId(); } catch (Exception exception) { Log.e(TAG, NEW_INSTANCE_METHOD, exception); @@ -123,7 +120,7 @@ public BlockInfo() { public static BlockInfo newInstance() { BlockInfo blockInfo = new BlockInfo(); - Context context = BlockCanaryInternals.getContext().provideContext(); + Context context = BlockCanaryInternals.getContext(); if (blockInfo.versionName == null || blockInfo.versionName.length() == 0) { try { PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); @@ -137,17 +134,31 @@ public static BlockInfo newInstance() { blockInfo.cpuCoreNum = sCpuCoreNum; blockInfo.model = sModel; blockInfo.apiLevel = sApiLevel; - blockInfo.qualifier = sQualifier; blockInfo.imei = sImei; - blockInfo.uid = BlockCanaryInternals.getContext().provideUid(); blockInfo.processName = ProcessUtils.myProcessName(); - blockInfo.network = BlockCanaryInternals.getContext().provideNetworkType(); blockInfo.freeMemory = String.valueOf(PerformanceUtils.getFreeMemory()); blockInfo.totalMemory = String.valueOf(PerformanceUtils.getTotalMemory()); return blockInfo; } + + public BlockInfo setQualifier(String qualifier) { + this.qualifier = qualifier; + return this; + } + + + public BlockInfo setUid(String uid) { + this.uid = uid; + return this; + } + + public BlockInfo setNetwork(String network) { + this.network = network; + return this; + } + public BlockInfo setCpuBusyFlag(boolean busy) { cpuBusy = busy; return this; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java index 1efecfa..d06426e 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/PerformanceUtils.java @@ -68,7 +68,7 @@ public boolean accept(File pathname) { } public static long getFreeMemory() { - ActivityManager am = (ActivityManager) BlockCanaryInternals.getContext().provideContext().getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager am = (ActivityManager) BlockCanaryInternals.getContext().getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); am.getMemoryInfo(mi); return mi.availMem / 1024; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java index 7029f0f..f7f1db3 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/internal/ProcessUtils.java @@ -39,7 +39,7 @@ public static String myProcessName() { if (sProcessName != null) { return sProcessName; } - sProcessName = obtainProcessName(BlockCanaryInternals.getContext().provideContext()); + sProcessName = obtainProcessName(BlockCanaryInternals.getContext()); return sProcessName; } } diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/AbstractSampler.java similarity index 90% rename from blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java rename to blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/AbstractSampler.java index c1e3383..688f1c0 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/AbstractSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/AbstractSampler.java @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.moduth.blockcanary; +package com.github.moduth.blockcanary.sampler; + +import com.github.moduth.blockcanary.BlockCanaryInternals; +import com.github.moduth.blockcanary.HandlerThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; @@ -40,7 +43,7 @@ public void run() { }; public AbstractSampler(long sampleInterval) { - if (0 == sampleInterval) { + if ( sampleInterval <= 0 ) { sampleInterval = DEFAULT_SAMPLE_INTERVAL; } mSampleInterval = sampleInterval; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/CpuSampler.java similarity index 98% rename from blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java rename to blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/CpuSampler.java index 86c966d..e997f1e 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/CpuSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/CpuSampler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.moduth.blockcanary; +package com.github.moduth.blockcanary.sampler; import android.util.Log; @@ -29,7 +29,7 @@ /** * Dumps cpu usage. */ -class CpuSampler extends AbstractSampler { +public class CpuSampler extends AbstractSampler { private static final String TAG = "CpuSampler"; private static final int BUFFER_SIZE = 1000; diff --git a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/StackSampler.java similarity index 96% rename from blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java rename to blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/StackSampler.java index 2d65e4a..8584ab9 100644 --- a/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/StackSampler.java +++ b/blockcanary-analyzer/src/main/java/com/github/moduth/blockcanary/sampler/StackSampler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.moduth.blockcanary; +package com.github.moduth.blockcanary.sampler; import com.github.moduth.blockcanary.internal.BlockInfo; @@ -23,7 +23,7 @@ /** * Dumps thread stack. */ -class StackSampler extends AbstractSampler { +public class StackSampler extends AbstractSampler { private static final int DEFAULT_MAX_ENTRY_COUNT = 100; private static final LinkedHashMap sStackMap = new LinkedHashMap<>(); diff --git a/blockcanary-android/build.gradle b/blockcanary-android/build.gradle index ebe613e..5573931 100644 --- a/blockcanary-android/build.gradle +++ b/blockcanary-android/build.gradle @@ -21,6 +21,6 @@ android { dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') -// compile project(':blockcanary-analyzer') - compile 'com.github.markzhai:blockcanary-analyzer:1.5.0' + compile project(':blockcanary-analyzer') +// compile 'com.github.markzhai:blockcanary-analyzer:1.5.0' } diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java index edc0858..53e4186 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/BlockCanary.java @@ -21,6 +21,7 @@ import android.os.Looper; import android.preference.PreferenceManager; +import com.github.moduth.blockcanary.interceptor.BlockInterceptor; import com.github.moduth.blockcanary.ui.DisplayActivity; import java.util.concurrent.Executor; @@ -32,33 +33,22 @@ public final class BlockCanary { - private static final String TAG = "BlockCanary"; - private static BlockCanary sInstance; - private BlockCanaryInternals mBlockCanaryCore; private boolean mMonitorStarted = false; private BlockCanary() { - BlockCanaryInternals.setContext(BlockCanaryContext.get()); - mBlockCanaryCore = BlockCanaryInternals.getInstance(); - mBlockCanaryCore.addBlockInterceptor(BlockCanaryContext.get()); - if (!BlockCanaryContext.get().displayNotification()) { - return; - } - mBlockCanaryCore.addBlockInterceptor(new DisplayService()); - } /** * Install {@link BlockCanary} * - * @param context Application context - * @param blockCanaryContext BlockCanary context + * @param context Application context + * @param interceptor BlockCanary interceptor * @return {@link BlockCanary} */ - public static BlockCanary install(Context context, BlockCanaryContext blockCanaryContext) { - BlockCanaryContext.init(context, blockCanaryContext); - setEnabled(context, DisplayActivity.class, BlockCanaryContext.get().displayNotification()); + public static BlockCanary install(Context context, BlockInterceptor interceptor) { + get().setup(context, interceptor); + setEnabled(context, DisplayActivity.class, interceptor.displayNotification()); return get(); } @@ -78,13 +68,26 @@ public static BlockCanary get() { return sInstance; } + /** + * setup BlockInterceptor to provide some params. + * @param context Application context + * @param interceptor BlockInterceptor instance + */ + public void setup(Context context, BlockInterceptor interceptor) { + BlockCanaryInternals.setContext(context.getApplicationContext()); + BlockCanaryInternals.getInstance().addBlockInterceptor(interceptor); + if (interceptor!= null && interceptor.displayNotification()) { + BlockCanaryInternals.getInstance().addBlockInterceptor(new DisplayService()); + } + } + /** * Start monitoring. */ public void start() { if (!mMonitorStarted) { mMonitorStarted = true; - Looper.getMainLooper().setMessageLogging(mBlockCanaryCore.monitor); + Looper.getMainLooper().setMessageLogging(BlockCanaryInternals.getInstance().monitor); } } @@ -95,8 +98,8 @@ public void stop() { if (mMonitorStarted) { mMonitorStarted = false; Looper.getMainLooper().setMessageLogging(null); - mBlockCanaryCore.stackSampler.stop(); - mBlockCanaryCore.cpuSampler.stop(); + BlockCanaryInternals.getInstance().stackSampler.stop(); + BlockCanaryInternals.getInstance().cpuSampler.stop(); } } @@ -112,7 +115,7 @@ public void upload() { * BlockCanary. */ public void recordStartTime() { - PreferenceManager.getDefaultSharedPreferences(BlockCanaryContext.get().provideContext()) + PreferenceManager.getDefaultSharedPreferences(BlockCanaryInternals.getContext()) .edit() .putLong("BlockCanary_StartTime", System.currentTimeMillis()) .commit(); @@ -125,10 +128,10 @@ public void recordStartTime() { */ public boolean isMonitorDurationEnd() { long startTime = - PreferenceManager.getDefaultSharedPreferences(BlockCanaryContext.get().provideContext()) + PreferenceManager.getDefaultSharedPreferences(BlockCanaryInternals.getContext()) .getLong("BlockCanary_StartTime", 0); return startTime != 0 && System.currentTimeMillis() - startTime > - BlockCanaryContext.get().provideMonitorDuration() * 3600 * 1000; + BlockCanaryInternals.getInstance().getInterceptor(0).provideMonitorDuration() * 3600 * 1000; } // these lines are originally copied from LeakCanary: Copyright (C) 2015 Square, Inc. diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java index 7d71590..ab92e49 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/DisplayService.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.util.Log; +import com.github.moduth.blockcanary.interceptor.DefaultBlockInterceptor; import com.github.moduth.blockcanary.internal.BlockInfo; import com.github.moduth.blockcanary.ui.DisplayActivity; @@ -34,7 +35,7 @@ import static android.os.Build.VERSION_CODES.HONEYCOMB; import static android.os.Build.VERSION_CODES.JELLY_BEAN; -final class DisplayService implements BlockInterceptor { +final class DisplayService extends DefaultBlockInterceptor { private static final String TAG = "DisplayService"; diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java index 7334075..4b90b97 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/Uploader.java @@ -17,6 +17,8 @@ import android.util.Log; +import com.github.moduth.blockcanary.interceptor.BlockInterceptor; + import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; @@ -41,7 +43,8 @@ private static File zip() { Log.e(TAG, "zip: ", e); } File zippedFile = LogWriter.generateTempZip("BlockCanary-" + timeString); - BlockCanaryInternals.getContext().zip(BlockCanaryInternals.getLogFiles(), zippedFile); + BlockInterceptor interceptor = BlockCanaryInternals.getInstance().getInterceptor(0); + interceptor.zip(LogWriter.getLogFiles(), zippedFile); LogWriter.deleteAll(); return zippedFile; } @@ -52,7 +55,8 @@ public static void zipAndUpload() { public void run() { final File file = zip(); if (file.exists()) { - BlockCanaryInternals.getContext().upload(file); + BlockInterceptor interceptor = BlockCanaryInternals.getInstance().getInterceptor(0); + interceptor.upload(file); } } }); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java index 195b0ce..8246879 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/BlockCanaryUtils.java @@ -15,10 +15,10 @@ final class BlockCanaryUtils { private static final List CONCERN_LIST = new LinkedList<>(); static { - WHITE_LIST.addAll(BlockCanaryInternals.getContext().provideWhiteList()); + WHITE_LIST.addAll(BlockCanaryInternals.getInstance().getInterceptor(0).provideWhiteList()); - if (BlockCanaryInternals.getContext().concernPackages() != null) { - CONCERN_LIST.addAll(BlockCanaryInternals.getContext().concernPackages()); + if (BlockCanaryInternals.getInstance().getInterceptor(0).concernPackages() != null) { + CONCERN_LIST.addAll(BlockCanaryInternals.getInstance().getInterceptor(0).concernPackages()); } if (CONCERN_LIST.isEmpty()) { CONCERN_LIST.add(ProcessUtils.myProcessName()); diff --git a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java index cdd30b8..5402b20 100644 --- a/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java +++ b/blockcanary-android/src/main/java/com/github/moduth/blockcanary/ui/DisplayActivity.java @@ -42,7 +42,6 @@ import android.widget.ListView; import android.widget.TextView; -import com.github.moduth.blockcanary.BlockCanaryContext; import com.github.moduth.blockcanary.BlockCanaryInternals; import com.github.moduth.blockcanary.LogWriter; import com.github.moduth.blockcanary.R; @@ -397,7 +396,7 @@ static void forgetActivity() { @Override public void run() { final List blockInfoList = new ArrayList<>(); - File[] files = BlockCanaryInternals.getLogFiles(); + File[] files = LogWriter.getLogFiles(); if (files != null) { for (File blockFile : files) { try { @@ -409,7 +408,7 @@ public void run() { boolean needAddToList = true; if (BlockCanaryUtils.isInWhiteList(blockInfo)) { - if (BlockCanaryContext.get().deleteFilesInWhiteList()) { + if (BlockCanaryInternals.getInstance().getInterceptor(0).deleteFilesInWhiteList()) { blockFile.delete(); blockFile = null; } @@ -417,7 +416,7 @@ public void run() { } blockInfo.concernStackString = BlockCanaryUtils.concernStackString(blockInfo); - if (BlockCanaryContext.get().filterNonConcernStack() && + if (BlockCanaryInternals.getInstance().getInterceptor(0).filterNonConcernStack() && TextUtils.isEmpty(blockInfo.concernStackString)) { needAddToList = false; } diff --git a/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java b/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java index 612df72..c4926ca 100644 --- a/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java +++ b/blockcanary-sample/src/main/java/com/example/blockcanary/AppContext.java @@ -19,11 +19,11 @@ import android.content.pm.PackageManager; import android.util.Log; -import com.github.moduth.blockcanary.BlockCanaryContext; +import com.github.moduth.blockcanary.interceptor.DefaultBlockInterceptor; import java.util.List; -public class AppContext extends BlockCanaryContext { +public class AppContext extends DefaultBlockInterceptor { private static final String TAG = "AppContext"; @Override