From 50d946c13a5a47c6617530425479b0ad4f381700 Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Fri, 17 Mar 2017 13:55:38 -0700 Subject: [PATCH] Add TRON logs Add logs for instant app resolution [both phase 1 & 2] as well as new logs for all activity starts. Change-Id: I0d25daa383854eacd3bc406ce1360d819a8ec4ba Fixes: 35442251 Fixes: 35441725 Test: Manual; install/run instant app and inspect the event logs for appropriate tags --- .../java/android/content/pm/ActivityInfo.java | 6 ++ .../server/am/ActivityMetricsLogger.java | 15 ++++- .../pm/EphemeralResolverConnection.java | 11 ++-- .../android/server/pm/InstantAppResolver.java | 66 +++++++++++++++---- .../server/pm/PackageManagerService.java | 2 + 5 files changed, 83 insertions(+), 17 deletions(-) diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 48c52d5fc4e89..6dbe5fb2468b4 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -158,6 +158,12 @@ public class ActivityInfo extends ComponentInfo */ public String targetActivity; + /** + * Token used to string together multiple events within a single launch action. + * @hide + */ + public String launchToken; + /** * Activity can not be resized and always occupies the fullscreen area with all windows fully * visible. diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 918747b370767..dd8c05ea9b87b 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -11,10 +11,13 @@ import static android.app.ActivityManager.StackId.PINNED_STACK_ID; import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_ACTIVITY_NAME; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_CALLING_PACKAGE_NAME; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS; 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_INSTANT_APP_LAUNCH_TOKEN; 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_WARM_LAUNCH; @@ -309,8 +312,18 @@ class ActivityMetricsLogger { } final LogMaker builder = new LogMaker(APP_TRANSITION); builder.setPackageName(info.launchedActivity.packageName); - builder.addTaggedData(APP_TRANSITION_ACTIVITY_NAME, info.launchedActivity.info.name); builder.setType(type); + builder.addTaggedData(APP_TRANSITION_ACTIVITY_NAME, info.launchedActivity.info.name); + if (info.launchedActivity.launchedFromPackage != null) { + builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME, + info.launchedActivity.launchedFromPackage); + } + if (info.launchedActivity.info.launchToken != null) { + builder.addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, + info.launchedActivity.info.launchToken); + } + builder.addTaggedData(APP_TRANSITION_IS_EPHEMERAL, + info.launchedActivity.info.applicationInfo.isInstantApp() ? 1 : 0); builder.addTaggedData(APP_TRANSITION_DEVICE_UPTIME_SECONDS, mCurrentTransitionDeviceUptime); builder.addTaggedData(APP_TRANSITION_DELAY_MS, mCurrentTransitionDelayMs); diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java index 9c1992cf7083f..3432ecd19efef 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java +++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java @@ -84,7 +84,7 @@ final class EphemeralResolverConnection { } public final void getInstantAppIntentFilterList(int hashPrefix[], String hostName, - PhaseTwoCallback callback, Handler callbackHandler, final int sequence) { + PhaseTwoCallback callback, Handler callbackHandler, final long startTime) { final IRemoteCallback remoteCallback = new IRemoteCallback.Stub() { @Override public void sendResult(Bundle data) throws RemoteException { @@ -94,14 +94,15 @@ final class EphemeralResolverConnection { callbackHandler.post(new Runnable() { @Override public void run() { - callback.onPhaseTwoResolved(resolveList, sequence); + callback.onPhaseTwoResolved(resolveList, startTime); } }); } }; try { - getRemoteInstanceLazy() - .getInstantAppIntentFilterList(hashPrefix, sequence, hostName, remoteCallback); + // TODO deprecate sequence; it's never used + getRemoteInstanceLazy().getInstantAppIntentFilterList( + hashPrefix, 0 /*sequence*/, hostName, remoteCallback); } catch (RemoteException re) { } catch (TimeoutException te) { } @@ -174,7 +175,7 @@ final class EphemeralResolverConnection { */ public abstract static class PhaseTwoCallback { abstract void onPhaseTwoResolved( - List instantAppResolveInfoList, int sequence); + List instantAppResolveInfoList, long startTime); } private final class MyServiceConnection implements ServiceConnection { diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java index 38214188a1a59..3396954e6ddc0 100644 --- a/services/core/java/com/android/server/pm/InstantAppResolver.java +++ b/services/core/java/com/android/server/pm/InstantAppResolver.java @@ -16,6 +16,12 @@ package com.android.server.pm; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_DELAY_MS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_RESOLUTION_STATUS; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; @@ -32,12 +38,16 @@ import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.InstantAppIntentFilter; import android.content.pm.InstantAppResolveInfo; import android.content.pm.InstantAppResolveInfo.InstantAppDigest; +import android.metrics.LogMaker; import android.os.Binder; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; import android.util.Slog; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto; import com.android.server.pm.EphemeralResolverConnection.PhaseTwoCallback; import java.util.ArrayList; @@ -47,28 +57,48 @@ import java.util.UUID; /** @hide */ public abstract class InstantAppResolver { + private static int RESOLUTION_SUCCESS = 0; + private static int RESOLUTION_FAILURE = 1; + + private static MetricsLogger sMetricsLogger; + private static MetricsLogger getLogger() { + if (sMetricsLogger == null) { + sMetricsLogger = new MetricsLogger(); + } + return sMetricsLogger; + } + public static AuxiliaryResolveInfo doInstantAppResolutionPhaseOne(Context context, EphemeralResolverConnection connection, InstantAppRequest requestObj) { + final long startTime = System.currentTimeMillis(); + final String token = UUID.randomUUID().toString(); final Intent intent = requestObj.origIntent; final InstantAppDigest digest = new InstantAppDigest(intent.getData().getHost(), 5 /*maxDigests*/); final int[] shaPrefix = digest.getDigestPrefix(); final List instantAppResolveInfoList = - connection.getInstantAppResolveInfoList(shaPrefix); + connection.getInstantAppResolveInfoList(shaPrefix); // pass token + + final AuxiliaryResolveInfo resolveInfo; if (instantAppResolveInfoList == null || instantAppResolveInfoList.size() == 0) { // No hash prefix match; there are no instant apps for this domain. - return null; + resolveInfo = null; + } else { + resolveInfo = InstantAppResolver.filterInstantAppIntent(instantAppResolveInfoList, + intent, requestObj.resolvedType, requestObj.userId, + intent.getPackage(), digest, token); } - final String token = UUID.randomUUID().toString(); - return InstantAppResolver.filterInstantAppIntent(instantAppResolveInfoList, - intent, requestObj.resolvedType, requestObj.userId, - intent.getPackage(), digest, token); + logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_ONE, startTime, token, + resolveInfo != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE); + + return resolveInfo; } public static void doInstantAppResolutionPhaseTwo(Context context, EphemeralResolverConnection connection, InstantAppRequest requestObj, ActivityInfo instantAppInstaller, Handler callbackHandler) { + final long startTime = System.currentTimeMillis(); final Intent intent = requestObj.origIntent; final String hostName = intent.getData().getHost(); final InstantAppDigest digest = new InstantAppDigest(hostName, 5 /*maxDigests*/); @@ -77,16 +107,16 @@ public abstract class InstantAppResolver { final PhaseTwoCallback callback = new PhaseTwoCallback() { @Override void onPhaseTwoResolved(List instantAppResolveInfoList, - int sequence) { + long startTime) { final String packageName; final String splitName; final int versionCode; + final String token = requestObj.responseObj.token; if (instantAppResolveInfoList != null && instantAppResolveInfoList.size() > 0) { final AuxiliaryResolveInfo instantAppIntentInfo = InstantAppResolver.filterInstantAppIntent( instantAppResolveInfoList, intent, null /*resolvedType*/, - 0 /*userId*/, intent.getPackage(), digest, - requestObj.responseObj.token); + 0 /*userId*/, intent.getPackage(), digest, token); if (instantAppIntentInfo != null && instantAppIntentInfo.resolveInfo != null) { packageName = instantAppIntentInfo.resolveInfo.getPackageName(); @@ -110,15 +140,19 @@ public abstract class InstantAppResolver { packageName, splitName, versionCode, - requestObj.responseObj.token, + token, false /*needsPhaseTwo*/); installerIntent.setComponent(new ComponentName( instantAppInstaller.packageName, instantAppInstaller.name)); + + logMetrics(ACTION_INSTANT_APP_RESOLUTION_PHASE_TWO, startTime, token, + packageName != null ? RESOLUTION_SUCCESS : RESOLUTION_FAILURE); + context.startActivity(installerIntent); } }; connection.getInstantAppIntentFilterList( - shaPrefix, hostName, callback, callbackHandler, 0 /*sequence*/); + shaPrefix, hostName, callback, callbackHandler, startTime); } /** @@ -242,4 +276,14 @@ public abstract class InstantAppResolver { // Hash or filter mis-match; no instant apps for this domain. return null; } + + private static void logMetrics(int action, long startTime, String token, int status) { + final LogMaker logMaker = new LogMaker(action) + .setType(MetricsProto.MetricsEvent.TYPE_ACTION) + .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_DELAY_MS, + new Long(System.currentTimeMillis() - startTime)) + .addTaggedData(FIELD_INSTANT_APP_LAUNCH_TOKEN, token) + .addTaggedData(FIELD_INSTANT_APP_RESOLUTION_STATUS, new Integer(status)); + getLogger().write(logMaker); + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 1d1bf0d195d9a..2d33c71fec95c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -6314,6 +6314,8 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.v(TAG, "Adding ephemeral installer to the ResolveInfo list"); } final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo); + ephemeralInstaller.activityInfo = new ActivityInfo(mInstantAppInstallerActivity); + ephemeralInstaller.activityInfo.launchToken = auxiliaryResponse.token; ephemeralInstaller.auxiliaryInfo = auxiliaryResponse; // make sure this resolver is the default ephemeralInstaller.isDefault = true;