jimu-decompiled/sources/com/squareup/leakcanary/internal/DisplayLeakActivity.java
2025-05-13 19:24:51 +02:00

471 lines
21 KiB
Java

package com.squareup.leakcanary.internal;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.format.DateUtils;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import androidx.core.content.FileProvider;
import com.squareup.leakcanary.AnalysisResult;
import com.squareup.leakcanary.AnalyzedHeap;
import com.squareup.leakcanary.BuildConfig;
import com.squareup.leakcanary.CanaryLog;
import com.squareup.leakcanary.HeapDump;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.LeakDirectoryProvider;
import com.squareup.leakcanary.R;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;
/* loaded from: classes.dex */
public final class DisplayLeakActivity extends Activity {
private static final String SHOW_LEAK_EXTRA = "show_latest";
private Button actionButton;
private TextView failureView;
List<AnalyzedHeap> leaks;
private ListView listView;
String visibleLeakRefKey;
class LeakListAdapter extends BaseAdapter {
LeakListAdapter() {
}
@Override // android.widget.Adapter
public int getCount() {
return DisplayLeakActivity.this.leaks.size();
}
@Override // android.widget.Adapter
public long getItemId(int i) {
return i;
}
@Override // android.widget.Adapter
public View getView(int i, View view, ViewGroup viewGroup) {
String str;
String string;
if (view == null) {
view = LayoutInflater.from(DisplayLeakActivity.this).inflate(R.layout.leak_canary_leak_row, viewGroup, false);
}
TextView textView = (TextView) view.findViewById(R.id.leak_canary_row_text);
TextView textView2 = (TextView) view.findViewById(R.id.leak_canary_row_time);
AnalyzedHeap item = getItem(i);
String str2 = (DisplayLeakActivity.this.leaks.size() - i) + ". ";
AnalysisResult analysisResult = item.result;
if (analysisResult.failure != null) {
str = str2 + item.result.failure.getClass().getSimpleName() + " " + item.result.failure.getMessage();
} else {
String classSimpleName = DisplayLeakActivity.classSimpleName(analysisResult.className);
AnalysisResult analysisResult2 = item.result;
if (analysisResult2.leakFound) {
long j = analysisResult2.retainedHeapSize;
if (j == -1) {
string = DisplayLeakActivity.this.getString(R.string.leak_canary_class_has_leaked, new Object[]{classSimpleName});
} else {
string = DisplayLeakActivity.this.getString(R.string.leak_canary_class_has_leaked_retaining, new Object[]{classSimpleName, Formatter.formatShortFileSize(DisplayLeakActivity.this, j)});
}
if (item.result.excludedLeak) {
string = DisplayLeakActivity.this.getString(R.string.leak_canary_excluded_row, new Object[]{string});
}
str = str2 + string;
} else {
str = str2 + DisplayLeakActivity.this.getString(R.string.leak_canary_class_no_leak, new Object[]{classSimpleName});
}
}
textView.setText(str);
textView2.setText(DateUtils.formatDateTime(DisplayLeakActivity.this, item.selfLastModified, 17));
return view;
}
@Override // android.widget.Adapter
public AnalyzedHeap getItem(int i) {
return DisplayLeakActivity.this.leaks.get(i);
}
}
static class LoadLeaks implements Runnable {
DisplayLeakActivity activityOrNull;
private final LeakDirectoryProvider leakDirectoryProvider;
private final Handler mainHandler = new Handler(Looper.getMainLooper());
static final List<LoadLeaks> inFlight = new ArrayList();
static final Executor backgroundExecutor = LeakCanaryInternals.newSingleThreadExecutor("LoadLeaks");
LoadLeaks(DisplayLeakActivity displayLeakActivity, LeakDirectoryProvider leakDirectoryProvider) {
this.activityOrNull = displayLeakActivity;
this.leakDirectoryProvider = leakDirectoryProvider;
}
static void forgetActivity() {
Iterator<LoadLeaks> it = inFlight.iterator();
while (it.hasNext()) {
it.next().activityOrNull = null;
}
inFlight.clear();
}
static void load(DisplayLeakActivity displayLeakActivity, LeakDirectoryProvider leakDirectoryProvider) {
LoadLeaks loadLeaks = new LoadLeaks(displayLeakActivity, leakDirectoryProvider);
inFlight.add(loadLeaks);
backgroundExecutor.execute(loadLeaks);
}
@Override // java.lang.Runnable
public void run() {
final ArrayList arrayList = new ArrayList();
Iterator<File> it = this.leakDirectoryProvider.listFiles(new FilenameFilter() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.LoadLeaks.1
@Override // java.io.FilenameFilter
public boolean accept(File file, String str) {
return str.endsWith(".result");
}
}).iterator();
while (it.hasNext()) {
AnalyzedHeap load = AnalyzedHeap.load(it.next());
if (load != null) {
arrayList.add(load);
}
}
Collections.sort(arrayList, new Comparator<AnalyzedHeap>() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.LoadLeaks.2
@Override // java.util.Comparator
public int compare(AnalyzedHeap analyzedHeap, AnalyzedHeap analyzedHeap2) {
return Long.valueOf(analyzedHeap2.selfFile.lastModified()).compareTo(Long.valueOf(analyzedHeap.selfFile.lastModified()));
}
});
this.mainHandler.post(new Runnable() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.LoadLeaks.3
@Override // java.lang.Runnable
public void run() {
LoadLeaks.inFlight.remove(LoadLeaks.this);
DisplayLeakActivity displayLeakActivity = LoadLeaks.this.activityOrNull;
if (displayLeakActivity != null) {
displayLeakActivity.leaks = arrayList;
displayLeakActivity.updateUi();
}
}
});
}
}
static String classSimpleName(String str) {
int lastIndexOf = str.lastIndexOf(46);
return lastIndexOf == -1 ? str : str.substring(lastIndexOf + 1);
}
public static PendingIntent createPendingIntent(Context context) {
return createPendingIntent(context, null);
}
private void setDisplayHomeAsUpEnabled(boolean z) {
ActionBar actionBar = getActionBar();
if (actionBar == null) {
return;
}
actionBar.setDisplayHomeAsUpEnabled(z);
}
/* JADX INFO: Access modifiers changed from: private */
public void startShareIntentChooser(Uri uri) {
Intent intent = new Intent("android.intent.action.SEND");
intent.setType("application/octet-stream");
intent.putExtra("android.intent.extra.STREAM", uri);
startActivity(Intent.createChooser(intent, getString(R.string.leak_canary_share_with)));
}
void deleteAllLeaks() {
final LeakDirectoryProvider leakDirectoryProvider = LeakCanaryInternals.getLeakDirectoryProvider(this);
AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.5
@Override // java.lang.Runnable
public void run() {
leakDirectoryProvider.clearLeakDirectory();
}
});
this.leaks = Collections.emptyList();
updateUi();
}
void deleteVisibleLeak() {
final AnalyzedHeap visibleLeak = getVisibleLeak();
AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.4
@Override // java.lang.Runnable
public void run() {
AnalyzedHeap analyzedHeap = visibleLeak;
File file = analyzedHeap.heapDump.heapDumpFile;
File file2 = analyzedHeap.selfFile;
if (!file2.delete()) {
CanaryLog.d("Could not delete result file %s", file2.getPath());
}
if (file.delete()) {
return;
}
CanaryLog.d("Could not delete heap dump file %s", file.getPath());
}
});
this.visibleLeakRefKey = null;
this.leaks.remove(visibleLeak);
updateUi();
}
AnalyzedHeap getVisibleLeak() {
List<AnalyzedHeap> list = this.leaks;
if (list == null) {
return null;
}
for (AnalyzedHeap analyzedHeap : list) {
if (analyzedHeap.heapDump.referenceKey.equals(this.visibleLeakRefKey)) {
return analyzedHeap;
}
}
return null;
}
@Override // android.app.Activity
public void onBackPressed() {
if (this.visibleLeakRefKey == null) {
super.onBackPressed();
} else {
this.visibleLeakRefKey = null;
updateUi();
}
}
@Override // android.app.Activity
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
if (bundle != null) {
this.visibleLeakRefKey = bundle.getString("visibleLeakRefKey");
} else {
Intent intent = getIntent();
if (intent.hasExtra(SHOW_LEAK_EXTRA)) {
this.visibleLeakRefKey = intent.getStringExtra(SHOW_LEAK_EXTRA);
}
}
this.leaks = (List) getLastNonConfigurationInstance();
setContentView(R.layout.leak_canary_display_leak);
this.listView = (ListView) findViewById(R.id.leak_canary_display_leak_list);
this.failureView = (TextView) findViewById(R.id.leak_canary_display_leak_failure);
this.actionButton = (Button) findViewById(R.id.leak_canary_action);
updateUi();
}
@Override // android.app.Activity
public boolean onCreateOptionsMenu(Menu menu) {
AnalyzedHeap visibleLeak = getVisibleLeak();
if (visibleLeak == null) {
return false;
}
menu.add(R.string.leak_canary_share_leak).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.1
@Override // android.view.MenuItem.OnMenuItemClickListener
public boolean onMenuItemClick(MenuItem menuItem) {
DisplayLeakActivity.this.shareLeak();
return true;
}
});
if (!visibleLeak.heapDumpFileExists) {
return true;
}
menu.add(R.string.leak_canary_share_heap_dump).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.2
@Override // android.view.MenuItem.OnMenuItemClickListener
public boolean onMenuItemClick(MenuItem menuItem) {
DisplayLeakActivity.this.shareHeapDump();
return true;
}
});
return true;
}
@Override // android.app.Activity
protected void onDestroy() {
super.onDestroy();
LoadLeaks.forgetActivity();
}
@Override // android.app.Activity
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() != 16908332) {
return true;
}
this.visibleLeakRefKey = null;
updateUi();
return true;
}
@Override // android.app.Activity
protected void onResume() {
super.onResume();
LoadLeaks.load(this, LeakCanaryInternals.getLeakDirectoryProvider(this));
}
@Override // android.app.Activity
public Object onRetainNonConfigurationInstance() {
return this.leaks;
}
@Override // android.app.Activity
protected void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
bundle.putString("visibleLeakRefKey", this.visibleLeakRefKey);
}
@Override // android.app.Activity, android.view.ContextThemeWrapper, android.content.ContextWrapper, android.content.Context
public void setTheme(int i) {
if (i != R.style.leak_canary_LeakCanary_Base) {
return;
}
super.setTheme(i);
}
@SuppressLint({"SetWorldReadable"})
void shareHeapDump() {
final File file = getVisibleLeak().heapDump.heapDumpFile;
AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.3
@Override // java.lang.Runnable
public void run() {
file.setReadable(true, false);
final Uri uriForFile = FileProvider.getUriForFile(DisplayLeakActivity.this.getBaseContext(), "com.squareup.leakcanary.fileprovider." + DisplayLeakActivity.this.getApplication().getPackageName(), file);
DisplayLeakActivity.this.runOnUiThread(new Runnable() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.3.1
@Override // java.lang.Runnable
public void run() {
DisplayLeakActivity.this.startShareIntentChooser(uriForFile);
}
});
}
});
}
void shareLeak() {
AnalyzedHeap visibleLeak = getVisibleLeak();
String leakInfo = LeakCanary.leakInfo(this, visibleLeak.heapDump, visibleLeak.result, true);
Intent intent = new Intent("android.intent.action.SEND");
intent.setType("text/plain");
intent.putExtra("android.intent.extra.TEXT", leakInfo);
startActivity(Intent.createChooser(intent, getString(R.string.leak_canary_share_with)));
}
void updateUi() {
String string;
List<AnalyzedHeap> list = this.leaks;
if (list == null) {
setTitle("Loading leaks...");
return;
}
if (list.isEmpty()) {
this.visibleLeakRefKey = null;
}
AnalyzedHeap visibleLeak = getVisibleLeak();
if (visibleLeak == null) {
this.visibleLeakRefKey = null;
}
ListAdapter adapter = this.listView.getAdapter();
this.listView.setVisibility(0);
this.failureView.setVisibility(8);
if (visibleLeak == null) {
if (adapter instanceof LeakListAdapter) {
((LeakListAdapter) adapter).notifyDataSetChanged();
} else {
this.listView.setAdapter((ListAdapter) new LeakListAdapter());
this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.8
@Override // android.widget.AdapterView.OnItemClickListener
public void onItemClick(AdapterView<?> adapterView, View view, int i, long j) {
DisplayLeakActivity displayLeakActivity = DisplayLeakActivity.this;
displayLeakActivity.visibleLeakRefKey = displayLeakActivity.leaks.get(i).heapDump.referenceKey;
DisplayLeakActivity.this.updateUi();
}
});
invalidateOptionsMenu();
setTitle(getString(R.string.leak_canary_leak_list_title, new Object[]{getPackageName()}));
setDisplayHomeAsUpEnabled(false);
this.actionButton.setText(R.string.leak_canary_delete_all);
this.actionButton.setOnClickListener(new View.OnClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.9
@Override // android.view.View.OnClickListener
public void onClick(View view) {
new AlertDialog.Builder(DisplayLeakActivity.this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(R.string.leak_canary_delete_all).setMessage(R.string.leak_canary_delete_all_leaks_title).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.9.1
@Override // android.content.DialogInterface.OnClickListener
public void onClick(DialogInterface dialogInterface, int i) {
DisplayLeakActivity.this.deleteAllLeaks();
}
}).setNegativeButton(android.R.string.cancel, (DialogInterface.OnClickListener) null).show();
}
});
}
this.actionButton.setVisibility(this.leaks.size() == 0 ? 8 : 0);
return;
}
AnalysisResult analysisResult = visibleLeak.result;
this.actionButton.setVisibility(0);
this.actionButton.setText(R.string.leak_canary_delete);
this.actionButton.setOnClickListener(new View.OnClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.6
@Override // android.view.View.OnClickListener
public void onClick(View view) {
DisplayLeakActivity.this.deleteVisibleLeak();
}
});
invalidateOptionsMenu();
setDisplayHomeAsUpEnabled(true);
if (analysisResult.leakFound) {
final DisplayLeakAdapter displayLeakAdapter = new DisplayLeakAdapter(getResources());
this.listView.setAdapter((ListAdapter) displayLeakAdapter);
this.listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // from class: com.squareup.leakcanary.internal.DisplayLeakActivity.7
@Override // android.widget.AdapterView.OnItemClickListener
public void onItemClick(AdapterView<?> adapterView, View view, int i, long j) {
displayLeakAdapter.toggleRow(i);
}
});
HeapDump heapDump = visibleLeak.heapDump;
displayLeakAdapter.update(analysisResult.leakTrace, heapDump.referenceKey, heapDump.referenceName);
long j = analysisResult.retainedHeapSize;
if (j == -1) {
setTitle(getString(R.string.leak_canary_class_has_leaked, new Object[]{classSimpleName(analysisResult.className)}));
return;
} else {
setTitle(getString(R.string.leak_canary_class_has_leaked_retaining, new Object[]{classSimpleName(analysisResult.className), Formatter.formatShortFileSize(this, j)}));
return;
}
}
this.listView.setVisibility(8);
this.failureView.setVisibility(0);
this.listView.setAdapter((ListAdapter) null);
if (analysisResult.failure != null) {
setTitle(R.string.leak_canary_analysis_failed);
string = getString(R.string.leak_canary_failure_report) + BuildConfig.LIBRARY_VERSION + " " + BuildConfig.GIT_SHA + "\n" + Log.getStackTraceString(analysisResult.failure);
} else {
setTitle(getString(R.string.leak_canary_class_no_leak, new Object[]{classSimpleName(analysisResult.className)}));
string = getString(R.string.leak_canary_no_leak_details);
}
this.failureView.setText(string + "\n\n" + getString(R.string.leak_canary_download_dump, new Object[]{visibleLeak.heapDump.heapDumpFile.getAbsolutePath()}));
}
public static PendingIntent createPendingIntent(Context context, String str) {
LeakCanaryInternals.setEnabledBlocking(context, DisplayLeakActivity.class, true);
Intent intent = new Intent(context, (Class<?>) DisplayLeakActivity.class);
intent.putExtra(SHOW_LEAK_EXTRA, str);
intent.setFlags(335544320);
return PendingIntent.getActivity(context, 1, intent, 134217728);
}
}