Initial commit

This commit is contained in:
2025-05-13 19:24:51 +02:00
commit a950f49678
10604 changed files with 932663 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
package com.squareup.leakcanary.internal;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
/* loaded from: classes.dex */
public abstract class ActivityLifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks {
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityCreated(Activity activity, Bundle bundle) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityDestroyed(Activity activity) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityPaused(Activity activity) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityResumed(Activity activity) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityStarted(Activity activity) {
}
@Override // android.app.Application.ActivityLifecycleCallbacks
public void onActivityStopped(Activity activity) {
}
}

View File

@@ -0,0 +1,35 @@
package com.squareup.leakcanary.internal;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.view.View;
import com.squareup.leakcanary.RefWatcher;
/* loaded from: classes.dex */
class AndroidOFragmentRefWatcher implements FragmentRefWatcher {
private final FragmentManager.FragmentLifecycleCallbacks fragmentLifecycleCallbacks = new FragmentManager.FragmentLifecycleCallbacks() { // from class: com.squareup.leakcanary.internal.AndroidOFragmentRefWatcher.1
@Override // android.app.FragmentManager.FragmentLifecycleCallbacks
public void onFragmentDestroyed(FragmentManager fragmentManager, Fragment fragment) {
AndroidOFragmentRefWatcher.this.refWatcher.watch(fragment);
}
@Override // android.app.FragmentManager.FragmentLifecycleCallbacks
public void onFragmentViewDestroyed(FragmentManager fragmentManager, Fragment fragment) {
View view = fragment.getView();
if (view != null) {
AndroidOFragmentRefWatcher.this.refWatcher.watch(view);
}
}
};
private final RefWatcher refWatcher;
AndroidOFragmentRefWatcher(RefWatcher refWatcher) {
this.refWatcher = refWatcher;
}
@Override // com.squareup.leakcanary.internal.FragmentRefWatcher
public void watchFragments(Activity activity) {
activity.getFragmentManager().registerFragmentLifecycleCallbacks(this.fragmentLifecycleCallbacks, true);
}
}

View File

@@ -0,0 +1,470 @@
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);
}
}

View File

@@ -0,0 +1,250 @@
package com.squareup.leakcanary.internal;
import android.content.Context;
import android.content.res.Resources;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.squareup.leakcanary.Exclusion;
import com.squareup.leakcanary.LeakReference;
import com.squareup.leakcanary.LeakTrace;
import com.squareup.leakcanary.LeakTraceElement;
import com.squareup.leakcanary.R;
import com.squareup.leakcanary.Reachability;
import com.squareup.leakcanary.internal.DisplayLeakConnectorView;
/* loaded from: classes.dex */
final class DisplayLeakAdapter extends BaseAdapter {
private static final int NORMAL_ROW = 1;
private static final int TOP_ROW = 0;
private final String classNameColorHexString;
private final String extraColorHexString;
private final String helpColorHexString;
private final String leakColorHexString;
private final String referenceColorHexString;
private String referenceKey;
private boolean[] opened = new boolean[0];
private LeakTrace leakTrace = null;
private String referenceName = "";
/* renamed from: com.squareup.leakcanary.internal.DisplayLeakAdapter$1, reason: invalid class name */
static /* synthetic */ class AnonymousClass1 {
static final /* synthetic */ int[] $SwitchMap$com$squareup$leakcanary$Reachability = new int[Reachability.values().length];
static {
try {
$SwitchMap$com$squareup$leakcanary$Reachability[Reachability.UNKNOWN.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
$SwitchMap$com$squareup$leakcanary$Reachability[Reachability.REACHABLE.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
try {
$SwitchMap$com$squareup$leakcanary$Reachability[Reachability.UNREACHABLE.ordinal()] = 3;
} catch (NoSuchFieldError unused3) {
}
}
}
DisplayLeakAdapter(Resources resources) {
this.classNameColorHexString = hexStringColor(resources, R.color.leak_canary_class_name);
this.leakColorHexString = hexStringColor(resources, R.color.leak_canary_leak);
this.referenceColorHexString = hexStringColor(resources, R.color.leak_canary_reference);
this.extraColorHexString = hexStringColor(resources, R.color.leak_canary_extra);
this.helpColorHexString = hexStringColor(resources, R.color.leak_canary_help);
}
private int elementIndex(int i) {
return i - 2;
}
private static <T extends View> T findById(View view, int i) {
return (T) view.findViewById(i);
}
private DisplayLeakConnectorView.Type getConnectorType(int i) {
if (i == 1) {
return DisplayLeakConnectorView.Type.HELP;
}
if (i == 2) {
return this.leakTrace.expectedReachability.size() == 1 ? DisplayLeakConnectorView.Type.START_LAST_REACHABLE : this.leakTrace.expectedReachability.get(elementIndex(i + 1)) != Reachability.REACHABLE ? DisplayLeakConnectorView.Type.START_LAST_REACHABLE : DisplayLeakConnectorView.Type.START;
}
if (i == getCount() - 1) {
return this.leakTrace.expectedReachability.get(elementIndex(i - 1)) != Reachability.UNREACHABLE ? DisplayLeakConnectorView.Type.END_FIRST_UNREACHABLE : DisplayLeakConnectorView.Type.END;
}
Reachability reachability = this.leakTrace.expectedReachability.get(elementIndex(i));
int i2 = AnonymousClass1.$SwitchMap$com$squareup$leakcanary$Reachability[reachability.ordinal()];
if (i2 == 1) {
return DisplayLeakConnectorView.Type.NODE_UNKNOWN;
}
if (i2 == 2) {
return this.leakTrace.expectedReachability.get(elementIndex(i + 1)) != Reachability.REACHABLE ? DisplayLeakConnectorView.Type.NODE_LAST_REACHABLE : DisplayLeakConnectorView.Type.NODE_REACHABLE;
}
if (i2 == 3) {
return this.leakTrace.expectedReachability.get(elementIndex(i - 1)) != Reachability.UNREACHABLE ? DisplayLeakConnectorView.Type.NODE_FIRST_UNREACHABLE : DisplayLeakConnectorView.Type.NODE_UNREACHABLE;
}
throw new IllegalStateException("Unknown value: " + reachability);
}
private static String hexStringColor(Resources resources, int i) {
return String.format("#%06X", Integer.valueOf(resources.getColor(i) & 16777215));
}
private Spanned htmlDetails(boolean z, LeakTraceElement leakTraceElement) {
String str;
if (leakTraceElement.extra != null) {
str = " <font color='" + this.extraColorHexString + "'>" + leakTraceElement.extra + "</font>";
} else {
str = "";
}
Exclusion exclusion = leakTraceElement.exclusion;
if (exclusion != null) {
String str2 = str + "<br/><br/>Excluded by rule";
if (exclusion.name != null) {
str2 = str2 + " <font color='#ffffff'>" + exclusion.name + "</font>";
}
str = str2 + " matching <font color='#f3cf83'>" + exclusion.matching + "</font>";
if (exclusion.reason != null) {
str = str + " because <font color='#f3cf83'>" + exclusion.reason + "</font>";
}
}
String str3 = str + "<br><font color='" + this.extraColorHexString + "'>" + leakTraceElement.toDetailedString().replace("\n", "<br>") + "</font>";
if (z && !this.referenceName.equals("")) {
str3 = str3 + " <font color='" + this.extraColorHexString + "'>" + this.referenceName + "</font>";
}
return Html.fromHtml(str3);
}
private Spanned htmlTitle(LeakTraceElement leakTraceElement, boolean z, Resources resources) {
String str;
String str2;
String str3 = "<font color='" + this.classNameColorHexString + "'>" + leakTraceElement.getSimpleClassName().replace("[]", "[ ]") + "</font>";
LeakReference leakReference = leakTraceElement.reference;
if (leakReference != null) {
String replaceAll = leakReference.getDisplayName().replaceAll("<", "&lt;").replaceAll(">", "&gt;");
if (z) {
str2 = "<u><font color='" + this.leakColorHexString + "'>" + replaceAll + "</font></u>";
} else {
str2 = "<font color='" + this.referenceColorHexString + "'>" + replaceAll + "</font>";
}
if (leakTraceElement.reference.type == LeakTraceElement.Type.STATIC_FIELD) {
str2 = "<i>" + str2 + "</i>";
}
String str4 = str3 + "." + str2;
if (z) {
str4 = "<b>" + str4 + "</b>";
}
str = "" + str4;
} else {
str = "" + str3;
}
if (leakTraceElement.exclusion != null) {
str = str + " (excluded)";
}
SpannableStringBuilder spannableStringBuilder = (SpannableStringBuilder) Html.fromHtml(str);
if (z) {
SquigglySpan.replaceUnderlineSpans(spannableStringBuilder, resources);
}
return spannableStringBuilder;
}
@Override // android.widget.Adapter
public int getCount() {
LeakTrace leakTrace = this.leakTrace;
if (leakTrace == null) {
return 2;
}
return leakTrace.elements.size() + 2;
}
@Override // android.widget.Adapter
public long getItemId(int i) {
return i;
}
@Override // android.widget.BaseAdapter, android.widget.Adapter
public int getItemViewType(int i) {
return i == 0 ? 0 : 1;
}
@Override // android.widget.Adapter
public View getView(int i, View view, ViewGroup viewGroup) {
Context context = viewGroup.getContext();
boolean z = false;
if (getItemViewType(i) == 0) {
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.leak_canary_ref_top_row, viewGroup, false);
}
((TextView) findById(view, R.id.leak_canary_row_text)).setText(context.getPackageName());
} else {
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.leak_canary_ref_row, viewGroup, false);
}
TextView textView = (TextView) findById(view, R.id.leak_canary_row_title);
TextView textView2 = (TextView) findById(view, R.id.leak_canary_row_details);
DisplayLeakConnectorView displayLeakConnectorView = (DisplayLeakConnectorView) findById(view, R.id.leak_canary_row_connector);
MoreDetailsView moreDetailsView = (MoreDetailsView) findById(view, R.id.leak_canary_row_more);
displayLeakConnectorView.setType(getConnectorType(i));
moreDetailsView.setOpened(this.opened[i]);
if (this.opened[i]) {
textView2.setVisibility(0);
} else {
textView2.setVisibility(8);
}
Resources resources = view.getResources();
if (i == 1) {
textView.setText(Html.fromHtml("<font color='" + this.helpColorHexString + "'><b>" + resources.getString(R.string.leak_canary_help_title) + "</b></font>"));
SpannableStringBuilder spannableStringBuilder = (SpannableStringBuilder) Html.fromHtml(resources.getString(R.string.leak_canary_help_detail));
SquigglySpan.replaceUnderlineSpans(spannableStringBuilder, resources);
textView2.setText(spannableStringBuilder);
} else {
boolean z2 = i == getCount() - 1;
LeakTraceElement item = getItem(i);
Reachability reachability = this.leakTrace.expectedReachability.get(elementIndex(i));
if (!z2 && reachability != Reachability.UNREACHABLE && this.leakTrace.expectedReachability.get(elementIndex(i + 1)) != Reachability.REACHABLE) {
z = true;
}
textView.setText(htmlTitle(item, z, resources));
if (this.opened[i]) {
textView2.setText(htmlDetails(z2, item));
}
}
}
return view;
}
@Override // android.widget.BaseAdapter, android.widget.Adapter
public int getViewTypeCount() {
return 2;
}
public void toggleRow(int i) {
this.opened[i] = !r0[i];
notifyDataSetChanged();
}
public void update(LeakTrace leakTrace, String str, String str2) {
if (str.equals(this.referenceKey)) {
return;
}
this.referenceKey = str;
this.referenceName = str2;
this.leakTrace = leakTrace;
this.opened = new boolean[leakTrace.elements.size() + 2];
notifyDataSetChanged();
}
@Override // android.widget.Adapter
public LeakTraceElement getItem(int i) {
if (getItemViewType(i) == 0 || i == 1) {
return null;
}
return this.leakTrace.elements.get(elementIndex(i));
}
}

View File

@@ -0,0 +1,228 @@
package com.squareup.leakcanary.internal;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
public final class DisplayLeakConnectorView extends View {
private Bitmap cache;
private final float circleY;
private final Paint classNamePaint;
private final Paint clearPaint;
private final Paint leakPaint;
private final Paint referencePaint;
private final float strokeSize;
private Type type;
private static final float SQRT_TWO = (float) Math.sqrt(2.0d);
private static final PorterDuffXfermode CLEAR_XFER_MODE = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
/* renamed from: com.squareup.leakcanary.internal.DisplayLeakConnectorView$1, reason: invalid class name */
static /* synthetic */ class AnonymousClass1 {
static final /* synthetic */ int[] $SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type = new int[Type.values().length];
static {
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.NODE_UNKNOWN.ordinal()] = 1;
} catch (NoSuchFieldError unused) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.NODE_UNREACHABLE.ordinal()] = 2;
} catch (NoSuchFieldError unused2) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.NODE_REACHABLE.ordinal()] = 3;
} catch (NoSuchFieldError unused3) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.NODE_FIRST_UNREACHABLE.ordinal()] = 4;
} catch (NoSuchFieldError unused4) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.NODE_LAST_REACHABLE.ordinal()] = 5;
} catch (NoSuchFieldError unused5) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.START.ordinal()] = 6;
} catch (NoSuchFieldError unused6) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.START_LAST_REACHABLE.ordinal()] = 7;
} catch (NoSuchFieldError unused7) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.END.ordinal()] = 8;
} catch (NoSuchFieldError unused8) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.END_FIRST_UNREACHABLE.ordinal()] = 9;
} catch (NoSuchFieldError unused9) {
}
try {
$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[Type.HELP.ordinal()] = 10;
} catch (NoSuchFieldError unused10) {
}
}
}
public enum Type {
HELP,
START,
START_LAST_REACHABLE,
NODE_UNKNOWN,
NODE_FIRST_UNREACHABLE,
NODE_UNREACHABLE,
NODE_REACHABLE,
NODE_LAST_REACHABLE,
END,
END_FIRST_UNREACHABLE
}
public DisplayLeakConnectorView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
Resources resources = getResources();
this.type = Type.NODE_UNKNOWN;
this.circleY = resources.getDimensionPixelSize(R.dimen.leak_canary_connector_center_y);
this.strokeSize = resources.getDimensionPixelSize(R.dimen.leak_canary_connector_stroke_size);
this.classNamePaint = new Paint(1);
this.classNamePaint.setColor(resources.getColor(R.color.leak_canary_class_name));
this.classNamePaint.setStrokeWidth(this.strokeSize);
this.leakPaint = new Paint(1);
this.leakPaint.setColor(resources.getColor(R.color.leak_canary_leak));
this.leakPaint.setStyle(Paint.Style.STROKE);
this.leakPaint.setStrokeWidth(this.strokeSize);
this.leakPaint.setPathEffect(new DashPathEffect(new float[]{resources.getDimensionPixelSize(R.dimen.leak_canary_connector_leak_dash_line), resources.getDimensionPixelSize(R.dimen.leak_canary_connector_leak_dash_gap)}, 0.0f));
this.clearPaint = new Paint(1);
this.clearPaint.setColor(0);
this.clearPaint.setXfermode(CLEAR_XFER_MODE);
this.referencePaint = new Paint(1);
this.referencePaint.setColor(resources.getColor(R.color.leak_canary_reference));
this.referencePaint.setStrokeWidth(this.strokeSize);
}
private void drawArrowHead(Canvas canvas, Paint paint) {
float measuredWidth = getMeasuredWidth();
float f = measuredWidth / 2.0f;
float f2 = measuredWidth / 3.0f;
float f3 = (f / 2.0f) * SQRT_TWO;
float f4 = this.strokeSize;
float f5 = this.circleY;
float f6 = ((f5 - f3) - (f2 * 2.0f)) - f4;
canvas.drawLine(f, 0.0f, f, (f5 - f2) - (f4 / 2.0f), paint);
canvas.translate(f, f6);
canvas.rotate(45.0f);
canvas.drawLine(0.0f, f, f + (f4 / 2.0f), f, paint);
canvas.drawLine(f, 0.0f, f, f, paint);
canvas.rotate(-45.0f);
canvas.translate(-f, -f6);
}
private void drawInstanceCircle(Canvas canvas) {
float measuredWidth = getMeasuredWidth();
canvas.drawCircle(measuredWidth / 2.0f, this.circleY, measuredWidth / 3.0f, this.classNamePaint);
}
private void drawItems(Canvas canvas, Paint paint, Paint paint2) {
if (paint != null) {
drawArrowHead(canvas, paint);
}
if (paint2 != null) {
drawNextArrowLine(canvas, paint2);
}
drawInstanceCircle(canvas);
}
private void drawNextArrowLine(Canvas canvas, Paint paint) {
float measuredWidth = getMeasuredWidth() / 2.0f;
canvas.drawLine(measuredWidth, this.circleY, measuredWidth, getMeasuredHeight(), paint);
}
private void drawRoot(Canvas canvas) {
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
float f = measuredWidth;
float f2 = f / 2.0f;
float f3 = f2 - (this.strokeSize / 2.0f);
canvas.drawRect(0.0f, 0.0f, f, f3, this.classNamePaint);
canvas.drawCircle(0.0f, f3, f3, this.clearPaint);
canvas.drawCircle(f, f3, f3, this.clearPaint);
canvas.drawLine(f2, 0.0f, f2, measuredHeight, this.classNamePaint);
}
private void drawStartLine(Canvas canvas) {
float measuredWidth = getMeasuredWidth() / 2.0f;
canvas.drawLine(measuredWidth, 0.0f, measuredWidth, this.circleY, this.classNamePaint);
}
@Override // android.view.View
protected void onDraw(Canvas canvas) {
int measuredWidth = getMeasuredWidth();
int measuredHeight = getMeasuredHeight();
Bitmap bitmap = this.cache;
if (bitmap != null && (bitmap.getWidth() != measuredWidth || this.cache.getHeight() != measuredHeight)) {
this.cache.recycle();
this.cache = null;
}
if (this.cache == null) {
this.cache = Bitmap.createBitmap(measuredWidth, measuredHeight, Bitmap.Config.ARGB_8888);
Canvas canvas2 = new Canvas(this.cache);
switch (AnonymousClass1.$SwitchMap$com$squareup$leakcanary$internal$DisplayLeakConnectorView$Type[this.type.ordinal()]) {
case 1:
Paint paint = this.leakPaint;
drawItems(canvas2, paint, paint);
break;
case 2:
case 3:
Paint paint2 = this.referencePaint;
drawItems(canvas2, paint2, paint2);
break;
case 4:
drawItems(canvas2, this.leakPaint, this.referencePaint);
break;
case 5:
drawItems(canvas2, this.referencePaint, this.leakPaint);
break;
case 6:
drawStartLine(canvas2);
drawItems(canvas2, null, this.referencePaint);
break;
case 7:
drawStartLine(canvas2);
drawItems(canvas2, null, this.leakPaint);
break;
case 8:
drawItems(canvas2, this.referencePaint, null);
break;
case 9:
drawItems(canvas2, this.leakPaint, null);
break;
case 10:
drawRoot(canvas2);
break;
default:
throw new UnsupportedOperationException("Unknown type " + this.type);
}
}
canvas.drawBitmap(this.cache, 0.0f, 0.0f, (Paint) null);
}
public void setType(Type type) {
if (type != this.type) {
this.type = type;
Bitmap bitmap = this.cache;
if (bitmap != null) {
bitmap.recycle();
this.cache = null;
}
invalidate();
}
}
}

View File

@@ -0,0 +1,48 @@
package com.squareup.leakcanary.internal;
import android.app.IntentService;
import android.app.Notification;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
public abstract class ForegroundService extends IntentService {
private final int notificationContentTitleResId;
private final int notificationId;
public ForegroundService(String str, int i) {
super(str);
this.notificationContentTitleResId = i;
this.notificationId = (int) SystemClock.uptimeMillis();
}
@Override // android.app.IntentService, android.app.Service
public IBinder onBind(Intent intent) {
return null;
}
@Override // android.app.IntentService, android.app.Service
public void onCreate() {
super.onCreate();
showForegroundNotification(100, 0, true, getString(R.string.leak_canary_notification_foreground_text));
}
@Override // android.app.IntentService, android.app.Service
public void onDestroy() {
super.onDestroy();
stopForeground(true);
}
@Override // android.app.IntentService
protected void onHandleIntent(Intent intent) {
onHandleIntentInForeground(intent);
}
protected abstract void onHandleIntentInForeground(Intent intent);
protected void showForegroundNotification(int i, int i2, boolean z, String str) {
startForeground(this.notificationId, LeakCanaryInternals.buildNotification(this, new Notification.Builder(this).setContentTitle(getString(this.notificationContentTitleResId)).setContentText(str).setProgress(i, i2, z)));
}
}

View File

@@ -0,0 +1,50 @@
package com.squareup.leakcanary.internal;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import com.squareup.leakcanary.RefWatcher;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/* loaded from: classes.dex */
public interface FragmentRefWatcher {
public static final class Helper {
private static final String SUPPORT_FRAGMENT_REF_WATCHER_CLASS_NAME = "com.squareup.leakcanary.internal.SupportFragmentRefWatcher";
private final Application.ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacksAdapter() { // from class: com.squareup.leakcanary.internal.FragmentRefWatcher.Helper.1
@Override // com.squareup.leakcanary.internal.ActivityLifecycleCallbacksAdapter, android.app.Application.ActivityLifecycleCallbacks
public void onActivityCreated(Activity activity, Bundle bundle) {
Iterator it = Helper.this.fragmentRefWatchers.iterator();
while (it.hasNext()) {
((FragmentRefWatcher) it.next()).watchFragments(activity);
}
}
};
private final List<FragmentRefWatcher> fragmentRefWatchers;
private Helper(List<FragmentRefWatcher> list) {
this.fragmentRefWatchers = list;
}
public static void install(Context context, RefWatcher refWatcher) {
ArrayList arrayList = new ArrayList();
if (Build.VERSION.SDK_INT >= 26) {
arrayList.add(new AndroidOFragmentRefWatcher(refWatcher));
}
try {
arrayList.add((FragmentRefWatcher) Class.forName(SUPPORT_FRAGMENT_REF_WATCHER_CLASS_NAME).getDeclaredConstructor(RefWatcher.class).newInstance(refWatcher));
} catch (Exception unused) {
}
if (arrayList.size() == 0) {
return;
}
((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks(new Helper(arrayList).activityLifecycleCallbacks);
}
}
void watchFragments(Activity activity);
}

View File

@@ -0,0 +1,31 @@
package com.squareup.leakcanary.internal;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/* loaded from: classes.dex */
public final class FutureResult<T> {
private final AtomicReference<T> resultHolder = new AtomicReference<>();
private final CountDownLatch latch = new CountDownLatch(1);
public T get() {
if (this.latch.getCount() <= 0) {
return this.resultHolder.get();
}
throw new IllegalStateException("Call wait() and check its result");
}
public void set(T t) {
this.resultHolder.set(t);
this.latch.countDown();
}
public boolean wait(long j, TimeUnit timeUnit) {
try {
return this.latch.await(j, timeUnit);
} catch (InterruptedException e) {
throw new RuntimeException("Did not expect thread to be interrupted", e);
}
}
}

View File

@@ -0,0 +1,49 @@
package com.squareup.leakcanary.internal;
import android.content.Context;
import android.content.Intent;
import androidx.core.content.ContextCompat;
import com.squareup.leakcanary.AbstractAnalysisResultService;
import com.squareup.leakcanary.AnalyzerProgressListener;
import com.squareup.leakcanary.CanaryLog;
import com.squareup.leakcanary.HeapAnalyzer;
import com.squareup.leakcanary.HeapDump;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
public final class HeapAnalyzerService extends ForegroundService implements AnalyzerProgressListener {
private static final String HEAPDUMP_EXTRA = "heapdump_extra";
private static final String LISTENER_CLASS_EXTRA = "listener_class_extra";
public HeapAnalyzerService() {
super(HeapAnalyzerService.class.getSimpleName(), R.string.leak_canary_notification_analysing);
}
public static void runAnalysis(Context context, HeapDump heapDump, Class<? extends AbstractAnalysisResultService> cls) {
LeakCanaryInternals.setEnabledBlocking(context, HeapAnalyzerService.class, true);
LeakCanaryInternals.setEnabledBlocking(context, cls, true);
Intent intent = new Intent(context, (Class<?>) HeapAnalyzerService.class);
intent.putExtra(LISTENER_CLASS_EXTRA, cls.getName());
intent.putExtra(HEAPDUMP_EXTRA, heapDump);
ContextCompat.a(context, intent);
}
@Override // com.squareup.leakcanary.internal.ForegroundService
protected void onHandleIntentInForeground(Intent intent) {
if (intent == null) {
CanaryLog.d("HeapAnalyzerService received a null intent, ignoring.", new Object[0]);
return;
}
String stringExtra = intent.getStringExtra(LISTENER_CLASS_EXTRA);
HeapDump heapDump = (HeapDump) intent.getSerializableExtra(HEAPDUMP_EXTRA);
AbstractAnalysisResultService.sendResultToListener(this, stringExtra, heapDump, new HeapAnalyzer(heapDump.excludedRefs, this, heapDump.reachabilityInspectorClasses).checkForLeak(heapDump.heapDumpFile, heapDump.referenceKey, heapDump.computeRetainedHeapSize));
}
@Override // com.squareup.leakcanary.AnalyzerProgressListener
public void onProgressUpdate(AnalyzerProgressListener.Step step) {
int ordinal = (int) ((step.ordinal() * 100.0f) / AnalyzerProgressListener.Step.values().length);
CanaryLog.d("Analysis in progress, working on: %s", step.name());
String lowerCase = step.name().replace("_", " ").toLowerCase();
showForegroundNotification(100, ordinal, false, lowerCase.substring(0, 1).toUpperCase() + lowerCase.substring(1));
}
}

View File

@@ -0,0 +1,7 @@
package com.squareup.leakcanary.internal;
import androidx.core.content.FileProvider;
/* loaded from: classes.dex */
public class LeakCanaryFileProvider extends FileProvider {
}

View File

@@ -0,0 +1,140 @@
package com.squareup.leakcanary.internal;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Process;
import com.ijm.dataencryption.de.DataDecryptTool;
import com.squareup.leakcanary.CanaryLog;
import com.squareup.leakcanary.DefaultLeakDirectoryProvider;
import com.squareup.leakcanary.LeakDirectoryProvider;
import com.squareup.leakcanary.R;
import com.squareup.leakcanary.RefWatcher;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/* loaded from: classes.dex */
public final class LeakCanaryInternals {
public static final String HUAWEI = "HUAWEI";
public static final String LENOVO = "LENOVO";
public static final String LG = "LGE";
public static final String MEIZU = "Meizu";
public static final String MOTOROLA = "motorola";
private static final String NOTIFICATION_CHANNEL_ID = "leakcanary";
public static final String NVIDIA = "NVIDIA";
public static final String SAMSUNG = "samsung";
public static final String VIVO = "vivo";
public static volatile RefWatcher installedRefWatcher;
public static volatile Boolean isInAnalyzerProcess;
private static volatile LeakDirectoryProvider leakDirectoryProvider;
private LeakCanaryInternals() {
throw new AssertionError();
}
public static Notification buildNotification(Context context, Notification.Builder builder) {
builder.setSmallIcon(R.drawable.leak_canary_notification).setWhen(System.currentTimeMillis()).setOnlyAlertOnce(true);
if (Build.VERSION.SDK_INT >= 26) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService("notification");
if (notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) {
notificationManager.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID, context.getString(R.string.leak_canary_notification_channel), 3));
}
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
return Build.VERSION.SDK_INT < 16 ? builder.getNotification() : builder.build();
}
public static String classSimpleName(String str) {
int lastIndexOf = str.lastIndexOf(46);
return lastIndexOf == -1 ? str : str.substring(lastIndexOf + 1);
}
public static LeakDirectoryProvider getLeakDirectoryProvider(Context context) {
LeakDirectoryProvider leakDirectoryProvider2 = leakDirectoryProvider;
return leakDirectoryProvider2 == null ? new DefaultLeakDirectoryProvider(context) : leakDirectoryProvider2;
}
public static boolean isInServiceProcess(Context context, Class<? extends Service> cls) {
PackageManager packageManager = context.getPackageManager();
try {
String str = packageManager.getPackageInfo(context.getPackageName(), 4).applicationInfo.processName;
try {
ServiceInfo serviceInfo = packageManager.getServiceInfo(new ComponentName(context, cls), DataDecryptTool.DECRYPT_DB_FILE);
if (serviceInfo.processName.equals(str)) {
CanaryLog.d("Did not expect service %s to run in main process %s", cls, str);
return false;
}
int myPid = Process.myPid();
ActivityManager.RunningAppProcessInfo runningAppProcessInfo = null;
try {
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = ((ActivityManager) context.getSystemService("activity")).getRunningAppProcesses();
if (runningAppProcesses != null) {
Iterator<ActivityManager.RunningAppProcessInfo> it = runningAppProcesses.iterator();
while (true) {
if (!it.hasNext()) {
break;
}
ActivityManager.RunningAppProcessInfo next = it.next();
if (next.pid == myPid) {
runningAppProcessInfo = next;
break;
}
}
}
if (runningAppProcessInfo != null) {
return runningAppProcessInfo.processName.equals(serviceInfo.processName);
}
CanaryLog.d("Could not find running process for %d", Integer.valueOf(myPid));
return false;
} catch (SecurityException e) {
CanaryLog.d("Could not get running app processes %d", e);
return false;
}
} catch (PackageManager.NameNotFoundException unused) {
}
} catch (Exception e2) {
CanaryLog.d(e2, "Could not get package info for %s", context.getPackageName());
return false;
}
}
public static Executor newSingleThreadExecutor(String str) {
return Executors.newSingleThreadExecutor(new LeakCanarySingleThreadFactory(str));
}
public static void setEnabledAsync(Context context, final Class<?> cls, final boolean z) {
final Context applicationContext = context.getApplicationContext();
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() { // from class: com.squareup.leakcanary.internal.LeakCanaryInternals.1
@Override // java.lang.Runnable
public void run() {
LeakCanaryInternals.setEnabledBlocking(applicationContext, cls, z);
}
});
}
public static void setEnabledBlocking(Context context, Class<?> cls, boolean z) {
context.getPackageManager().setComponentEnabledSetting(new ComponentName(context, cls), z ? 1 : 2, 1);
}
public static void setLeakDirectoryProvider(LeakDirectoryProvider leakDirectoryProvider2) {
if (leakDirectoryProvider != null) {
throw new IllegalStateException("Cannot set the LeakDirectoryProvider after it has already been set. Try setting it before installing the RefWatcher.");
}
leakDirectoryProvider = leakDirectoryProvider2;
}
public static void showNotification(Context context, CharSequence charSequence, CharSequence charSequence2, PendingIntent pendingIntent, int i) {
((NotificationManager) context.getSystemService("notification")).notify(i, buildNotification(context, new Notification.Builder(context).setContentText(charSequence2).setContentTitle(charSequence).setAutoCancel(true).setContentIntent(pendingIntent)));
}
}

View File

@@ -0,0 +1,17 @@
package com.squareup.leakcanary.internal;
import java.util.concurrent.ThreadFactory;
/* loaded from: classes.dex */
final class LeakCanarySingleThreadFactory implements ThreadFactory {
private final String threadName;
LeakCanarySingleThreadFactory(String str) {
this.threadName = "LeakCanary-" + str;
}
@Override // java.util.concurrent.ThreadFactory
public Thread newThread(Runnable runnable) {
return new Thread(runnable, this.threadName);
}
}

View File

@@ -0,0 +1,51 @@
package com.squareup.leakcanary.internal;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
public final class MoreDetailsView extends View {
private final Paint iconPaint;
private boolean opened;
public MoreDetailsView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
Resources resources = getResources();
this.iconPaint = new Paint(1);
this.iconPaint.setStrokeWidth(resources.getDimensionPixelSize(R.dimen.leak_canary_more_stroke_width));
TypedArray obtainStyledAttributes = context.obtainStyledAttributes(attributeSet, R.styleable.leak_canary_MoreDetailsView);
int color = obtainStyledAttributes.getColor(R.styleable.leak_canary_MoreDetailsView_leak_canary_plus_color, -16777216);
obtainStyledAttributes.recycle();
this.iconPaint.setColor(color);
}
@Override // android.view.View
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
int i = height / 2;
int i2 = width / 2;
if (this.opened) {
float f = i;
canvas.drawLine(0.0f, f, width, f, this.iconPaint);
} else {
float f2 = i;
canvas.drawLine(0.0f, f2, width, f2, this.iconPaint);
float f3 = i2;
canvas.drawLine(f3, 0.0f, f3, height, this.iconPaint);
}
}
public void setOpened(boolean z) {
if (z != this.opened) {
this.opened = z;
invalidate();
}
}
}

View File

@@ -0,0 +1,51 @@
package com.squareup.leakcanary.internal;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import com.squareup.leakcanary.R;
@TargetApi(23)
/* loaded from: classes.dex */
public class RequestStoragePermissionActivity extends Activity {
public static PendingIntent createPendingIntent(Context context) {
LeakCanaryInternals.setEnabledBlocking(context, RequestStoragePermissionActivity.class, true);
Intent intent = new Intent(context, (Class<?>) RequestStoragePermissionActivity.class);
intent.setFlags(335544320);
return PendingIntent.getActivity(context, 1, intent, 134217728);
}
private boolean hasStoragePermission() {
return checkSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE") == 0;
}
@Override // android.app.Activity
public void finish() {
overridePendingTransition(0, 0);
super.finish();
}
@Override // android.app.Activity
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
if (bundle == null) {
if (hasStoragePermission()) {
finish();
} else {
requestPermissions(new String[]{"android.permission.WRITE_EXTERNAL_STORAGE"}, 42);
}
}
}
@Override // android.app.Activity
public void onRequestPermissionsResult(int i, String[] strArr, int[] iArr) {
if (!hasStoragePermission()) {
Toast.makeText(getApplication(), R.string.leak_canary_permission_not_granted, 1).show();
}
finish();
}
}

View File

@@ -0,0 +1,79 @@
package com.squareup.leakcanary.internal;
import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
public class RowElementLayout extends ViewGroup {
private View connector;
private final int connectorWidth;
private View details;
private final int minHeight;
private View moreButton;
private final int moreMarginTop;
private final int moreSize;
private final int rowMargins;
private View title;
private final int titleMarginTop;
public RowElementLayout(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
Resources resources = getResources();
this.connectorWidth = resources.getDimensionPixelSize(R.dimen.leak_canary_connector_width);
this.rowMargins = resources.getDimensionPixelSize(R.dimen.leak_canary_row_margins);
this.moreSize = resources.getDimensionPixelSize(R.dimen.leak_canary_more_size);
this.minHeight = resources.getDimensionPixelSize(R.dimen.leak_canary_row_min);
this.titleMarginTop = resources.getDimensionPixelSize(R.dimen.leak_canary_row_title_margin_top);
this.moreMarginTop = resources.getDimensionPixelSize(R.dimen.leak_canary_more_margin_top);
}
@Override // android.view.View
protected void onFinishInflate() {
super.onFinishInflate();
this.connector = findViewById(R.id.leak_canary_row_connector);
this.moreButton = findViewById(R.id.leak_canary_row_more);
this.title = findViewById(R.id.leak_canary_row_title);
this.details = findViewById(R.id.leak_canary_row_details);
}
@Override // android.view.ViewGroup, android.view.View
protected void onLayout(boolean z, int i, int i2, int i3, int i4) {
int measuredWidth = getMeasuredWidth();
int measuredWidth2 = this.rowMargins + this.connector.getMeasuredWidth();
View view = this.connector;
view.layout(this.rowMargins, 0, measuredWidth2, view.getMeasuredHeight());
View view2 = this.moreButton;
int i5 = this.rowMargins;
int i6 = this.moreSize;
int i7 = this.moreMarginTop;
view2.layout((measuredWidth - i5) - i6, i7, measuredWidth - i5, i6 + i7);
int i8 = measuredWidth2 + this.rowMargins;
int measuredHeight = this.titleMarginTop + this.title.getMeasuredHeight();
View view3 = this.title;
view3.layout(i8, this.titleMarginTop, view3.getMeasuredWidth() + i8, measuredHeight);
if (this.details.getVisibility() != 8) {
View view4 = this.details;
view4.layout(i8, measuredHeight, measuredWidth - this.rowMargins, view4.getMeasuredHeight() + measuredHeight);
}
}
@Override // android.view.View
protected void onMeasure(int i, int i2) {
int size = View.MeasureSpec.getSize(i);
this.title.measure(View.MeasureSpec.makeMeasureSpec(((size - this.connectorWidth) - this.moreSize) - (this.rowMargins * 4), Integer.MIN_VALUE), View.MeasureSpec.makeMeasureSpec(0, 0));
int makeMeasureSpec = View.MeasureSpec.makeMeasureSpec(this.moreSize, 1073741824);
this.moreButton.measure(makeMeasureSpec, makeMeasureSpec);
int measuredHeight = this.titleMarginTop + this.title.getMeasuredHeight();
this.details.measure(View.MeasureSpec.makeMeasureSpec((size - this.connectorWidth) - (this.rowMargins * 3), Integer.MIN_VALUE), View.MeasureSpec.makeMeasureSpec(0, 0));
if (this.details.getVisibility() != 8) {
measuredHeight += this.details.getMeasuredHeight();
}
int max = Math.max(measuredHeight, this.minHeight);
this.connector.measure(View.MeasureSpec.makeMeasureSpec(this.connectorWidth, 1073741824), View.MeasureSpec.makeMeasureSpec(max, 1073741824));
setMeasuredDimension(size, max);
}
}

View File

@@ -0,0 +1,69 @@
package com.squareup.leakcanary.internal;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.text.SpannableStringBuilder;
import android.text.style.ReplacementSpan;
import android.text.style.UnderlineSpan;
import com.squareup.leakcanary.R;
/* loaded from: classes.dex */
class SquigglySpan extends ReplacementSpan {
private final float amplitude;
private final float halfStrokeWidth;
private final float halfWaveHeight;
private final Path path;
private final float periodDegrees;
private final int referenceColor;
private final Paint squigglyPaint = new Paint(1);
private int width;
SquigglySpan(Resources resources) {
this.squigglyPaint.setStyle(Paint.Style.STROKE);
this.squigglyPaint.setColor(resources.getColor(R.color.leak_canary_leak));
float dimensionPixelSize = resources.getDimensionPixelSize(R.dimen.leak_canary_squiggly_span_stroke_width);
this.squigglyPaint.setStrokeWidth(dimensionPixelSize);
this.halfStrokeWidth = dimensionPixelSize / 2.0f;
this.amplitude = resources.getDimensionPixelSize(R.dimen.leak_canary_squiggly_span_amplitude);
this.periodDegrees = resources.getDimensionPixelSize(R.dimen.leak_canary_squiggly_span_period_degrees);
this.path = new Path();
this.halfWaveHeight = ((this.amplitude * 2.0f) + dimensionPixelSize) / 2.0f;
this.referenceColor = resources.getColor(R.color.leak_canary_reference);
}
public static void replaceUnderlineSpans(SpannableStringBuilder spannableStringBuilder, Resources resources) {
for (UnderlineSpan underlineSpan : (UnderlineSpan[]) spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), UnderlineSpan.class)) {
int spanStart = spannableStringBuilder.getSpanStart(underlineSpan);
int spanEnd = spannableStringBuilder.getSpanEnd(underlineSpan);
spannableStringBuilder.removeSpan(underlineSpan);
spannableStringBuilder.setSpan(new SquigglySpan(resources), spanStart, spanEnd, 0);
}
}
private static void squigglyHorizontalPath(Path path, float f, float f2, float f3, float f4, float f5) {
path.reset();
path.moveTo(f, f3);
float f6 = (float) (6.283185307179586d / f5);
for (float f7 = 0.0f; f7 <= f2 - f; f7 += 1.0f) {
path.lineTo(f + f7, (float) ((f4 * Math.sin((f6 * f7) + 40.0f)) + f3));
}
}
@Override // android.text.style.ReplacementSpan
public void draw(Canvas canvas, CharSequence charSequence, int i, int i2, float f, int i3, int i4, int i5, Paint paint) {
Path path = this.path;
float f2 = this.halfStrokeWidth;
squigglyHorizontalPath(path, f + f2, (this.width + f) - f2, i5 - this.halfWaveHeight, this.amplitude, this.periodDegrees);
canvas.drawPath(this.path, this.squigglyPaint);
paint.setColor(this.referenceColor);
canvas.drawText(charSequence, i, i2, f, i4, paint);
}
@Override // android.text.style.ReplacementSpan
public int getSize(Paint paint, CharSequence charSequence, int i, int i2, Paint.FontMetricsInt fontMetricsInt) {
this.width = (int) paint.measureText(charSequence, i, i2);
return this.width;
}
}