- 28,932 files - Full Java source code - Smali files - Resources Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
603 lines
31 KiB
Java
603 lines
31 KiB
Java
package com.google.firebase.crashlytics.internal.common;
|
|
|
|
import android.app.ActivityManager;
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Environment;
|
|
import android.os.StatFs;
|
|
import android.util.Base64;
|
|
import com.google.android.gms.tasks.SuccessContinuation;
|
|
import com.google.android.gms.tasks.Task;
|
|
import com.google.android.gms.tasks.TaskCompletionSource;
|
|
import com.google.android.gms.tasks.Tasks;
|
|
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
|
|
import com.google.firebase.crashlytics.internal.Logger;
|
|
import com.google.firebase.crashlytics.internal.NativeSessionFileProvider;
|
|
import com.google.firebase.crashlytics.internal.analytics.AnalyticsEventLogger;
|
|
import com.google.firebase.crashlytics.internal.common.CrashlyticsUncaughtExceptionHandler;
|
|
import com.google.firebase.crashlytics.internal.metadata.LogFileManager;
|
|
import com.google.firebase.crashlytics.internal.metadata.UserMetadata;
|
|
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport;
|
|
import com.google.firebase.crashlytics.internal.model.StaticSessionData;
|
|
import com.google.firebase.crashlytics.internal.persistence.FileStore;
|
|
import com.google.firebase.crashlytics.internal.settings.Settings;
|
|
import com.google.firebase.crashlytics.internal.settings.SettingsProvider;
|
|
import com.ironsource.ad;
|
|
import com.mbridge.msdk.MBridgeConstans;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.File;
|
|
import java.io.FilenameFilter;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.lang.Thread;
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.SortedSet;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
|
import java.util.concurrent.TimeoutException;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
/* loaded from: classes3.dex */
|
|
public class CrashlyticsController {
|
|
public static final FilenameFilter APP_EXCEPTION_MARKER_FILTER = new FilenameFilter() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController$$ExternalSyntheticLambda0
|
|
@Override // java.io.FilenameFilter
|
|
public final boolean accept(File file, String str) {
|
|
boolean lambda$static$0;
|
|
lambda$static$0 = CrashlyticsController.lambda$static$0(file, str);
|
|
return lambda$static$0;
|
|
}
|
|
};
|
|
public final AnalyticsEventLogger analyticsEventLogger;
|
|
public final AppData appData;
|
|
public final CrashlyticsBackgroundWorker backgroundWorker;
|
|
public final Context context;
|
|
public CrashlyticsUncaughtExceptionHandler crashHandler;
|
|
public final CrashlyticsFileMarker crashMarker;
|
|
public final DataCollectionArbiter dataCollectionArbiter;
|
|
public final FileStore fileStore;
|
|
public final IdManager idManager;
|
|
public final LogFileManager logFileManager;
|
|
public final CrashlyticsNativeComponent nativeComponent;
|
|
public final SessionReportingCoordinator reportingCoordinator;
|
|
public final CrashlyticsAppQualitySessionsSubscriber sessionsSubscriber;
|
|
public final UserMetadata userMetadata;
|
|
public SettingsProvider settingsProvider = null;
|
|
public final TaskCompletionSource unsentReportsAvailable = new TaskCompletionSource();
|
|
public final TaskCompletionSource reportActionProvided = new TaskCompletionSource();
|
|
public final TaskCompletionSource unsentReportsHandled = new TaskCompletionSource();
|
|
public final AtomicBoolean checkForUnsentReportsCalled = new AtomicBoolean(false);
|
|
|
|
public static /* synthetic */ boolean lambda$static$0(File file, String str) {
|
|
return str.startsWith(".ae");
|
|
}
|
|
|
|
public CrashlyticsController(Context context, CrashlyticsBackgroundWorker crashlyticsBackgroundWorker, IdManager idManager, DataCollectionArbiter dataCollectionArbiter, FileStore fileStore, CrashlyticsFileMarker crashlyticsFileMarker, AppData appData, UserMetadata userMetadata, LogFileManager logFileManager, SessionReportingCoordinator sessionReportingCoordinator, CrashlyticsNativeComponent crashlyticsNativeComponent, AnalyticsEventLogger analyticsEventLogger, CrashlyticsAppQualitySessionsSubscriber crashlyticsAppQualitySessionsSubscriber) {
|
|
this.context = context;
|
|
this.backgroundWorker = crashlyticsBackgroundWorker;
|
|
this.idManager = idManager;
|
|
this.dataCollectionArbiter = dataCollectionArbiter;
|
|
this.fileStore = fileStore;
|
|
this.crashMarker = crashlyticsFileMarker;
|
|
this.appData = appData;
|
|
this.userMetadata = userMetadata;
|
|
this.logFileManager = logFileManager;
|
|
this.nativeComponent = crashlyticsNativeComponent;
|
|
this.analyticsEventLogger = analyticsEventLogger;
|
|
this.sessionsSubscriber = crashlyticsAppQualitySessionsSubscriber;
|
|
this.reportingCoordinator = sessionReportingCoordinator;
|
|
}
|
|
|
|
public void enableExceptionHandling(String str, Thread.UncaughtExceptionHandler uncaughtExceptionHandler, SettingsProvider settingsProvider) {
|
|
this.settingsProvider = settingsProvider;
|
|
openSession(str);
|
|
CrashlyticsUncaughtExceptionHandler crashlyticsUncaughtExceptionHandler = new CrashlyticsUncaughtExceptionHandler(new CrashlyticsUncaughtExceptionHandler.CrashListener() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.1
|
|
@Override // com.google.firebase.crashlytics.internal.common.CrashlyticsUncaughtExceptionHandler.CrashListener
|
|
public void onUncaughtException(SettingsProvider settingsProvider2, Thread thread, Throwable th) {
|
|
CrashlyticsController.this.handleUncaughtException(settingsProvider2, thread, th);
|
|
}
|
|
}, settingsProvider, uncaughtExceptionHandler, this.nativeComponent);
|
|
this.crashHandler = crashlyticsUncaughtExceptionHandler;
|
|
Thread.setDefaultUncaughtExceptionHandler(crashlyticsUncaughtExceptionHandler);
|
|
}
|
|
|
|
public void handleUncaughtException(SettingsProvider settingsProvider, Thread thread, Throwable th) {
|
|
handleUncaughtException(settingsProvider, thread, th, false);
|
|
}
|
|
|
|
public synchronized void handleUncaughtException(final SettingsProvider settingsProvider, final Thread thread, final Throwable th, final boolean z) {
|
|
Logger.getLogger().d("Handling uncaught exception \"" + th + "\" from thread " + thread.getName());
|
|
final long currentTimeMillis = System.currentTimeMillis();
|
|
try {
|
|
Utils.awaitEvenIfOnMainThread(this.backgroundWorker.submitTask(new Callable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.2
|
|
@Override // java.util.concurrent.Callable
|
|
public Task call() {
|
|
long timestampSeconds = CrashlyticsController.getTimestampSeconds(currentTimeMillis);
|
|
final String currentSessionId = CrashlyticsController.this.getCurrentSessionId();
|
|
if (currentSessionId != null) {
|
|
CrashlyticsController.this.crashMarker.create();
|
|
CrashlyticsController.this.reportingCoordinator.persistFatalEvent(th, thread, currentSessionId, timestampSeconds);
|
|
CrashlyticsController.this.doWriteAppExceptionMarker(currentTimeMillis);
|
|
CrashlyticsController.this.doCloseSessions(settingsProvider);
|
|
CrashlyticsController.this.doOpenSession(new CLSUUID(CrashlyticsController.this.idManager).toString(), Boolean.valueOf(z));
|
|
if (CrashlyticsController.this.dataCollectionArbiter.isAutomaticDataCollectionEnabled()) {
|
|
final Executor executor = CrashlyticsController.this.backgroundWorker.getExecutor();
|
|
return settingsProvider.getSettingsAsync().onSuccessTask(executor, new SuccessContinuation() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.2.1
|
|
@Override // com.google.android.gms.tasks.SuccessContinuation
|
|
public Task then(Settings settings) {
|
|
if (settings != null) {
|
|
Task[] taskArr = new Task[2];
|
|
taskArr[0] = CrashlyticsController.this.logAnalyticsAppExceptionEvents();
|
|
taskArr[1] = CrashlyticsController.this.reportingCoordinator.sendReports(executor, z ? currentSessionId : null);
|
|
return Tasks.whenAll((Task<?>[]) taskArr);
|
|
}
|
|
Logger.getLogger().w("Received null app settings, cannot send reports at crash time.");
|
|
return Tasks.forResult(null);
|
|
}
|
|
});
|
|
}
|
|
return Tasks.forResult(null);
|
|
}
|
|
Logger.getLogger().e("Tried to write a fatal exception while no session was open.");
|
|
return Tasks.forResult(null);
|
|
}
|
|
}));
|
|
} catch (TimeoutException unused) {
|
|
Logger.getLogger().e("Cannot send reports. Timed out while fetching settings.");
|
|
} catch (Exception e) {
|
|
Logger.getLogger().e("Error handling uncaught exception", e);
|
|
}
|
|
}
|
|
|
|
public final Task waitForReportAction() {
|
|
if (this.dataCollectionArbiter.isAutomaticDataCollectionEnabled()) {
|
|
Logger.getLogger().d("Automatic data collection is enabled. Allowing upload.");
|
|
this.unsentReportsAvailable.trySetResult(Boolean.FALSE);
|
|
return Tasks.forResult(Boolean.TRUE);
|
|
}
|
|
Logger.getLogger().d("Automatic data collection is disabled.");
|
|
Logger.getLogger().v("Notifying that unsent reports are available.");
|
|
this.unsentReportsAvailable.trySetResult(Boolean.TRUE);
|
|
Task onSuccessTask = this.dataCollectionArbiter.waitForAutomaticDataCollectionEnabled().onSuccessTask(new SuccessContinuation() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.3
|
|
@Override // com.google.android.gms.tasks.SuccessContinuation
|
|
public Task then(Void r1) {
|
|
return Tasks.forResult(Boolean.TRUE);
|
|
}
|
|
});
|
|
Logger.getLogger().d("Waiting for send/deleteUnsentReports to be called.");
|
|
return Utils.race(onSuccessTask, this.reportActionProvided.getTask());
|
|
}
|
|
|
|
public boolean didCrashOnPreviousExecution() {
|
|
if (!this.crashMarker.isPresent()) {
|
|
String currentSessionId = getCurrentSessionId();
|
|
return currentSessionId != null && this.nativeComponent.hasCrashDataForSession(currentSessionId);
|
|
}
|
|
Logger.getLogger().v("Found previous crash marker.");
|
|
this.crashMarker.remove();
|
|
return true;
|
|
}
|
|
|
|
public Task checkForUnsentReports() {
|
|
if (!this.checkForUnsentReportsCalled.compareAndSet(false, true)) {
|
|
Logger.getLogger().w("checkForUnsentReports should only be called once per execution.");
|
|
return Tasks.forResult(Boolean.FALSE);
|
|
}
|
|
return this.unsentReportsAvailable.getTask();
|
|
}
|
|
|
|
public Task sendUnsentReports() {
|
|
this.reportActionProvided.trySetResult(Boolean.TRUE);
|
|
return this.unsentReportsHandled.getTask();
|
|
}
|
|
|
|
public Task deleteUnsentReports() {
|
|
this.reportActionProvided.trySetResult(Boolean.FALSE);
|
|
return this.unsentReportsHandled.getTask();
|
|
}
|
|
|
|
public Task submitAllReports(Task task) {
|
|
if (!this.reportingCoordinator.hasReportsToSend()) {
|
|
Logger.getLogger().v("No crash reports are available to be sent.");
|
|
this.unsentReportsAvailable.trySetResult(Boolean.FALSE);
|
|
return Tasks.forResult(null);
|
|
}
|
|
Logger.getLogger().v("Crash reports are available to be sent.");
|
|
return waitForReportAction().onSuccessTask(new AnonymousClass4(task));
|
|
}
|
|
|
|
/* renamed from: com.google.firebase.crashlytics.internal.common.CrashlyticsController$4, reason: invalid class name */
|
|
public class AnonymousClass4 implements SuccessContinuation {
|
|
public final /* synthetic */ Task val$settingsDataTask;
|
|
|
|
public AnonymousClass4(Task task) {
|
|
this.val$settingsDataTask = task;
|
|
}
|
|
|
|
@Override // com.google.android.gms.tasks.SuccessContinuation
|
|
public Task then(final Boolean bool) {
|
|
return CrashlyticsController.this.backgroundWorker.submitTask(new Callable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.4.1
|
|
@Override // java.util.concurrent.Callable
|
|
public Task call() {
|
|
if (!bool.booleanValue()) {
|
|
Logger.getLogger().v("Deleting cached crash reports...");
|
|
CrashlyticsController.deleteFiles(CrashlyticsController.this.listAppExceptionMarkerFiles());
|
|
CrashlyticsController.this.reportingCoordinator.removeAllReports();
|
|
CrashlyticsController.this.unsentReportsHandled.trySetResult(null);
|
|
return Tasks.forResult(null);
|
|
}
|
|
Logger.getLogger().d("Sending cached crash reports...");
|
|
CrashlyticsController.this.dataCollectionArbiter.grantDataCollectionPermission(bool.booleanValue());
|
|
final Executor executor = CrashlyticsController.this.backgroundWorker.getExecutor();
|
|
return AnonymousClass4.this.val$settingsDataTask.onSuccessTask(executor, new SuccessContinuation() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.4.1.1
|
|
@Override // com.google.android.gms.tasks.SuccessContinuation
|
|
public Task then(Settings settings) {
|
|
if (settings != null) {
|
|
CrashlyticsController.this.logAnalyticsAppExceptionEvents();
|
|
CrashlyticsController.this.reportingCoordinator.sendReports(executor);
|
|
CrashlyticsController.this.unsentReportsHandled.trySetResult(null);
|
|
return Tasks.forResult(null);
|
|
}
|
|
Logger.getLogger().w("Received null app settings at app startup. Cannot send cached reports");
|
|
return Tasks.forResult(null);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public void writeToLog(final long j, final String str) {
|
|
this.backgroundWorker.submit(new Callable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.5
|
|
@Override // java.util.concurrent.Callable
|
|
public Void call() {
|
|
if (CrashlyticsController.this.isHandlingException()) {
|
|
return null;
|
|
}
|
|
CrashlyticsController.this.logFileManager.writeToLog(j, str);
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
public void writeNonFatalException(final Thread thread, final Throwable th) {
|
|
final long currentTimeMillis = System.currentTimeMillis();
|
|
this.backgroundWorker.submit(new Runnable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.6
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
if (CrashlyticsController.this.isHandlingException()) {
|
|
return;
|
|
}
|
|
long timestampSeconds = CrashlyticsController.getTimestampSeconds(currentTimeMillis);
|
|
String currentSessionId = CrashlyticsController.this.getCurrentSessionId();
|
|
if (currentSessionId != null) {
|
|
CrashlyticsController.this.reportingCoordinator.persistNonFatalEvent(th, thread, currentSessionId, timestampSeconds);
|
|
} else {
|
|
Logger.getLogger().w("Tried to write a non-fatal exception while no session was open.");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setUserId(String str) {
|
|
this.userMetadata.setUserId(str);
|
|
}
|
|
|
|
public void setCustomKey(String str, String str2) {
|
|
try {
|
|
this.userMetadata.setCustomKey(str, str2);
|
|
} catch (IllegalArgumentException e) {
|
|
Context context = this.context;
|
|
if (context != null && CommonUtils.isAppDebuggable(context)) {
|
|
throw e;
|
|
}
|
|
Logger.getLogger().e("Attempting to set custom attribute with null key, ignoring.");
|
|
}
|
|
}
|
|
|
|
public void setInternalKey(String str, String str2) {
|
|
try {
|
|
this.userMetadata.setInternalKey(str, str2);
|
|
} catch (IllegalArgumentException e) {
|
|
Context context = this.context;
|
|
if (context != null && CommonUtils.isAppDebuggable(context)) {
|
|
throw e;
|
|
}
|
|
Logger.getLogger().e("Attempting to set custom attribute with null key, ignoring.");
|
|
}
|
|
}
|
|
|
|
public void openSession(final String str) {
|
|
this.backgroundWorker.submit(new Callable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.7
|
|
@Override // java.util.concurrent.Callable
|
|
public Void call() {
|
|
CrashlyticsController.this.doOpenSession(str, Boolean.FALSE);
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
public final String getCurrentSessionId() {
|
|
SortedSet listSortedOpenSessionIds = this.reportingCoordinator.listSortedOpenSessionIds();
|
|
if (listSortedOpenSessionIds.isEmpty()) {
|
|
return null;
|
|
}
|
|
return (String) listSortedOpenSessionIds.first();
|
|
}
|
|
|
|
public boolean finalizeSessions(SettingsProvider settingsProvider) {
|
|
this.backgroundWorker.checkRunningOnThread();
|
|
if (isHandlingException()) {
|
|
Logger.getLogger().w("Skipping session finalization because a crash has already occurred.");
|
|
return false;
|
|
}
|
|
Logger.getLogger().v("Finalizing previously open sessions.");
|
|
try {
|
|
doCloseSessions(true, settingsProvider);
|
|
Logger.getLogger().v("Closed all previously open sessions.");
|
|
return true;
|
|
} catch (Exception e) {
|
|
Logger.getLogger().e("Unable to finalize previously open sessions.", e);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public final void doOpenSession(String str, Boolean bool) {
|
|
long currentTimestampSeconds = getCurrentTimestampSeconds();
|
|
Logger.getLogger().d("Opening a new session with ID " + str);
|
|
this.nativeComponent.prepareNativeSession(str, String.format(Locale.US, "Crashlytics Android SDK/%s", CrashlyticsCore.getVersion()), currentTimestampSeconds, StaticSessionData.create(createAppData(this.idManager, this.appData), createOsData(), createDeviceData(this.context)));
|
|
if (bool.booleanValue() && str != null) {
|
|
this.userMetadata.setNewSession(str);
|
|
}
|
|
this.logFileManager.setCurrentSession(str);
|
|
this.sessionsSubscriber.setSessionId(str);
|
|
this.reportingCoordinator.onBeginSession(str, currentTimestampSeconds);
|
|
}
|
|
|
|
public void doCloseSessions(SettingsProvider settingsProvider) {
|
|
doCloseSessions(false, settingsProvider);
|
|
}
|
|
|
|
/* JADX WARN: Multi-variable type inference failed */
|
|
public final void doCloseSessions(boolean z, SettingsProvider settingsProvider) {
|
|
String str;
|
|
ArrayList arrayList = new ArrayList(this.reportingCoordinator.listSortedOpenSessionIds());
|
|
if (arrayList.size() <= z) {
|
|
Logger.getLogger().v("No open sessions to be closed.");
|
|
return;
|
|
}
|
|
String str2 = (String) arrayList.get(z ? 1 : 0);
|
|
if (settingsProvider.getSettingsSync().featureFlagData.collectAnrs) {
|
|
writeApplicationExitInfoEventIfRelevant(str2);
|
|
} else {
|
|
Logger.getLogger().v("ANR feature disabled.");
|
|
}
|
|
if (this.nativeComponent.hasCrashDataForSession(str2)) {
|
|
finalizePreviousNativeSession(str2);
|
|
}
|
|
if (z != 0) {
|
|
str = (String) arrayList.get(0);
|
|
} else {
|
|
this.sessionsSubscriber.setSessionId(null);
|
|
str = null;
|
|
}
|
|
this.reportingCoordinator.finalizeSessions(getCurrentTimestampSeconds(), str);
|
|
}
|
|
|
|
public List listAppExceptionMarkerFiles() {
|
|
return this.fileStore.getCommonFiles(APP_EXCEPTION_MARKER_FILTER);
|
|
}
|
|
|
|
public void saveVersionControlInfo() {
|
|
try {
|
|
String versionControlInfo = getVersionControlInfo();
|
|
if (versionControlInfo != null) {
|
|
setInternalKey("com.crashlytics.version-control-info", versionControlInfo);
|
|
Logger.getLogger().i("Saved version control info");
|
|
}
|
|
} catch (IOException e) {
|
|
Logger.getLogger().w("Unable to save version control info", e);
|
|
}
|
|
}
|
|
|
|
public String getVersionControlInfo() {
|
|
InputStream resourceAsStream = getResourceAsStream("META-INF/version-control-info.textproto");
|
|
if (resourceAsStream == null) {
|
|
return null;
|
|
}
|
|
Logger.getLogger().d("Read version control info");
|
|
return Base64.encodeToString(readResource(resourceAsStream), 0);
|
|
}
|
|
|
|
public final InputStream getResourceAsStream(String str) {
|
|
ClassLoader classLoader = getClass().getClassLoader();
|
|
if (classLoader == null) {
|
|
Logger.getLogger().w("Couldn't get Class Loader");
|
|
return null;
|
|
}
|
|
InputStream resourceAsStream = classLoader.getResourceAsStream(str);
|
|
if (resourceAsStream != null) {
|
|
return resourceAsStream;
|
|
}
|
|
Logger.getLogger().i("No version control information found");
|
|
return null;
|
|
}
|
|
|
|
public static byte[] readResource(InputStream inputStream) {
|
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
byte[] bArr = new byte[1024];
|
|
while (true) {
|
|
int read = inputStream.read(bArr);
|
|
if (read != -1) {
|
|
byteArrayOutputStream.write(bArr, 0, read);
|
|
} else {
|
|
return byteArrayOutputStream.toByteArray();
|
|
}
|
|
}
|
|
}
|
|
|
|
public final void finalizePreviousNativeSession(String str) {
|
|
Logger.getLogger().v("Finalizing native report for session " + str);
|
|
NativeSessionFileProvider sessionFileProvider = this.nativeComponent.getSessionFileProvider(str);
|
|
File minidumpFile = sessionFileProvider.getMinidumpFile();
|
|
CrashlyticsReport.ApplicationExitInfo applicationExitInto = sessionFileProvider.getApplicationExitInto();
|
|
if (nativeCoreAbsent(str, minidumpFile, applicationExitInto)) {
|
|
Logger.getLogger().w("No native core present");
|
|
return;
|
|
}
|
|
long lastModified = minidumpFile.lastModified();
|
|
LogFileManager logFileManager = new LogFileManager(this.fileStore, str);
|
|
File nativeSessionDir = this.fileStore.getNativeSessionDir(str);
|
|
if (!nativeSessionDir.isDirectory()) {
|
|
Logger.getLogger().w("Couldn't create directory to store native session files, aborting.");
|
|
return;
|
|
}
|
|
doWriteAppExceptionMarker(lastModified);
|
|
List nativeSessionFiles = getNativeSessionFiles(sessionFileProvider, str, this.fileStore, logFileManager.getBytesForLog());
|
|
NativeSessionFileGzipper.processNativeSessions(nativeSessionDir, nativeSessionFiles);
|
|
Logger.getLogger().d("CrashlyticsController#finalizePreviousNativeSession");
|
|
this.reportingCoordinator.finalizeSessionWithNativeEvent(str, nativeSessionFiles, applicationExitInto);
|
|
logFileManager.clearLog();
|
|
}
|
|
|
|
public static boolean nativeCoreAbsent(String str, File file, CrashlyticsReport.ApplicationExitInfo applicationExitInfo) {
|
|
if (file == null || !file.exists()) {
|
|
Logger.getLogger().w("No minidump data found for session " + str);
|
|
}
|
|
if (applicationExitInfo == null) {
|
|
Logger.getLogger().i("No Tombstones data found for session " + str);
|
|
}
|
|
return (file == null || !file.exists()) && applicationExitInfo == null;
|
|
}
|
|
|
|
public static long getCurrentTimestampSeconds() {
|
|
return getTimestampSeconds(System.currentTimeMillis());
|
|
}
|
|
|
|
public static long getTimestampSeconds(long j) {
|
|
return j / 1000;
|
|
}
|
|
|
|
public final void doWriteAppExceptionMarker(long j) {
|
|
try {
|
|
if (this.fileStore.getCommonFile(".ae" + j).createNewFile()) {
|
|
} else {
|
|
throw new IOException("Create new file failed.");
|
|
}
|
|
} catch (IOException e) {
|
|
Logger.getLogger().w("Could not create app exception marker file.", e);
|
|
}
|
|
}
|
|
|
|
public static StaticSessionData.AppData createAppData(IdManager idManager, AppData appData) {
|
|
return StaticSessionData.AppData.create(idManager.getAppIdentifier(), appData.versionCode, appData.versionName, idManager.getInstallIds().getCrashlyticsInstallId(), DeliveryMechanism.determineFrom(appData.installerPackageName).getId(), appData.developmentPlatformProvider);
|
|
}
|
|
|
|
public static StaticSessionData.OsData createOsData() {
|
|
return StaticSessionData.OsData.create(Build.VERSION.RELEASE, Build.VERSION.CODENAME, CommonUtils.isRooted());
|
|
}
|
|
|
|
public static StaticSessionData.DeviceData createDeviceData(Context context) {
|
|
StatFs statFs = new StatFs(Environment.getDataDirectory().getPath());
|
|
return StaticSessionData.DeviceData.create(CommonUtils.getCpuArchitectureInt(), Build.MODEL, Runtime.getRuntime().availableProcessors(), CommonUtils.calculateTotalRamInBytes(context), statFs.getBlockCount() * statFs.getBlockSize(), CommonUtils.isEmulator(), CommonUtils.getDeviceState(), Build.MANUFACTURER, Build.PRODUCT);
|
|
}
|
|
|
|
public boolean isHandlingException() {
|
|
CrashlyticsUncaughtExceptionHandler crashlyticsUncaughtExceptionHandler = this.crashHandler;
|
|
return crashlyticsUncaughtExceptionHandler != null && crashlyticsUncaughtExceptionHandler.isHandlingException();
|
|
}
|
|
|
|
public final Task logAnalyticsAppExceptionEvents() {
|
|
ArrayList arrayList = new ArrayList();
|
|
for (File file : listAppExceptionMarkerFiles()) {
|
|
try {
|
|
arrayList.add(logAnalyticsAppExceptionEvent(Long.parseLong(file.getName().substring(3))));
|
|
} catch (NumberFormatException unused) {
|
|
Logger.getLogger().w("Could not parse app exception timestamp from file " + file.getName());
|
|
}
|
|
file.delete();
|
|
}
|
|
return Tasks.whenAll(arrayList);
|
|
}
|
|
|
|
public final Task logAnalyticsAppExceptionEvent(final long j) {
|
|
if (firebaseCrashExists()) {
|
|
Logger.getLogger().w("Skipping logging Crashlytics event to Firebase, FirebaseCrash exists");
|
|
return Tasks.forResult(null);
|
|
}
|
|
Logger.getLogger().d("Logging app exception event to Firebase Analytics");
|
|
return Tasks.call(new ScheduledThreadPoolExecutor(1), new Callable() { // from class: com.google.firebase.crashlytics.internal.common.CrashlyticsController.8
|
|
@Override // java.util.concurrent.Callable
|
|
public Void call() {
|
|
Bundle bundle = new Bundle();
|
|
bundle.putInt("fatal", 1);
|
|
bundle.putLong("timestamp", j);
|
|
CrashlyticsController.this.analyticsEventLogger.logEvent("_ae", bundle);
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void deleteFiles(List list) {
|
|
Iterator it = list.iterator();
|
|
while (it.hasNext()) {
|
|
((File) it.next()).delete();
|
|
}
|
|
}
|
|
|
|
public static boolean firebaseCrashExists() {
|
|
try {
|
|
Class.forName("com.google.firebase.crash.FirebaseCrash");
|
|
return true;
|
|
} catch (ClassNotFoundException unused) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static List getNativeSessionFiles(NativeSessionFileProvider nativeSessionFileProvider, String str, FileStore fileStore, byte[] bArr) {
|
|
File sessionFile = fileStore.getSessionFile(str, "user-data");
|
|
File sessionFile2 = fileStore.getSessionFile(str, "keys");
|
|
File sessionFile3 = fileStore.getSessionFile(str, "rollouts-state");
|
|
ArrayList arrayList = new ArrayList();
|
|
arrayList.add(new BytesBackedNativeSessionFile("logs_file", "logs", bArr));
|
|
arrayList.add(new FileBackedNativeSessionFile("crash_meta_file", "metadata", nativeSessionFileProvider.getMetadataFile()));
|
|
arrayList.add(new FileBackedNativeSessionFile("session_meta_file", "session", nativeSessionFileProvider.getSessionFile()));
|
|
arrayList.add(new FileBackedNativeSessionFile("app_meta_file", MBridgeConstans.DYNAMIC_VIEW_WX_APP, nativeSessionFileProvider.getAppFile()));
|
|
arrayList.add(new FileBackedNativeSessionFile("device_meta_file", "device", nativeSessionFileProvider.getDeviceFile()));
|
|
arrayList.add(new FileBackedNativeSessionFile("os_meta_file", ad.y, nativeSessionFileProvider.getOsFile()));
|
|
arrayList.add(nativeCoreFile(nativeSessionFileProvider));
|
|
arrayList.add(new FileBackedNativeSessionFile("user_meta_file", "user", sessionFile));
|
|
arrayList.add(new FileBackedNativeSessionFile("keys_file", "keys", sessionFile2));
|
|
arrayList.add(new FileBackedNativeSessionFile("rollouts_file", "rollouts", sessionFile3));
|
|
return arrayList;
|
|
}
|
|
|
|
public static NativeSessionFile nativeCoreFile(NativeSessionFileProvider nativeSessionFileProvider) {
|
|
File minidumpFile = nativeSessionFileProvider.getMinidumpFile();
|
|
if (minidumpFile == null || !minidumpFile.exists()) {
|
|
return new BytesBackedNativeSessionFile("minidump_file", "minidump", new byte[]{0});
|
|
}
|
|
return new FileBackedNativeSessionFile("minidump_file", "minidump", minidumpFile);
|
|
}
|
|
|
|
public final void writeApplicationExitInfoEventIfRelevant(String str) {
|
|
List historicalProcessExitReasons;
|
|
int i = Build.VERSION.SDK_INT;
|
|
if (i >= 30) {
|
|
historicalProcessExitReasons = ((ActivityManager) this.context.getSystemService("activity")).getHistoricalProcessExitReasons(null, 0, 0);
|
|
if (historicalProcessExitReasons.size() != 0) {
|
|
this.reportingCoordinator.persistRelevantAppExitInfoEvent(str, historicalProcessExitReasons, new LogFileManager(this.fileStore, str), UserMetadata.loadFromExistingSession(str, this.fileStore, this.backgroundWorker));
|
|
return;
|
|
} else {
|
|
Logger.getLogger().v("No ApplicationExitInfo available. Session: " + str);
|
|
return;
|
|
}
|
|
}
|
|
Logger.getLogger().v("ANR feature enabled, but device is API " + i);
|
|
}
|
|
}
|