Loading protos/launcher_atom.proto +1 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ message Application { // Legacy shortcuts and shortcuts handled by ShortcutManager message Shortcut { optional string shortcut_name = 1; optional string shortcut_id = 2; } // AppWidgets handled by AppWidgetManager Loading quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java +144 −88 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ package com.android.launcher3.appprediction; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.annotation.TargetApi; Loading @@ -31,29 +37,38 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logger.LauncherAtom.ContainerInfo; import com.android.launcher3.logger.LauncherAtom.FolderContainer; import com.android.launcher3.logger.LauncherAtom.HotseatContainer; import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer; import com.android.launcher3.logging.StatsLogManager.EventEnum; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.systemui.plugins.AppLaunchEventsPlugin; import com.android.systemui.plugins.PluginListener; import com.android.launcher3.pm.UserCache; import com.android.quickstep.logging.StatsLogCompatManager; import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.function.Predicate; /** * Subclass of app tracker which publishes the data to the prediction engine and gets back results. */ @TargetApi(Build.VERSION_CODES.Q) public class PredictionAppTracker extends AppLaunchTracker implements PluginListener<AppLaunchEventsPlugin> { public class PredictionAppTracker extends AppLaunchTracker implements StatsLogConsumer { private static final String TAG = "PredictionAppTracker"; private static final boolean DBG = false; Loading @@ -65,7 +80,6 @@ public class PredictionAppTracker extends AppLaunchTracker protected final Context mContext; private final Handler mMessageHandler; private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList; // Accessed only on worker thread private AppPredictor mHomeAppPredictor; Loading @@ -76,10 +90,6 @@ public class PredictionAppTracker extends AppLaunchTracker InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged); mMessageHandler.sendEmptyMessage(MSG_INIT); mAppLaunchEventsPluginsList = new ArrayList<>(); PluginManagerWrapper.INSTANCE.get(context) .addPluginListener(this, AppLaunchEventsPlugin.class, true); } @UiThread Loading @@ -96,6 +106,7 @@ public class PredictionAppTracker extends AppLaunchTracker mHomeAppPredictor.destroy(); mHomeAppPredictor = null; } StatsLogCompatManager.LOGS_CONSUMER.remove(this); } @WorkerThread Loading Loading @@ -137,6 +148,7 @@ public class PredictionAppTracker extends AppLaunchTracker // Initialize the clients int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns; mHomeAppPredictor = createPredictor(Client.HOME, count); StatsLogCompatManager.LOGS_CONSUMER.add(this); return true; } case MSG_DESTROY: { Loading Loading @@ -168,98 +180,142 @@ public class PredictionAppTracker extends AppLaunchTracker if (DBG) { Log.d(TAG, String.format("Sent immediate message to update %s", client)); } // Relay onReturnedToHome to every plugin. mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome); } @Override @UiThread public void onStartShortcut(String packageName, String shortcutId, UserHandle user, String container) { // TODO: Use the full shortcut info AppTarget target = new AppTarget.Builder( new AppTargetId("shortcut:" + shortcutId), packageName, user) .setClassName(shortcutId) @AnyThread private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) { AppTarget target = toAppTarget(atomInfo); if (target != null) { AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) .setLaunchLocation(getContainer(atomInfo)) .build(); sendLaunch(target, container); // Relay onStartShortcut info to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onStartShortcut( packageName, shortcutId, user, container != null ? container : CONTAINER_DEFAULT) ); Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); } } @Override @UiThread public void onStartApp(ComponentName cn, UserHandle user, String container) { if (cn != null) { AppTarget target = new AppTarget.Builder( new AppTargetId("app:" + cn), cn.getPackageName(), user) .setClassName(cn.getClassName()) .build(); sendLaunch(target, container); // Relay onStartApp to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onStartApp( cn, user, container != null ? container : CONTAINER_DEFAULT) ); public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) { if (event == LAUNCHER_APP_LAUNCH_TAP || event == LAUNCHER_TASK_LAUNCH_SWIPE_DOWN || event == LAUNCHER_TASK_LAUNCH_TAP || event == LAUNCHER_QUICKSWITCH_RIGHT || event == LAUNCHER_QUICKSWITCH_LEFT) { sendEvent(atomInfo, AppTargetEvent.ACTION_LAUNCH); } else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) { sendEvent(atomInfo, AppTargetEvent.ACTION_DISMISS); } } @Override @UiThread public void onDismissApp(ComponentName cn, UserHandle user, String container) { if (cn == null) return; AppTarget target = new AppTarget.Builder( new AppTargetId("app: " + cn), cn.getPackageName(), user) @Nullable private AppTarget toAppTarget(LauncherAtom.ItemInfo info) { UserHandle userHandle = Process.myUserHandle(); if (info.getIsWork()) { userHandle = UserCache.INSTANCE.get(mContext).getUserProfiles().stream() .filter(((Predicate<UserHandle>) userHandle::equals).negate()) .findAny() .orElse(null); } if (userHandle == null) { return null; } ComponentName cn = null; String id = null; switch (info.getItemCase()) { case APPLICATION: { LauncherAtom.Application app = info.getApplication(); if ((cn = parseNullable(app.getComponentName())) != null) { id = "app:" + cn.getPackageName(); } break; } case SHORTCUT: { LauncherAtom.Shortcut si = info.getShortcut(); if (!TextUtils.isEmpty(si.getShortcutId()) && (cn = parseNullable(si.getShortcutName())) != null) { id = "shortcut:" + si.getShortcutId(); } break; } case WIDGET: { LauncherAtom.Widget widget = info.getWidget(); if ((cn = parseNullable(widget.getComponentName())) != null) { id = "widget:" + cn.getPackageName(); } break; } case TASK: { LauncherAtom.Task task = info.getTask(); if ((cn = parseNullable(task.getComponentName())) != null) { id = "app:" + cn.getPackageName(); } break; } case FOLDER_ICON: { id = "folder:" + SystemClock.uptimeMillis(); cn = new ComponentName(mContext.getPackageName(), "#folder"); } } if (id != null && cn != null) { return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle) .setClassName(cn.getClassName()) .build(); sendDismiss(target, container); // Relay onDismissApp to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onDismissApp( cn, user, container != null ? container : CONTAINER_DEFAULT) ); } @UiThread private void sendEvent(AppTarget target, String container, int eventId) { AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) .setLaunchLocation(container == null ? CONTAINER_DEFAULT : container) .build(); Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); return null; } @UiThread private void sendLaunch(AppTarget target, String container) { sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH); private String getContainer(LauncherAtom.ItemInfo info) { ContainerInfo ci = info.getContainerInfo(); switch (ci.getContainerCase()) { case WORKSPACE: { // In case the item type is not widgets, the spaceX and spanY default to 1. int spanX = info.getWidget().getSpanX(); int spanY = info.getWidget().getSpanY(); return getWorkspaceContainerString(ci.getWorkspace(), spanX, spanY); } case HOTSEAT: { return getHotseatContainerString(ci.getHotseat()); } case TASK_SWITCHER_CONTAINER: { return "task-switcher"; } case ALL_APPS_CONTAINER: { return "all-apps"; } case SEARCH_RESULT_CONTAINER: { return "search-results"; } case PREDICTED_HOTSEAT_CONTAINER: { return "predictions/hotseat"; } case PREDICTION_CONTAINER: { return "predictions"; } case FOLDER: { FolderContainer fc = ci.getFolder(); switch (fc.getParentContainerCase()) { case WORKSPACE: return "folder/" + getWorkspaceContainerString(fc.getWorkspace(), 1, 1); case HOTSEAT: return "folder/" + getHotseatContainerString(fc.getHotseat()); } return "folder"; } } return ""; } @UiThread private void sendDismiss(AppTarget target, String container) { sendEvent(target, container, AppTargetEvent.ACTION_DISMISS); private static String getWorkspaceContainerString(WorkspaceContainer wc, int spanX, int spanY) { return String.format(Locale.ENGLISH, "workspace/%d/[%d,%d]/[%d,%d]", wc.getPageIndex(), wc.getGridX(), wc.getGridY(), spanX, spanY); } @Override public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) { mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin); private static String getHotseatContainerString(HotseatContainer hc) { return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex()); } @Override public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) { mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin); private static ComponentName parseNullable(String componentNameString) { return TextUtils.isEmpty(componentNameString) ? null : ComponentName.unflattenFromString(componentNameString); } } quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java +1 −5 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.keyboard.FocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper; import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; Loading Loading @@ -93,9 +92,6 @@ public class PredictionRowView extends LinearLayout implements private static final Interpolator ALPHA_FACTOR_INTERPOLATOR = (t) -> (t < 0.8f) ? 0 : (t - 0.8f) / 0.2f; private static final OnClickListener PREDICTION_CLICK_LISTENER = ItemClickHandler.getInstance(AppLaunchTracker.CONTAINER_PREDICTIONS); private final Launcher mLauncher; private final PredictionUiStateManager mPredictionUiStateManager; private int mNumPredictedAppsPerRow; Loading Loading @@ -246,7 +242,7 @@ public class PredictionRowView extends LinearLayout implements while (getChildCount() < mNumPredictedAppsPerRow) { BubbleTextView icon = (BubbleTextView) inflater.inflate( R.layout.all_apps_icon, this, false); icon.setOnClickListener(PREDICTION_CLICK_LISTENER); icon.setOnClickListener(ItemClickHandler.INSTANCE); icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS); icon.setLongPressTimeoutFactor(1f); icon.setOnFocusChangeListener(mFocusHelper); Loading quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +2 −5 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import androidx.annotation.Nullable; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; Loading Loading @@ -129,12 +127,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { } @Override public boolean startActivitySafely(View v, Intent intent, ItemInfo item, @Nullable String sourceContainer) { public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { if (mHotseatPredictionController != null) { mHotseatPredictionController.setPauseUIUpdate(true); } return super.startActivitySafely(v, intent, item, sourceContainer); return super.startActivitySafely(v, intent, item); } @Override Loading quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +30 −23 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import android.view.ViewTreeObserver.OnDrawListener; import android.view.WindowInsets; import android.view.animation.Interpolator; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.android.launcher3.AbstractFloatingView; Loading @@ -69,6 +70,7 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; Loading Loading @@ -874,22 +876,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } private void doLogGesture(GestureEndTarget endTarget) { DeviceProfile dp = mDp; if (dp == null || mDownPos == null) { // We probably never received an animation controller, skip logging. return; } int pageIndex = endTarget == LAST_TASK ? LOG_NO_OP_PAGE_INDEX : mRecentsView.getNextPage(); UserEventDispatcher.newInstance(mContext).logStateChangeAction( mLogAction, mLogDirection, (int) mDownPos.x, (int) mDownPos.y, ContainerType.NAVBAR, ContainerType.APP, endTarget.containerType, pageIndex); private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) { StatsLogManager.EventEnum event; switch (endTarget) { case HOME: Loading @@ -907,10 +894,29 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte default: event = IGNORE; } StatsLogManager.newInstance(mContext).logger() StatsLogger logger = StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) .log(event); .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)); if (targetTask != null) { logger.withItemInfo(targetTask.getItemInfo()); } logger.log(event); DeviceProfile dp = mDp; if (dp == null || mDownPos == null) { // We probably never received an animation controller, skip logging. return; } int pageIndex = endTarget == LAST_TASK ? LOG_NO_OP_PAGE_INDEX : mRecentsView.getNextPage(); UserEventDispatcher.newInstance(mContext).logStateChangeAction( mLogAction, mLogDirection, (int) mDownPos.x, (int) mDownPos.y, ContainerType.NAVBAR, ContainerType.APP, endTarget.containerType, pageIndex); } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ Loading Loading @@ -1115,7 +1121,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte private void resumeLastTask() { mRecentsAnimationController.finish(false /* toRecents */, null); ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); doLogGesture(LAST_TASK); doLogGesture(LAST_TASK, null); reset(); } Loading @@ -1130,6 +1136,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte @UiThread private void startNewTaskInternal() { TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); startNewTask(success -> { if (!success) { reset(); Loading @@ -1138,7 +1145,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte endLauncherTransitionController(); updateSysUiFlags(1 /* windowProgress == overview */); } doLogGesture(NEW_TASK); doLogGesture(NEW_TASK, taskToLaunch); }); } Loading Loading @@ -1284,7 +1291,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); } ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true); doLogGesture(HOME); doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView()); } protected abstract void finishRecentsControllerToHome(Runnable callback); Loading @@ -1299,7 +1306,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte mRecentsView.onSwipeUpAnimationSuccess(); SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); doLogGesture(RECENTS); doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView()); reset(); } Loading Loading
protos/launcher_atom.proto +1 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,7 @@ message Application { // Legacy shortcuts and shortcuts handled by ShortcutManager message Shortcut { optional string shortcut_name = 1; optional string shortcut_id = 2; } // AppWidgets handled by AppWidgetManager Loading
quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java +144 −88 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ package com.android.launcher3.appprediction; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.annotation.TargetApi; Loading @@ -31,29 +37,38 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Process; import android.os.SystemClock; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logger.LauncherAtom.ContainerInfo; import com.android.launcher3.logger.LauncherAtom.FolderContainer; import com.android.launcher3.logger.LauncherAtom.HotseatContainer; import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer; import com.android.launcher3.logging.StatsLogManager.EventEnum; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.systemui.plugins.AppLaunchEventsPlugin; import com.android.systemui.plugins.PluginListener; import com.android.launcher3.pm.UserCache; import com.android.quickstep.logging.StatsLogCompatManager; import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.function.Predicate; /** * Subclass of app tracker which publishes the data to the prediction engine and gets back results. */ @TargetApi(Build.VERSION_CODES.Q) public class PredictionAppTracker extends AppLaunchTracker implements PluginListener<AppLaunchEventsPlugin> { public class PredictionAppTracker extends AppLaunchTracker implements StatsLogConsumer { private static final String TAG = "PredictionAppTracker"; private static final boolean DBG = false; Loading @@ -65,7 +80,6 @@ public class PredictionAppTracker extends AppLaunchTracker protected final Context mContext; private final Handler mMessageHandler; private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList; // Accessed only on worker thread private AppPredictor mHomeAppPredictor; Loading @@ -76,10 +90,6 @@ public class PredictionAppTracker extends AppLaunchTracker InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged); mMessageHandler.sendEmptyMessage(MSG_INIT); mAppLaunchEventsPluginsList = new ArrayList<>(); PluginManagerWrapper.INSTANCE.get(context) .addPluginListener(this, AppLaunchEventsPlugin.class, true); } @UiThread Loading @@ -96,6 +106,7 @@ public class PredictionAppTracker extends AppLaunchTracker mHomeAppPredictor.destroy(); mHomeAppPredictor = null; } StatsLogCompatManager.LOGS_CONSUMER.remove(this); } @WorkerThread Loading Loading @@ -137,6 +148,7 @@ public class PredictionAppTracker extends AppLaunchTracker // Initialize the clients int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns; mHomeAppPredictor = createPredictor(Client.HOME, count); StatsLogCompatManager.LOGS_CONSUMER.add(this); return true; } case MSG_DESTROY: { Loading Loading @@ -168,98 +180,142 @@ public class PredictionAppTracker extends AppLaunchTracker if (DBG) { Log.d(TAG, String.format("Sent immediate message to update %s", client)); } // Relay onReturnedToHome to every plugin. mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome); } @Override @UiThread public void onStartShortcut(String packageName, String shortcutId, UserHandle user, String container) { // TODO: Use the full shortcut info AppTarget target = new AppTarget.Builder( new AppTargetId("shortcut:" + shortcutId), packageName, user) .setClassName(shortcutId) @AnyThread private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) { AppTarget target = toAppTarget(atomInfo); if (target != null) { AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) .setLaunchLocation(getContainer(atomInfo)) .build(); sendLaunch(target, container); // Relay onStartShortcut info to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onStartShortcut( packageName, shortcutId, user, container != null ? container : CONTAINER_DEFAULT) ); Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); } } @Override @UiThread public void onStartApp(ComponentName cn, UserHandle user, String container) { if (cn != null) { AppTarget target = new AppTarget.Builder( new AppTargetId("app:" + cn), cn.getPackageName(), user) .setClassName(cn.getClassName()) .build(); sendLaunch(target, container); // Relay onStartApp to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onStartApp( cn, user, container != null ? container : CONTAINER_DEFAULT) ); public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) { if (event == LAUNCHER_APP_LAUNCH_TAP || event == LAUNCHER_TASK_LAUNCH_SWIPE_DOWN || event == LAUNCHER_TASK_LAUNCH_TAP || event == LAUNCHER_QUICKSWITCH_RIGHT || event == LAUNCHER_QUICKSWITCH_LEFT) { sendEvent(atomInfo, AppTargetEvent.ACTION_LAUNCH); } else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) { sendEvent(atomInfo, AppTargetEvent.ACTION_DISMISS); } } @Override @UiThread public void onDismissApp(ComponentName cn, UserHandle user, String container) { if (cn == null) return; AppTarget target = new AppTarget.Builder( new AppTargetId("app: " + cn), cn.getPackageName(), user) @Nullable private AppTarget toAppTarget(LauncherAtom.ItemInfo info) { UserHandle userHandle = Process.myUserHandle(); if (info.getIsWork()) { userHandle = UserCache.INSTANCE.get(mContext).getUserProfiles().stream() .filter(((Predicate<UserHandle>) userHandle::equals).negate()) .findAny() .orElse(null); } if (userHandle == null) { return null; } ComponentName cn = null; String id = null; switch (info.getItemCase()) { case APPLICATION: { LauncherAtom.Application app = info.getApplication(); if ((cn = parseNullable(app.getComponentName())) != null) { id = "app:" + cn.getPackageName(); } break; } case SHORTCUT: { LauncherAtom.Shortcut si = info.getShortcut(); if (!TextUtils.isEmpty(si.getShortcutId()) && (cn = parseNullable(si.getShortcutName())) != null) { id = "shortcut:" + si.getShortcutId(); } break; } case WIDGET: { LauncherAtom.Widget widget = info.getWidget(); if ((cn = parseNullable(widget.getComponentName())) != null) { id = "widget:" + cn.getPackageName(); } break; } case TASK: { LauncherAtom.Task task = info.getTask(); if ((cn = parseNullable(task.getComponentName())) != null) { id = "app:" + cn.getPackageName(); } break; } case FOLDER_ICON: { id = "folder:" + SystemClock.uptimeMillis(); cn = new ComponentName(mContext.getPackageName(), "#folder"); } } if (id != null && cn != null) { return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle) .setClassName(cn.getClassName()) .build(); sendDismiss(target, container); // Relay onDismissApp to every connected plugin. mAppLaunchEventsPluginsList .forEach(plugin -> plugin.onDismissApp( cn, user, container != null ? container : CONTAINER_DEFAULT) ); } @UiThread private void sendEvent(AppTarget target, String container, int eventId) { AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) .setLaunchLocation(container == null ? CONTAINER_DEFAULT : container) .build(); Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); return null; } @UiThread private void sendLaunch(AppTarget target, String container) { sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH); private String getContainer(LauncherAtom.ItemInfo info) { ContainerInfo ci = info.getContainerInfo(); switch (ci.getContainerCase()) { case WORKSPACE: { // In case the item type is not widgets, the spaceX and spanY default to 1. int spanX = info.getWidget().getSpanX(); int spanY = info.getWidget().getSpanY(); return getWorkspaceContainerString(ci.getWorkspace(), spanX, spanY); } case HOTSEAT: { return getHotseatContainerString(ci.getHotseat()); } case TASK_SWITCHER_CONTAINER: { return "task-switcher"; } case ALL_APPS_CONTAINER: { return "all-apps"; } case SEARCH_RESULT_CONTAINER: { return "search-results"; } case PREDICTED_HOTSEAT_CONTAINER: { return "predictions/hotseat"; } case PREDICTION_CONTAINER: { return "predictions"; } case FOLDER: { FolderContainer fc = ci.getFolder(); switch (fc.getParentContainerCase()) { case WORKSPACE: return "folder/" + getWorkspaceContainerString(fc.getWorkspace(), 1, 1); case HOTSEAT: return "folder/" + getHotseatContainerString(fc.getHotseat()); } return "folder"; } } return ""; } @UiThread private void sendDismiss(AppTarget target, String container) { sendEvent(target, container, AppTargetEvent.ACTION_DISMISS); private static String getWorkspaceContainerString(WorkspaceContainer wc, int spanX, int spanY) { return String.format(Locale.ENGLISH, "workspace/%d/[%d,%d]/[%d,%d]", wc.getPageIndex(), wc.getGridX(), wc.getGridY(), spanX, spanY); } @Override public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) { mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin); private static String getHotseatContainerString(HotseatContainer hc) { return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex()); } @Override public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) { mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin); private static ComponentName parseNullable(String componentNameString) { return TextUtils.isEmpty(componentNameString) ? null : ComponentName.unflattenFromString(componentNameString); } }
quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java +1 −5 Original line number Diff line number Diff line Loading @@ -56,7 +56,6 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.keyboard.FocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper; import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; Loading Loading @@ -93,9 +92,6 @@ public class PredictionRowView extends LinearLayout implements private static final Interpolator ALPHA_FACTOR_INTERPOLATOR = (t) -> (t < 0.8f) ? 0 : (t - 0.8f) / 0.2f; private static final OnClickListener PREDICTION_CLICK_LISTENER = ItemClickHandler.getInstance(AppLaunchTracker.CONTAINER_PREDICTIONS); private final Launcher mLauncher; private final PredictionUiStateManager mPredictionUiStateManager; private int mNumPredictedAppsPerRow; Loading Loading @@ -246,7 +242,7 @@ public class PredictionRowView extends LinearLayout implements while (getChildCount() < mNumPredictedAppsPerRow) { BubbleTextView icon = (BubbleTextView) inflater.inflate( R.layout.all_apps_icon, this, false); icon.setOnClickListener(PREDICTION_CLICK_LISTENER); icon.setOnClickListener(ItemClickHandler.INSTANCE); icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS); icon.setLongPressTimeoutFactor(1f); icon.setOnFocusChangeListener(mFocusHelper); Loading
quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +2 −5 Original line number Diff line number Diff line Loading @@ -34,8 +34,6 @@ import android.os.Bundle; import android.util.Log; import android.view.View; import androidx.annotation.Nullable; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; Loading Loading @@ -129,12 +127,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { } @Override public boolean startActivitySafely(View v, Intent intent, ItemInfo item, @Nullable String sourceContainer) { public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { if (mHotseatPredictionController != null) { mHotseatPredictionController.setPauseUIUpdate(true); } return super.startActivitySafely(v, intent, item, sourceContainer); return super.startActivitySafely(v, intent, item); } @Override Loading
quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +30 −23 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import android.view.ViewTreeObserver.OnDrawListener; import android.view.WindowInsets; import android.view.animation.Interpolator; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.android.launcher3.AbstractFloatingView; Loading @@ -69,6 +70,7 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; Loading Loading @@ -874,22 +876,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } private void doLogGesture(GestureEndTarget endTarget) { DeviceProfile dp = mDp; if (dp == null || mDownPos == null) { // We probably never received an animation controller, skip logging. return; } int pageIndex = endTarget == LAST_TASK ? LOG_NO_OP_PAGE_INDEX : mRecentsView.getNextPage(); UserEventDispatcher.newInstance(mContext).logStateChangeAction( mLogAction, mLogDirection, (int) mDownPos.x, (int) mDownPos.y, ContainerType.NAVBAR, ContainerType.APP, endTarget.containerType, pageIndex); private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) { StatsLogManager.EventEnum event; switch (endTarget) { case HOME: Loading @@ -907,10 +894,29 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte default: event = IGNORE; } StatsLogManager.newInstance(mContext).logger() StatsLogger logger = StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) .log(event); .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)); if (targetTask != null) { logger.withItemInfo(targetTask.getItemInfo()); } logger.log(event); DeviceProfile dp = mDp; if (dp == null || mDownPos == null) { // We probably never received an animation controller, skip logging. return; } int pageIndex = endTarget == LAST_TASK ? LOG_NO_OP_PAGE_INDEX : mRecentsView.getNextPage(); UserEventDispatcher.newInstance(mContext).logStateChangeAction( mLogAction, mLogDirection, (int) mDownPos.x, (int) mDownPos.y, ContainerType.NAVBAR, ContainerType.APP, endTarget.containerType, pageIndex); } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ Loading Loading @@ -1115,7 +1121,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte private void resumeLastTask() { mRecentsAnimationController.finish(false /* toRecents */, null); ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); doLogGesture(LAST_TASK); doLogGesture(LAST_TASK, null); reset(); } Loading @@ -1130,6 +1136,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte @UiThread private void startNewTaskInternal() { TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); startNewTask(success -> { if (!success) { reset(); Loading @@ -1138,7 +1145,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte endLauncherTransitionController(); updateSysUiFlags(1 /* windowProgress == overview */); } doLogGesture(NEW_TASK); doLogGesture(NEW_TASK, taskToLaunch); }); } Loading Loading @@ -1284,7 +1291,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); } ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true); doLogGesture(HOME); doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView()); } protected abstract void finishRecentsControllerToHome(Runnable callback); Loading @@ -1299,7 +1306,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte mRecentsView.onSwipeUpAnimationSuccess(); SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); doLogGesture(RECENTS); doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView()); reset(); } Loading