[WW logging] Log rankings for app launches

Bug: 158219113
Change-Id: Ib6db4e73e48ff27ca9d3a5348eea42e1f534dba1
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
index f881610..0113570 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java
@@ -18,12 +18,12 @@
 
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_RANKED;
 
 import android.app.prediction.AppPredictor;
 import android.app.prediction.AppTarget;
 import android.content.ComponentName;
 import android.content.Context;
-import android.os.Process;
 
 import androidx.annotation.NonNull;
 
@@ -36,9 +36,10 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.AllAppsContainerView;
 import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
-import com.android.launcher3.hybridhotseat.HotseatFileLog;
 import com.android.launcher3.hybridhotseat.HotseatPredictionController;
 import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.shortcuts.ShortcutKey;
@@ -50,6 +51,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.OptionalInt;
 import java.util.stream.IntStream;
 
 /**
@@ -304,6 +306,41 @@
     }
 
     /**
+     * Logs ranking info for launched app within all apps prediction.
+     * Only applicable when {@link ItemInfo#itemType} is one of the followings:
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_SHORTCUT},
+     * {@link LauncherSettings.Favorites#ITEM_TYPE_DEEP_SHORTCUT}
+     */
+    public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
+        if (itemInfo.getTargetComponent() == null || itemInfo.user == null
+                || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
+                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
+                && itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)) {
+            return;
+        }
+
+        Launcher launcher = Launcher.getLauncher(mAppsView.getContext());
+        final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+        final List<ComponentKeyMapper> predictedApps = getCurrentState().apps;
+        OptionalInt rank = IntStream.range(0, predictedApps.size())
+                .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+                .findFirst();
+        if (!rank.isPresent()) {
+            return;
+        }
+
+        LauncherAtom.ItemInfo.Builder atomBuilder = LauncherAtom.ItemInfo.newBuilder();
+        atomBuilder.setRank(rank.getAsInt());
+        atomBuilder.setContainerInfo(
+                LauncherAtom.ContainerInfo.newBuilder().setPredictionContainer(
+                        LauncherAtom.PredictionContainer.newBuilder().build()).build());
+        launcher.getStatsLogManager().log(LAUNCHER_ALL_APPS_RANKED, instanceId,
+                atomBuilder.build());
+    }
+
+
+    /**
      * Fill in predicted_rank field based on app prediction.
      * Only applicable when {@link ItemInfo#itemType} is one of the followings:
      * {@link LauncherSettings.Favorites#ITEM_TYPE_APPLICATION},
@@ -313,17 +350,6 @@
     public static void fillInPredictedRank(
             @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
 
-        HotseatFileLog hotseatFileLog = HotseatFileLog.INSTANCE.getNoCreate();
-
-        if (hotseatFileLog != null && itemInfo != null && Utilities.IS_DEBUG_DEVICE) {
-            final String pkg = itemInfo.getTargetComponent() != null
-                    ? itemInfo.getTargetComponent().getPackageName() : "unknown";
-            hotseatFileLog.log("UserEvent",
-                    "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
-                            && !Process.myUserHandle().equals(itemInfo.user))
-                            + ",launchLocation:" + itemInfo.container);
-        }
-
         final PredictionUiStateManager manager = PredictionUiStateManager.INSTANCE.getNoCreate();
         if (manager == null || itemInfo.getTargetComponent() == null || itemInfo.user == null
                 || (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 6ca07bb..30a34e4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.hybridhotseat.HotseatEduController.SETTINGS_ACTION;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -29,6 +30,7 @@
 import android.app.prediction.AppTargetEvent;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.os.Process;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -52,6 +54,8 @@
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -185,7 +189,6 @@
 
     /**
      * Returns if hotseat client has predictions
-     * @return
      */
     public boolean hasPredictions() {
         return !mComponentKeyMappers.isEmpty();
@@ -358,6 +361,7 @@
         updateDependencies();
         bindItems(items, false, null);
     }
+
     private void setPredictedApps(List<AppTarget> appTargets) {
         mComponentKeyMappers.clear();
         if (appTargets.isEmpty()) {
@@ -635,6 +639,48 @@
         mHotseat.fillInLogContainerData(childInfo, child, parents);
     }
 
+    /**
+     * Logs rank info based on current list of predicted items
+     */
+    public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
+        if (Utilities.IS_DEBUG_DEVICE) {
+            final String pkg = itemInfo.getTargetComponent() != null
+                    ? itemInfo.getTargetComponent().getPackageName() : "unknown";
+            HotseatFileLog.INSTANCE.get(mLauncher).log("UserEvent",
+                    "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
+                            && !Process.myUserHandle().equals(itemInfo.user))
+                            + ",launchLocation:" + itemInfo.container);
+        }
+
+        final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
+
+        final List<ComponentKeyMapper> predictedApps = new ArrayList<>(mComponentKeyMappers);
+        OptionalInt rank = IntStream.range(0, predictedApps.size())
+                .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
+                .findFirst();
+        if (!rank.isPresent()) {
+            return;
+        }
+        LauncherAtom.PredictedHotseatContainer.Builder containerBuilder =
+                LauncherAtom.PredictedHotseatContainer.newBuilder();
+        LauncherAtom.ItemInfo.Builder atomBuilder = LauncherAtom.ItemInfo.newBuilder();
+        int cardinality = 0;
+        for (PredictedAppIcon icon : getPredictedIcons()) {
+            ItemInfo info = (ItemInfo) icon.getTag();
+            cardinality |= 1 << info.screenId;
+        }
+        containerBuilder.setCardinality(cardinality);
+        atomBuilder.setRank(rank.getAsInt());
+        if (itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+            containerBuilder.setIndex(rank.getAsInt());
+        }
+        atomBuilder.setContainerInfo(
+                LauncherAtom.ContainerInfo.newBuilder().setPredictedHotseatContainer(
+                        containerBuilder).build());
+        mLauncher.getStatsLogManager().log(LAUNCHER_HOTSEAT_RANKED, instanceId,
+                atomBuilder.build());
+    }
+
     private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
 
         private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 3b45ec9..4d307e2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -42,10 +42,12 @@
 import com.android.launcher3.Workspace;
 import com.android.launcher3.allapps.DiscoveryBounce;
 import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.appprediction.PredictionUiStateManager;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.hybridhotseat.HotseatEduController;
 import com.android.launcher3.hybridhotseat.HotseatPredictionController;
+import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -113,6 +115,15 @@
     }
 
     @Override
+    protected void logAppLaunch(ItemInfo info, InstanceId instanceId) {
+        super.logAppLaunch(info, instanceId);
+        if (mHotseatPredictionController != null) {
+            mHotseatPredictionController.logLaunchedAppRankingInfo(info, instanceId);
+        }
+        PredictionUiStateManager.INSTANCE.get(this).logLaunchedAppRankingInfo(info, instanceId);
+    }
+
+    @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         onStateOrResumeChanging(false /* inTransition */);
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index ebb44e2..e820b3f 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -78,7 +78,7 @@
      */
     @Override
     public void log(EventEnum event) {
-        log(event, DEFAULT_INSTANCE_ID, null);
+        log(event, DEFAULT_INSTANCE_ID, (ItemInfo) null);
     }
 
     /**
@@ -86,7 +86,7 @@
      */
     @Override
     public void log(EventEnum event, InstanceId instanceId) {
-        log(event, instanceId, null);
+        log(event, instanceId, (ItemInfo) null);
     }
 
     /**
@@ -101,6 +101,25 @@
      * Logs an event.
      *
      * @param event an enum implementing EventEnum interface.
+     * @param atomInfo item typically containing app or task launch related information.
+     */
+    public void log(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo) {
+        LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
+                new BaseModelUpdateTask() {
+                    @Override
+                    public void execute(LauncherAppState app, BgDataModel dataModel,
+                            AllAppsList apps) {
+                        write(event, instanceId, atomInfo, null,
+                                LAUNCHER_UICHANGED__DST_STATE__HOME,
+                                LAUNCHER_UICHANGED__DST_STATE__BACKGROUND);
+                    }
+                });
+    }
+
+    /**
+     * Logs an event.
+     *
+     * @param event an enum implementing EventEnum interface.
      * @param atomItemInfo item typically containing app or task launch related information.
      */
     @Override
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 88dbfd6..61ecdd7 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -43,6 +43,8 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.logging.InstanceId;
+import com.android.launcher3.logging.InstanceIdSequence;
 import com.android.launcher3.model.AppLaunchTracker;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -188,7 +190,8 @@
             }
             getUserEventDispatcher().logAppLaunch(v, intent, user);
             if (item != null) {
-                getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, item);
+                InstanceId instanceId = new InstanceIdSequence().newInstanceId();
+                logAppLaunch(item, instanceId);
             }
             return true;
         } catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
@@ -198,6 +201,10 @@
         return false;
     }
 
+    protected void logAppLaunch(ItemInfo info, InstanceId instanceId) {
+        getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, instanceId, info);
+    }
+
     private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info,
             @Nullable String sourceContainer) {
         try {
diff --git a/src/com/android/launcher3/logging/InstanceIdSequence.java b/src/com/android/launcher3/logging/InstanceIdSequence.java
index a4b7953..ee6a5a4 100644
--- a/src/com/android/launcher3/logging/InstanceIdSequence.java
+++ b/src/com/android/launcher3/logging/InstanceIdSequence.java
@@ -45,6 +45,13 @@
     }
 
     /**
+     * Constructs a sequence with identifiers [1, InstanceId.INSTANCE_ID_MAX].
+     */
+    public InstanceIdSequence() {
+        this(InstanceId.INSTANCE_ID_MAX);
+    }
+
+    /**
      * Gets the next instance from the sequence.  Safe for concurrent use.
      * @return new InstanceId
      */
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index fee91b0..c84b9fe 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -143,7 +143,13 @@
         LAUNCHER_HOTSEAT_EDU_DENY(481),
 
         @UiEvent(doc = "Hotseat education tip shown")
-        LAUNCHER_HOTSEAT_EDU_ONLY_TIP(482);
+        LAUNCHER_HOTSEAT_EDU_ONLY_TIP(482),
+
+        @UiEvent(doc = "App launch ranking logged for all apps predictions")
+        LAUNCHER_ALL_APPS_RANKED(552),
+
+        @UiEvent(doc = "App launch ranking logged for hotseat predictions)")
+        LAUNCHER_HOTSEAT_RANKED(553);
         // ADD MORE
         private final int mId;
 
@@ -218,6 +224,15 @@
     }
 
     /**
+     * Logs an event.
+     *
+     * @param event an enum implementing EventEnum interface.
+     * @param atomInfo item typically containing app or task launch related information.
+     */
+    public void log(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo) {
+    }
+
+    /**
      * Logs an event and accompanying {@link LauncherState}s.
      *
      * @param event an enum implementing EventEnum interface.