Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazily enable the Android components #1002

Merged
merged 1 commit into from
Jun 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ public RefWatcher buildAndInstall() {
}
RefWatcher refWatcher = build();
if (refWatcher != DISABLED) {
LeakCanary.enableDisplayLeakActivity(context);
if (watchActivities) {
ActivityRefWatcher.install((Application) context, refWatcher);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,14 @@ public static AndroidRefWatcherBuilder refWatcher(Context context) {
return new AndroidRefWatcherBuilder(context);
}

/**
* Blocking inter process call that enables the {@link DisplayLeakActivity}. When you first
* install the app, {@link DisplayLeakActivity} is disabled by default and will only be enabled
* once a potential leak has been found and the analysis starts. You can call this method to
* enable {@link DisplayLeakActivity} before any potential leak has been detected.
*/
public static void enableDisplayLeakActivity(Context context) {
setEnabled(context, DisplayLeakActivity.class, true);
LeakCanaryInternals.setEnabledBlocking(context, DisplayLeakActivity.class, true);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,14 @@
import com.squareup.leakcanary.internal.HeapAnalyzerService;

import static com.squareup.leakcanary.Preconditions.checkNotNull;
import static com.squareup.leakcanary.internal.LeakCanaryInternals.setEnabled;

public final class ServiceHeapDumpListener implements HeapDump.Listener {

private final Context context;
private final Class<? extends AbstractAnalysisResultService> listenerServiceClass;

public ServiceHeapDumpListener(Context context,
Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
setEnabled(context, listenerServiceClass, true);
setEnabled(context, HeapAnalyzerService.class, true);
public ServiceHeapDumpListener(final Context context,
final Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
this.listenerServiceClass = checkNotNull(listenerServiceClass, "listenerServiceClass");
this.context = checkNotNull(context, "context").getApplicationContext();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import static com.squareup.leakcanary.BuildConfig.LIBRARY_VERSION;
import static com.squareup.leakcanary.LeakCanary.leakInfo;
import static com.squareup.leakcanary.internal.LeakCanaryInternals.newSingleThreadExecutor;
import static com.squareup.leakcanary.internal.LeakCanaryInternals.setEnabledBlocking;

@SuppressWarnings("ConstantConditions")
public final class DisplayLeakActivity extends Activity {
Expand All @@ -83,6 +84,7 @@ public static PendingIntent createPendingIntent(Context context) {
}

public static PendingIntent createPendingIntent(Context context, String referenceKey) {
setEnabledBlocking(context, DisplayLeakActivity.class, true);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this now block for a non-zero amount of time on every leak?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, but from an IntentService handler thread so 🤷‍♂️

Intent intent = new Intent(context, DisplayLeakActivity.class);
intent.putExtra(SHOW_LEAK_EXTRA, referenceKey);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import com.squareup.leakcanary.HeapAnalyzer;
import com.squareup.leakcanary.HeapDump;

import static com.squareup.leakcanary.internal.LeakCanaryInternals.setEnabledBlocking;

/**
* This service runs in a separate process to avoid slowing down the app process or making it run
* out of memory.
Expand All @@ -35,6 +37,8 @@ public final class HeapAnalyzerService extends IntentService {

public static void runAnalysis(Context context, HeapDump heapDump,
Class<? extends AbstractAnalysisResultService> listenerServiceClass) {
setEnabledBlocking(context, HeapAnalyzerService.class, true);
setEnabledBlocking(context, listenerServiceClass, true);
Intent intent = new Intent(context, HeapAnalyzerService.class);
intent.putExtra(LISTENER_CLASS_EXTRA, listenerServiceClass.getName());
intent.putExtra(HEAPDUMP_EXTRA, heapDump);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,12 @@ public final class LeakCanaryInternals {
public static final String HUAWEI = "HUAWEI";
public static final String VIVO = "vivo";

private static final Executor fileIoExecutor = newSingleThreadExecutor("File-IO");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlexanderGH you'll be excited.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm excited when people are excited! I'd love to know why you're excited though :)

public static volatile RefWatcher installedRefWatcher;

private static final String NOTIFICATION_CHANNEL_ID = "leakcanary";

public static volatile Boolean isInAnalyzerProcess;

public static void executeOnFileIoThread(Runnable runnable) {
fileIoExecutor.execute(runnable);
}

/** Extracts the class simple name out of a string containing a fully qualified class name. */
public static String classSimpleName(String className) {
int separator = className.lastIndexOf('.');
Expand All @@ -74,16 +69,6 @@ public static String classSimpleName(String className) {
}
}

public static void setEnabled(Context context, final Class<?> componentClass,
final boolean enabled) {
final Context appContext = context.getApplicationContext();
executeOnFileIoThread(new Runnable() {
@Override public void run() {
setEnabledBlocking(appContext, componentClass, enabled);
}
});
}

public static void setEnabledBlocking(Context appContext, Class<?> componentClass,
boolean enabled) {
ComponentName component = new ComponentName(appContext, componentClass);
Expand Down