112 lines
5.0 KiB
Java
112 lines
5.0 KiB
Java
package com.squareup.leakcanary;
|
|
|
|
import android.app.Activity;
|
|
import android.app.Application;
|
|
import android.app.Notification;
|
|
import android.app.NotificationManager;
|
|
import android.content.Context;
|
|
import android.os.Debug;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.os.MessageQueue;
|
|
import android.os.SystemClock;
|
|
import android.view.LayoutInflater;
|
|
import android.view.ViewGroup;
|
|
import android.widget.Toast;
|
|
import com.squareup.leakcanary.internal.ActivityLifecycleCallbacksAdapter;
|
|
import com.squareup.leakcanary.internal.FutureResult;
|
|
import com.squareup.leakcanary.internal.LeakCanaryInternals;
|
|
import java.io.File;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
/* loaded from: classes.dex */
|
|
public final class AndroidHeapDumper implements HeapDumper {
|
|
private final Context context;
|
|
private final LeakDirectoryProvider leakDirectoryProvider;
|
|
private final Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
private Activity resumedActivity;
|
|
|
|
public AndroidHeapDumper(Context context, LeakDirectoryProvider leakDirectoryProvider) {
|
|
this.leakDirectoryProvider = leakDirectoryProvider;
|
|
this.context = context.getApplicationContext();
|
|
((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksAdapter() { // from class: com.squareup.leakcanary.AndroidHeapDumper.1
|
|
@Override // com.squareup.leakcanary.internal.ActivityLifecycleCallbacksAdapter, android.app.Application.ActivityLifecycleCallbacks
|
|
public void onActivityPaused(Activity activity) {
|
|
if (AndroidHeapDumper.this.resumedActivity == activity) {
|
|
AndroidHeapDumper.this.resumedActivity = null;
|
|
}
|
|
}
|
|
|
|
@Override // com.squareup.leakcanary.internal.ActivityLifecycleCallbacksAdapter, android.app.Application.ActivityLifecycleCallbacks
|
|
public void onActivityResumed(Activity activity) {
|
|
AndroidHeapDumper.this.resumedActivity = activity;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void cancelToast(final Toast toast) {
|
|
if (toast == null) {
|
|
return;
|
|
}
|
|
this.mainHandler.post(new Runnable() { // from class: com.squareup.leakcanary.AndroidHeapDumper.3
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
toast.cancel();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void showToast(final FutureResult<Toast> futureResult) {
|
|
this.mainHandler.post(new Runnable() { // from class: com.squareup.leakcanary.AndroidHeapDumper.2
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
if (AndroidHeapDumper.this.resumedActivity == null) {
|
|
futureResult.set(null);
|
|
return;
|
|
}
|
|
final Toast toast = new Toast(AndroidHeapDumper.this.resumedActivity);
|
|
toast.setGravity(16, 0, 0);
|
|
toast.setDuration(1);
|
|
toast.setView(LayoutInflater.from(AndroidHeapDumper.this.resumedActivity).inflate(R.layout.leak_canary_heap_dump_toast, (ViewGroup) null));
|
|
toast.show();
|
|
Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { // from class: com.squareup.leakcanary.AndroidHeapDumper.2.1
|
|
@Override // android.os.MessageQueue.IdleHandler
|
|
public boolean queueIdle() {
|
|
futureResult.set(toast);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override // com.squareup.leakcanary.HeapDumper
|
|
public File dumpHeap() {
|
|
File newHeapDumpFile = this.leakDirectoryProvider.newHeapDumpFile();
|
|
File file = HeapDumper.RETRY_LATER;
|
|
if (newHeapDumpFile == file) {
|
|
return file;
|
|
}
|
|
FutureResult<Toast> futureResult = new FutureResult<>();
|
|
showToast(futureResult);
|
|
if (!futureResult.wait(5L, TimeUnit.SECONDS)) {
|
|
CanaryLog.d("Did not dump heap, too much time waiting for Toast.", new Object[0]);
|
|
return HeapDumper.RETRY_LATER;
|
|
}
|
|
Notification buildNotification = LeakCanaryInternals.buildNotification(this.context, new Notification.Builder(this.context).setContentTitle(this.context.getString(R.string.leak_canary_notification_dumping)));
|
|
NotificationManager notificationManager = (NotificationManager) this.context.getSystemService("notification");
|
|
int uptimeMillis = (int) SystemClock.uptimeMillis();
|
|
notificationManager.notify(uptimeMillis, buildNotification);
|
|
Toast toast = futureResult.get();
|
|
try {
|
|
Debug.dumpHprofData(newHeapDumpFile.getAbsolutePath());
|
|
cancelToast(toast);
|
|
notificationManager.cancel(uptimeMillis);
|
|
return newHeapDumpFile;
|
|
} catch (Exception e) {
|
|
CanaryLog.d(e, "Could not dump heap", new Object[0]);
|
|
return HeapDumper.RETRY_LATER;
|
|
}
|
|
}
|
|
}
|