Commit 72fae848 authored by Tibor Goldschwendt's avatar Tibor Goldschwendt Committed by Commit Bot

[bundles] Add fully installed and emulated modules to crash reports

Bug: 873719
Change-Id: I3b9a44f5fa1b9ec47acb429e9062fcd2fbbb8f27
Reviewed-on: https://chromium-review.googlesource.com/c/1347038Reviewed-by: default avatarCait Phillips <caitkp@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Commit-Queue: Tibor Goldschwendt <tiborg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611855}
parent de7d4efe
......@@ -12,7 +12,7 @@ include_rules = [
"+components/language",
"+components/location/android/java",
"+components/minidump_uploader",
"+components/module_installer/android/java/src/org/chromium/components/module_installer",
"+components/module_installer",
"+components/navigation_interception",
"+components/offline_items_collection/core/android/java",
"+components/omnibox/browser/android/java",
......
......@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.metrics.UmaUtils;
import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
import org.chromium.chrome.browser.vr.OnExitVrRequestListener;
import org.chromium.chrome.browser.vr.VrModuleProvider;
import org.chromium.components.module_installer.ModuleInstaller;
/**
* Basic application functionality that should be shared among all browser applications that use
......@@ -102,6 +103,10 @@ public class ChromeApplication extends Application {
TraceEvent.end("ChromeApplication.attachBaseContext");
}
// Write installed modules to crash keys. This needs to be done as early as possible so that
// these values are set before any crashes are reported.
ModuleInstaller.updateCrashKeys();
MemoryPressureMonitor.INSTANCE.registerComponentCallbacks();
if (!ContextUtils.isIsolatedProcess()) {
......
......@@ -19,6 +19,8 @@ JavaCrashKey& GetCrashKey(int index) {
{"loaded_dynamic_module", JavaCrashKey::Tag::kArray},
{"active_dynamic_module", JavaCrashKey::Tag::kArray},
{"application_status", JavaCrashKey::Tag::kArray},
{"installed_modules", JavaCrashKey::Tag::kArray},
{"emulated_modules", JavaCrashKey::Tag::kArray},
};
static_assert(
base::size(crash_keys) == static_cast<size_t>(CrashKeyIndex::NUM_KEYS),
......
......@@ -14,6 +14,8 @@ enum class CrashKeyIndex {
LOADED_DYNAMIC_MODULE = 0,
ACTIVE_DYNAMIC_MODULE,
APPLICATION_STATUS,
INSTALLED_MODULES,
EMULATED_MODULES,
NUM_KEYS
};
......
......@@ -22,8 +22,8 @@ import java.util.concurrent.atomic.AtomicReferenceArray;
* The crash keys will only be included in browser process crash reports.
*/
public class CrashKeys {
private static final String[] KEYS =
new String[] {"loaded_dynamic_module", "active_dynamic_module", "application_status"};
private static final String[] KEYS = new String[] {"loaded_dynamic_module",
"active_dynamic_module", "application_status", "installed_modules", "emulated_modules"};
private final AtomicReferenceArray<String> mValues = new AtomicReferenceArray<>(KEYS.length);
......
......@@ -37,6 +37,7 @@ android_library("module_installer_impl_java") {
deps = [
":module_installer_java",
"//base:base_java",
"//components/crash/android:java",
"//third_party/google_android_play_core:com_google_android_play_core_java",
]
}
include_rules = [
"+components/crash/android",
]
......@@ -4,17 +4,30 @@
package org.chromium.components.module_installer;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.text.TextUtils;
import com.google.android.play.core.splitcompat.SplitCompat;
import com.google.android.play.core.splitinstall.SplitInstallManagerFactory;
import org.chromium.base.BuildInfo;
import org.chromium.base.CommandLine;
import org.chromium.base.ContextUtils;
import org.chromium.base.StrictModeContext;
import org.chromium.base.ThreadUtils;
import org.chromium.components.crash.CrashKeyIndex;
import org.chromium.components.crash.CrashKeys;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/** Installs dynamic feature modules (DFMs). */
public class ModuleInstaller {
......@@ -30,6 +43,40 @@ public class ModuleInstaller {
try (StrictModeContext unused = StrictModeContext.allowDiskWrites()) {
SplitCompat.install(ContextUtils.getApplicationContext());
}
// SplitCompat.install may add emulated modules. Thus, update crash keys.
updateCrashKeys();
}
/** Writes fully installed and emulated modules to crash keys. */
public static void updateCrashKeys() {
Context context = ContextUtils.getApplicationContext();
// Get modules that are fully installed as split APKs (excluding base which is always
// intalled). Tree set to have ordered and, thus, deterministic results.
Set<String> fullyInstalledModules = new TreeSet<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Split APKs are only supported on Android L+.
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(
BuildInfo.getInstance().packageName, 0);
if (packageInfo.splitNames != null) {
fullyInstalledModules.addAll(Arrays.asList(packageInfo.splitNames));
}
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
}
// Create temporary split install manager to retrieve both fully installed and emulated
// modules. Then remove fully installed ones to get emulated ones only.
Set<String> emulatedModules =
new TreeSet<>(SplitInstallManagerFactory.create(context).getInstalledModules());
emulatedModules.removeAll(fullyInstalledModules);
CrashKeys.getInstance().set(
CrashKeyIndex.INSTALLED_MODULES, encodeCrashKeyValue(fullyInstalledModules));
CrashKeys.getInstance().set(
CrashKeyIndex.EMULATED_MODULES, encodeCrashKeyValue(emulatedModules));
}
/**
......@@ -73,6 +120,8 @@ public class ModuleInstaller {
sBackend.close();
sBackend = null;
}
updateCrashKeys();
}
private static ModuleInstallerBackend getBackend() {
......@@ -85,5 +134,12 @@ public class ModuleInstaller {
return sBackend;
}
private static String encodeCrashKeyValue(Set<String> moduleNames) {
if (moduleNames.isEmpty()) return "<none>";
// Values with dots are interpreted as URLs. Some module names have dots in them. Make sure
// they don't get sanitized.
return TextUtils.join(",", moduleNames).replace('.', '$');
}
private ModuleInstaller() {}
}
......@@ -7,6 +7,8 @@ package org.chromium.components.module_installer;
/** Dummy fallback of ModuleInstaller for APK builds. */
public class ModuleInstaller {
public static void init() {}
public static void updateCrashKeys(){};
/** Should never be called for APK builds. */
public static void install(
String moduleName, OnModuleInstallFinishedListener onFinishedListener) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment