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 f881610b77..01135700db 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 @@ package com.android.launcher3.appprediction; 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.LauncherState; 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 com.android.launcher3.util.MainThreadInitializedObject; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.OptionalInt; import java.util.stream.IntStream; /** @@ -303,6 +305,41 @@ public class PredictionUiStateManager implements StateListener, return mCurrentState; } + /** + * 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 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: @@ -313,17 +350,6 @@ public class PredictionUiStateManager implements StateListener, 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 6ca07bb4a0..30a34e46eb 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 @@ package com.android.launcher3.hybridhotseat; 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.AppTarget; 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.appprediction.DynamicItemCache; 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 @@ public class HotseatPredictionController implements DragController.DragListener, /** * Returns if hotseat client has predictions - * @return */ public boolean hasPredictions() { return !mComponentKeyMappers.isEmpty(); @@ -358,6 +361,7 @@ public class HotseatPredictionController implements DragController.DragListener, updateDependencies(); bindItems(items, false, null); } + private void setPredictedApps(List appTargets) { mComponentKeyMappers.clear(); if (appTargets.isEmpty()) { @@ -635,6 +639,48 @@ public class HotseatPredictionController implements DragController.DragListener, 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 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 { 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 3b45ec955d..4d307e2a5d 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.LauncherState; 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; @@ -112,6 +114,15 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { } } + @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); diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java index ebb44e2466..e820b3f6c5 100644 --- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java +++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java @@ -78,7 +78,7 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void log(EventEnum event) { - log(event, DEFAULT_INSTANCE_ID, null); + log(event, DEFAULT_INSTANCE_ID, (ItemInfo) null); } /** @@ -86,7 +86,7 @@ public class StatsLogCompatManager extends StatsLogManager { */ @Override public void log(EventEnum event, InstanceId instanceId) { - log(event, instanceId, null); + log(event, instanceId, (ItemInfo) null); } /** @@ -97,6 +97,25 @@ public class StatsLogCompatManager extends StatsLogManager { log(event, DEFAULT_INSTANCE_ID, info); } + /** + * 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. * diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 88dbfd6e37..61ecdd7da6 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -43,6 +43,8 @@ import android.widget.Toast; 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 @@ public abstract class BaseDraggingActivity extends BaseActivity } 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 @@ public abstract class BaseDraggingActivity extends BaseActivity 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 a4b795352a..ee6a5a42ba 100644 --- a/src/com/android/launcher3/logging/InstanceIdSequence.java +++ b/src/com/android/launcher3/logging/InstanceIdSequence.java @@ -44,6 +44,13 @@ public class InstanceIdSequence { mInstanceIdMax = min(max(1, instanceIdMax), InstanceId.INSTANCE_ID_MAX); } + /** + * 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 fee91b00a9..c84b9fe487 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -143,7 +143,13 @@ public class StatsLogManager implements ResourceBasedOverride { 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; @@ -217,6 +223,15 @@ public class StatsLogManager implements ResourceBasedOverride { public void log(EventEnum event, @Nullable ItemInfo itemInfo) { } + /** + * 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. *