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
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 48c52d5..6dbe5fb 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -159,6 +159,12 @@
     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.
      * @hide
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 918747b..dd8c05e 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.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 @@
             }
             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 9c1992c..3432ecd 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 @@
     }
 
     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 @@
                 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 @@
      */
     public abstract static class PhaseTwoCallback {
         abstract void onPhaseTwoResolved(
-                List<InstantAppResolveInfo> instantAppResolveInfoList, int sequence);
+                List<InstantAppResolveInfo> 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 3821418..3396954 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.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 @@
 
 /** @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<InstantAppResolveInfo> 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 @@
         final PhaseTwoCallback callback = new PhaseTwoCallback() {
             @Override
             void onPhaseTwoResolved(List<InstantAppResolveInfo> 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 @@
                         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 @@
         // 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 1d1bf0d..2d33c71 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 @@
                     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;