Revert "Revert "Log the apk optimization state in the MetricsLogger""
This reverts commit 203a9ab7665787c94f7d0711a1ad172588070aa6.
Reason for revert: Fix the original issue. There was a race with the
cleanup method which was resetting the app record to null.
Test: manual, adb logcat -b events | grep sysui_multi_action
repeat steps from bugreport reporting the crash
Bug: 73102540
Change-Id: I6d9c6110a9d5dadeb9d4361592711d63563c958a
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2b02025..04ebfcd 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -940,6 +940,11 @@
// Empty if not set.
optional string launch_token = 13;
+ // The compiler filter used when when the package was optimized.
+ optional string package_optimization_compilation_filter = 14;
+
+ // The reason why the package was optimized.
+ optional string package_optimization_compilation_reason = 15;
}
message AppStartCancelChanged {
diff --git a/core/java/android/content/pm/dex/ArtManagerInternal.java b/core/java/android/content/pm/dex/ArtManagerInternal.java
new file mode 100644
index 0000000..62ab9e0
--- /dev/null
+++ b/core/java/android/content/pm/dex/ArtManagerInternal.java
@@ -0,0 +1,34 @@
+/**
+ * Copyright 2018 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.content.pm.dex;
+
+import android.content.pm.ApplicationInfo;
+
+/**
+ * Art manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class ArtManagerInternal {
+
+ /**
+ * Return optimization information about the application {@code info} when
+ * in executes using the specified {@code abi}.
+ */
+ public abstract PackageOptimizationInfo getPackageOptimizationInfo(
+ ApplicationInfo info, String abi);
+}
diff --git a/core/java/android/content/pm/dex/PackageOptimizationInfo.java b/core/java/android/content/pm/dex/PackageOptimizationInfo.java
new file mode 100644
index 0000000..b650457
--- /dev/null
+++ b/core/java/android/content/pm/dex/PackageOptimizationInfo.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2018 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.content.pm.dex;
+
+/**
+ * Encapsulates information about the optimizations performed on a package.
+ *
+ * @hide
+ */
+public class PackageOptimizationInfo {
+ private final String mCompilationFilter;
+ private final String mCompilationReason;
+
+ public PackageOptimizationInfo(String compilerFilter, String compilationReason) {
+ this.mCompilationReason = compilationReason;
+ this.mCompilationFilter = compilerFilter;
+ }
+
+ public String getCompilationReason() {
+ return mCompilationReason;
+ }
+
+ public String getCompilationFilter() {
+ return mCompilationFilter;
+ }
+
+ /**
+ * Create a default optimization info object for the case when we have no information.
+ */
+ public static PackageOptimizationInfo createWithNoInfo() {
+ return new PackageOptimizationInfo("no-info", "no-info");
+ }
+}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index c0e5960..c56002e 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5278,6 +5278,7 @@
// OS: P
FIELD_QS_MODE = 1311;
+
// OPEN: Settings->Developer Options->Default USB
// CATEGORY: SETTINGS
// OS: P
@@ -5317,6 +5318,16 @@
// OS: P
FIELD_LINKIFY_CALL_ID = 1319;
+ // FIELD: The compiler filter used when when optimizing the package.
+ // Logged together with app transition events.
+ // OS: P
+ PACKAGE_OPTIMIZATION_COMPILATION_FILTER = 1320;
+
+ // FIELD: The reason for optimizing the package.
+ // Logged together with app transition events.
+ // OS: P
+ PACKAGE_OPTIMIZATION_COMPILATION_REASON = 1321;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index db86f1a..978e344 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -23,6 +23,8 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_REASON;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PACKAGE_OPTIMIZATION_COMPILATION_FILTER;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
@@ -35,6 +37,9 @@
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromMemcg;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.dex.ArtManagerInternal;
+import android.content.pm.dex.PackageOptimizationInfo;
import android.metrics.LogMaker;
import android.os.Handler;
import android.os.Looper;
@@ -47,6 +52,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.SomeArgs;
+import com.android.server.LocalServices;
import java.util.ArrayList;
@@ -68,7 +74,8 @@
private static final long INVALID_START_TIME = -1;
private static final int MSG_CHECK_VISIBILITY = 0;
- private static final int MSG_LOG_APP_START_MEMORY_STATE_CAPTURE = 1;
+ private static final int MSG_LOG_APP_TRANSITION = 1;
+ private static final int MSG_LOG_APP_START_MEMORY_STATE_CAPTURE = 2;
// Preallocated strings we are sending to tron, so we don't have to allocate a new one every
// time we log.
@@ -93,6 +100,9 @@
private final SparseArray<WindowingModeTransitionInfo> mLastWindowingModeTransitionInfo =
new SparseArray<>();
private final H mHandler;
+
+ private ArtManagerInternal mArtManagerInternal;
+
private final class H extends Handler {
public H(Looper looper) {
@@ -106,12 +116,16 @@
final SomeArgs args = (SomeArgs) msg.obj;
checkVisibility((TaskRecord) args.arg1, (ActivityRecord) args.arg2);
break;
+ case MSG_LOG_APP_TRANSITION:
+ logAppTransition(msg.arg1, msg.arg2,
+ (WindowingModeTransitionInfoSnapshot) msg.obj);
+ break;
case MSG_LOG_APP_START_MEMORY_STATE_CAPTURE:
logAppStartMemoryStateCapture((WindowingModeTransitionInfo) msg.obj);
break;
}
}
- };
+ }
private final class WindowingModeTransitionInfo {
private ActivityRecord launchedActivity;
@@ -125,6 +139,36 @@
private boolean loggedStartingWindowDrawn;
}
+ private final class WindowingModeTransitionInfoSnapshot {
+ final private ApplicationInfo applicationInfo;
+ final private String packageName;
+ final private String launchedActivityName;
+ final private String launchedActivityLaunchedFromPackage;
+ final private String launchedActivityLaunchToken;
+ final private String launchedActivityAppRecordRequiredAbi;
+ final private int reason;
+ final private int startingWindowDelayMs;
+ final private int bindApplicationDelayMs;
+ final private int windowsDrawnDelayMs;
+ final private int type;
+
+ private WindowingModeTransitionInfoSnapshot(WindowingModeTransitionInfo info) {
+ applicationInfo = info.launchedActivity.appInfo;
+ packageName = info.launchedActivity.packageName;
+ launchedActivityName = info.launchedActivity.info.name;
+ launchedActivityLaunchedFromPackage = info.launchedActivity.launchedFromPackage;
+ launchedActivityLaunchToken = info.launchedActivity.info.launchToken;
+ launchedActivityAppRecordRequiredAbi = info.launchedActivity.app == null
+ ? null
+ : info.launchedActivity.app.requiredAbi;
+ reason = info.reason;
+ startingWindowDelayMs = info.startingWindowDelayMs;
+ bindApplicationDelayMs = info.bindApplicationDelayMs;
+ windowsDrawnDelayMs = info.windowsDrawnDelayMs;
+ type = getTransitionType(info);
+ }
+ }
+
ActivityMetricsLogger(ActivityStackSupervisor supervisor, Context context, Looper looper) {
mLastLogTimeSecs = SystemClock.elapsedRealtime() / 1000;
mSupervisor = supervisor;
@@ -456,54 +500,80 @@
if (type == -1) {
return;
}
- final LogMaker builder = new LogMaker(APP_TRANSITION);
- builder.setPackageName(info.launchedActivity.packageName);
- builder.setType(type);
- builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
- final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp();
- if (info.launchedActivity.launchedFromPackage != null) {
- builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
- info.launchedActivity.launchedFromPackage);
- }
- String launchToken = info.launchedActivity.info.launchToken;
- if (launchToken != null) {
- builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, launchToken);
- info.launchedActivity.info.launchToken = null;
- }
- builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
- builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
- mCurrentTransitionDeviceUptime);
- builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs);
- builder.setSubtype(info.reason);
- if (info.startingWindowDelayMs != -1) {
- builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
- info.startingWindowDelayMs);
- }
- if (info.bindApplicationDelayMs != -1) {
- builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
- info.bindApplicationDelayMs);
- }
- builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
- mMetricsLogger.write(builder);
- StatsLog.write(
- StatsLog.APP_START_CHANGED,
- info.launchedActivity.appInfo.uid,
- info.launchedActivity.packageName,
- convertAppStartTransitionType(type),
- info.launchedActivity.info.name,
- info.launchedActivity.launchedFromPackage,
- isInstantApp,
- mCurrentTransitionDeviceUptime * 1000,
- info.reason,
- mCurrentTransitionDelayMs,
- info.startingWindowDelayMs,
- info.bindApplicationDelayMs,
- info.windowsDrawnDelayMs,
- launchToken);
+
+ // Take a snapshot of the transition info before sending it to the handler for logging.
+ // This will avoid any races with other operations that modify the ActivityRecord.
+ final WindowingModeTransitionInfoSnapshot infoSnapshot =
+ new WindowingModeTransitionInfoSnapshot(info);
+ mHandler.obtainMessage(MSG_LOG_APP_TRANSITION, mCurrentTransitionDeviceUptime,
+ mCurrentTransitionDelayMs, infoSnapshot).sendToTarget();
+
+ info.launchedActivity.info.launchToken = null;
mHandler.obtainMessage(MSG_LOG_APP_START_MEMORY_STATE_CAPTURE, info).sendToTarget();
}
}
+ // This gets called on the handler without holding the activity manager lock.
+ private void logAppTransition(int currentTransitionDeviceUptime, int currentTransitionDelayMs,
+ WindowingModeTransitionInfoSnapshot info) {
+ final LogMaker builder = new LogMaker(APP_TRANSITION);
+ builder.setPackageName(info.packageName);
+ builder.setType(info.type);
+ builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivityName);
+ final boolean isInstantApp = info.applicationInfo.isInstantApp();
+ if (info.launchedActivityLaunchedFromPackage != null) {
+ builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
+ info.launchedActivityLaunchedFromPackage);
+ }
+ String launchToken = info.launchedActivityLaunchToken;
+ if (launchToken != null) {
+ builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, launchToken);
+ }
+ builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, isInstantApp ? 1 : 0);
+ builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS,
+ currentTransitionDeviceUptime);
+ builder.addTaggedData(APP_TRANSITION_DELAY_MS, currentTransitionDelayMs);
+ builder.setSubtype(info.reason);
+ if (info.startingWindowDelayMs != -1) {
+ builder.addTaggedData(APP_TRANSITION_STARTING_WINDOW_DELAY_MS,
+ info.startingWindowDelayMs);
+ }
+ if (info.bindApplicationDelayMs != -1) {
+ builder.addTaggedData(APP_TRANSITION_BIND_APPLICATION_DELAY_MS,
+ info.bindApplicationDelayMs);
+ }
+ builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
+ final ArtManagerInternal artManagerInternal = getArtManagerInternal();
+ final PackageOptimizationInfo packageOptimizationInfo =
+ (artManagerInternal == null) || (info.launchedActivityAppRecordRequiredAbi == null)
+ ? PackageOptimizationInfo.createWithNoInfo()
+ : artManagerInternal.getPackageOptimizationInfo(
+ info.applicationInfo,
+ info.launchedActivityAppRecordRequiredAbi);
+ builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_REASON,
+ packageOptimizationInfo.getCompilationReason());
+ builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER,
+ packageOptimizationInfo.getCompilationFilter());
+ mMetricsLogger.write(builder);
+ StatsLog.write(
+ StatsLog.APP_START_CHANGED,
+ info.applicationInfo.uid,
+ info.packageName,
+ convertAppStartTransitionType(info.type),
+ info.launchedActivityName,
+ info.launchedActivityLaunchedFromPackage,
+ isInstantApp,
+ currentTransitionDeviceUptime * 1000,
+ info.reason,
+ currentTransitionDelayMs,
+ info.startingWindowDelayMs,
+ info.bindApplicationDelayMs,
+ info.windowsDrawnDelayMs,
+ launchToken,
+ packageOptimizationInfo.getCompilationReason(),
+ packageOptimizationInfo.getCompilationFilter());
+ }
+
private int convertAppStartTransitionType(int tronType) {
if (tronType == TYPE_TRANSITION_COLD_LAUNCH) {
return StatsLog.APP_START_CHANGED__TYPE__COLD;
@@ -592,4 +662,14 @@
launchedActivity.appInfo.uid)
: null;
}
+
+ private ArtManagerInternal getArtManagerInternal() {
+ if (mArtManagerInternal == null) {
+ // Note that this may be null.
+ // ArtManagerInternal is registered during PackageManagerService
+ // initialization which happens after ActivityManagerService.
+ mArtManagerInternal = LocalServices.getService(ArtManagerInternal.class);
+ }
+ return mArtManagerInternal;
+ }
}
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index e290272..2ece2b2 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -19,18 +19,20 @@
import android.Manifest;
import android.annotation.UserIdInt;
import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.dex.ArtManager;
import android.content.pm.dex.ArtManager.ProfileType;
+import android.content.pm.dex.ArtManagerInternal;
import android.content.pm.dex.DexMetadataHelper;
+import android.content.pm.dex.PackageOptimizationInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.content.pm.IPackageManager;
import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -42,8 +44,13 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
import com.android.server.pm.Installer;
import com.android.server.pm.Installer.InstallerException;
+
+import dalvik.system.DexFile;
+
+import dalvik.system.VMRuntime;
import java.io.File;
import java.io.FileNotFoundException;
import libcore.io.IoUtils;
@@ -86,6 +93,8 @@
mInstaller = installer;
mInstallLock = installLock;
mHandler = new Handler(BackgroundThread.getHandler().getLooper());
+
+ LocalServices.addService(ArtManagerInternal.class, new ArtManagerInternalImpl());
}
@Override
@@ -397,4 +406,30 @@
}
return result;
}
+
+ private class ArtManagerInternalImpl extends ArtManagerInternal {
+ @Override
+ public PackageOptimizationInfo getPackageOptimizationInfo(
+ ApplicationInfo info, String abi) {
+ String compilationReason;
+ String compilationFilter;
+ try {
+ String isa = VMRuntime.getInstructionSet(abi);
+ String[] stats = DexFile.getDexFileOptimizationStatus(info.getBaseCodePath(), isa);
+ compilationFilter = stats[0];
+ compilationReason = stats[1];
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "Could not get optimizations status for " + info.getBaseCodePath(), e);
+ compilationFilter = "error";
+ compilationReason = "error";
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Requested optimization status for " + info.getBaseCodePath()
+ + " due to an invalid abi " + abi, e);
+ compilationFilter = "error";
+ compilationReason = "error";
+ }
+
+ return new PackageOptimizationInfo(compilationFilter, compilationReason);
+ }
+ }
}