Move DexLoadReporter out of LoadedApk
The DexLoadReporter was part of LoadedApk in order to lazily initialize
it when the first class loader of the app was created. However there's
no real association between the two and doing the initialization in
LoadedApk buys us nothing.
Extract the reporter in its own class and set it to BaseDexClassLoader
during bindApplication stage.
Test: boot, and check that loaded dex files are reported
Bug: 32871170
Bug: 26719109
Change-Id: I9a0e734ae4c16d5d0979aa6d0061fbc9b6e144f6
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 44cc5b4..92a02e9 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -148,6 +148,7 @@
import libcore.io.EventLogger;
import libcore.io.IoUtils;
import libcore.net.event.NetworkEventDispatcher;
+import dalvik.system.BaseDexClassLoader;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
@@ -5570,6 +5571,16 @@
}
}
+ // If we use profiles, setup the dex reporter to notify package manager
+ // of any relevant dex loads. The idle maintenance job will use the information
+ // reported to optimize the loaded dex files.
+ // Note that we only need one global reporter per app.
+ // Make sure we do this before calling onCreate so that we can capture the
+ // complete application startup.
+ if (SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false)) {
+ BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE);
+ }
+
// Install the Network Security Config Provider. This must happen before the application
// code is loaded to prevent issues with instances of TLS objects being created before
// the provider is installed.
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
new file mode 100644
index 0000000..009c448
--- /dev/null
+++ b/core/java/android/app/DexLoadReporter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.os.RemoteException;
+import android.util.Slog;
+
+import dalvik.system.BaseDexClassLoader;
+import dalvik.system.VMRuntime;
+
+import java.util.List;
+
+/**
+ * A dex load reporter which will notify package manager of any dex file loaded
+ * with {@code BaseDexClassLoader}.
+ * The goals are:
+ * 1) discover secondary dex files so that they can be optimized during the
+ * idle maintenance job.
+ * 2) determine whether or not a dex file is used by an app which does not
+ * own it (in order to select the optimal compilation method).
+ * @hide
+ */
+/*package*/ class DexLoadReporter implements BaseDexClassLoader.Reporter {
+ private static final String TAG = "DexLoadReporter";
+
+ /*package*/ static final DexLoadReporter INSTANCE = new DexLoadReporter();
+
+ private DexLoadReporter() {}
+
+ @Override
+ public void report(List<String> dexPaths) {
+ if (dexPaths.isEmpty()) {
+ return;
+ }
+ String packageName = ActivityThread.currentPackageName();
+ try {
+ ActivityThread.getPackageManager().notifyDexLoad(
+ packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
+ }
+ }
+}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 77c4c7e..8299c50 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -55,7 +55,6 @@
import com.android.internal.util.ArrayUtils;
-import dalvik.system.BaseDexClassLoader;
import dalvik.system.VMRuntime;
import java.io.File;
@@ -751,40 +750,6 @@
VMRuntime.registerAppInfo(profileFile.getPath(),
codePaths.toArray(new String[codePaths.size()]));
-
- // Setup the reporter to notify package manager of any relevant dex loads.
- // At this point the primary apk is loaded and will not be reported.
- // Anything loaded from now on will be tracked as a potential secondary
- // or foreign dex file. The goal is to enable:
- // 1) monitoring and compilation of secondary dex file
- // 2) track whether or not a dex file is used by other apps (used to
- // determined the compilation filter of apks).
- if (BaseDexClassLoader.getReporter() != DexLoadReporter.INSTANCE) {
- // Set the dex load reporter if not already set.
- // Note that during the app's life cycle different LoadedApks may be
- // created and loaded (e.g. if two different apps share the same runtime).
- BaseDexClassLoader.setReporter(DexLoadReporter.INSTANCE);
- }
- }
-
- private static class DexLoadReporter implements BaseDexClassLoader.Reporter {
- private static final DexLoadReporter INSTANCE = new DexLoadReporter();
-
- private DexLoadReporter() {}
-
- @Override
- public void report(List<String> dexPaths) {
- if (dexPaths.isEmpty()) {
- return;
- }
- String packageName = ActivityThread.currentPackageName();
- try {
- ActivityThread.getPackageManager().notifyDexLoad(
- packageName, dexPaths, VMRuntime.getRuntime().vmInstructionSet());
- } catch (RemoteException re) {
- Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
- }
- }
}
/**