Using StatsLog for notifyingAppPredictor

> Adding a listener in StartsLogManager for listening to events.
  This allows events to be directored to the predictor only if
  it is already running, instead of creating it.
> Unifying the event format to be same as hotseat predictor

Bug: 160748731
Change-Id: Ib00e6249ff642c030f00bcad5b748255e704d16a
This commit is contained in:
Sunny Goyal 2020-07-15 17:02:16 -07:00
parent 2c0cdfb100
commit 852537fd98
24 changed files with 259 additions and 345 deletions

View File

@ -131,6 +131,7 @@ message Application {
// Legacy shortcuts and shortcuts handled by ShortcutManager // Legacy shortcuts and shortcuts handled by ShortcutManager
message Shortcut { message Shortcut {
optional string shortcut_name = 1; optional string shortcut_name = 1;
optional string shortcut_id = 2;
} }
// AppWidgets handled by AppWidgetManager // AppWidgets handled by AppWidgetManager

View File

@ -16,6 +16,12 @@
package com.android.launcher3.appprediction; package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; 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 static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -31,29 +37,38 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import androidx.annotation.AnyThread;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client; 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.model.AppLaunchTracker;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.pm.UserCache;
import com.android.systemui.plugins.AppLaunchEventsPlugin; import com.android.quickstep.logging.StatsLogCompatManager;
import com.android.systemui.plugins.PluginListener; import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer;
import java.util.ArrayList; import java.util.Locale;
import java.util.List; import java.util.function.Predicate;
/** /**
* Subclass of app tracker which publishes the data to the prediction engine and gets back results. * Subclass of app tracker which publishes the data to the prediction engine and gets back results.
*/ */
@TargetApi(Build.VERSION_CODES.Q) @TargetApi(Build.VERSION_CODES.Q)
public class PredictionAppTracker extends AppLaunchTracker public class PredictionAppTracker extends AppLaunchTracker implements StatsLogConsumer {
implements PluginListener<AppLaunchEventsPlugin> {
private static final String TAG = "PredictionAppTracker"; private static final String TAG = "PredictionAppTracker";
private static final boolean DBG = false; private static final boolean DBG = false;
@ -65,7 +80,6 @@ public class PredictionAppTracker extends AppLaunchTracker
protected final Context mContext; protected final Context mContext;
private final Handler mMessageHandler; private final Handler mMessageHandler;
private final List<AppLaunchEventsPlugin> mAppLaunchEventsPluginsList;
// Accessed only on worker thread // Accessed only on worker thread
private AppPredictor mHomeAppPredictor; private AppPredictor mHomeAppPredictor;
@ -76,10 +90,6 @@ public class PredictionAppTracker extends AppLaunchTracker
InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged); InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged);
mMessageHandler.sendEmptyMessage(MSG_INIT); mMessageHandler.sendEmptyMessage(MSG_INIT);
mAppLaunchEventsPluginsList = new ArrayList<>();
PluginManagerWrapper.INSTANCE.get(context)
.addPluginListener(this, AppLaunchEventsPlugin.class, true);
} }
@UiThread @UiThread
@ -96,6 +106,7 @@ public class PredictionAppTracker extends AppLaunchTracker
mHomeAppPredictor.destroy(); mHomeAppPredictor.destroy();
mHomeAppPredictor = null; mHomeAppPredictor = null;
} }
StatsLogCompatManager.LOGS_CONSUMER.remove(this);
} }
@WorkerThread @WorkerThread
@ -137,6 +148,7 @@ public class PredictionAppTracker extends AppLaunchTracker
// Initialize the clients // Initialize the clients
int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns; int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns;
mHomeAppPredictor = createPredictor(Client.HOME, count); mHomeAppPredictor = createPredictor(Client.HOME, count);
StatsLogCompatManager.LOGS_CONSUMER.add(this);
return true; return true;
} }
case MSG_DESTROY: { case MSG_DESTROY: {
@ -168,98 +180,142 @@ public class PredictionAppTracker extends AppLaunchTracker
if (DBG) { if (DBG) {
Log.d(TAG, String.format("Sent immediate message to update %s", client)); Log.d(TAG, String.format("Sent immediate message to update %s", client));
} }
// Relay onReturnedToHome to every plugin.
mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome);
} }
@Override @AnyThread
@UiThread private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) {
public void onStartShortcut(String packageName, String shortcutId, UserHandle user, AppTarget target = toAppTarget(atomInfo);
String container) { if (target != null) {
// TODO: Use the full shortcut info
AppTarget target = new AppTarget.Builder(
new AppTargetId("shortcut:" + shortcutId), packageName, user)
.setClassName(shortcutId)
.build();
sendLaunch(target, container);
// Relay onStartShortcut info to every connected plugin.
mAppLaunchEventsPluginsList
.forEach(plugin -> plugin.onStartShortcut(
packageName,
shortcutId,
user,
container != null ? container : CONTAINER_DEFAULT)
);
}
@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)
);
}
}
@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)
.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) AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container) .setLaunchLocation(getContainer(atomInfo))
.build(); .build();
Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
} }
@UiThread
private void sendLaunch(AppTarget target, String container) {
sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH);
}
@UiThread
private void sendDismiss(AppTarget target, String container) {
sendEvent(target, container, AppTargetEvent.ACTION_DISMISS);
} }
@Override @Override
public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) { public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) {
mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin); 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 @Nullable
public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) { private AppTarget toAppTarget(LauncherAtom.ItemInfo info) {
mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin); 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();
}
return null;
}
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 "";
}
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);
}
private static String getHotseatContainerString(HotseatContainer hc) {
return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex());
}
private static ComponentName parseNullable(String componentNameString) {
return TextUtils.isEmpty(componentNameString)
? null : ComponentName.unflattenFromString(componentNameString);
} }
} }

View File

@ -56,7 +56,6 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.keyboard.FocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper;
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; 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.AppInfo;
import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.ItemInfoWithIcon;
@ -93,9 +92,6 @@ public class PredictionRowView extends LinearLayout implements
private static final Interpolator ALPHA_FACTOR_INTERPOLATOR = private static final Interpolator ALPHA_FACTOR_INTERPOLATOR =
(t) -> (t < 0.8f) ? 0 : (t - 0.8f) / 0.2f; (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 Launcher mLauncher;
private final PredictionUiStateManager mPredictionUiStateManager; private final PredictionUiStateManager mPredictionUiStateManager;
private int mNumPredictedAppsPerRow; private int mNumPredictedAppsPerRow;
@ -246,7 +242,7 @@ public class PredictionRowView extends LinearLayout implements
while (getChildCount() < mNumPredictedAppsPerRow) { while (getChildCount() < mNumPredictedAppsPerRow) {
BubbleTextView icon = (BubbleTextView) inflater.inflate( BubbleTextView icon = (BubbleTextView) inflater.inflate(
R.layout.all_apps_icon, this, false); R.layout.all_apps_icon, this, false);
icon.setOnClickListener(PREDICTION_CLICK_LISTENER); icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS); icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
icon.setLongPressTimeoutFactor(1f); icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mFocusHelper); icon.setOnFocusChangeListener(mFocusHelper);

View File

@ -34,8 +34,6 @@ import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
@ -129,12 +127,11 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
} }
@Override @Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item, public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
@Nullable String sourceContainer) {
if (mHotseatPredictionController != null) { if (mHotseatPredictionController != null) {
mHotseatPredictionController.setPauseUIUpdate(true); mHotseatPredictionController.setPauseUIUpdate(true);
} }
return super.startActivitySafely(v, intent, item, sourceContainer); return super.startActivitySafely(v, intent, item);
} }
@Override @Override

View File

@ -59,6 +59,7 @@ import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread; import androidx.annotation.UiThread;
import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.AbstractFloatingView;
@ -69,6 +70,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@ -876,22 +878,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
} }
private void doLogGesture(GestureEndTarget endTarget) { private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
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);
StatsLogManager.EventEnum event; StatsLogManager.EventEnum event;
switch (endTarget) { switch (endTarget) {
case HOME: case HOME:
@ -909,10 +896,29 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
default: default:
event = IGNORE; event = IGNORE;
} }
StatsLogManager.newInstance(mContext).logger() StatsLogger logger = StatsLogManager.newInstance(mContext).logger()
.withSrcState(LAUNCHER_STATE_BACKGROUND) .withSrcState(LAUNCHER_STATE_BACKGROUND)
.withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType));
.log(event); 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. */ /** Animates to the given progress, where 0 is the current app and 1 is overview. */
@ -1117,7 +1123,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
private void resumeLastTask() { private void resumeLastTask() {
mRecentsAnimationController.finish(false /* toRecents */, null); mRecentsAnimationController.finish(false /* toRecents */, null);
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
doLogGesture(LAST_TASK); doLogGesture(LAST_TASK, null);
reset(); reset();
} }
@ -1132,6 +1138,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
@UiThread @UiThread
private void startNewTaskInternal() { private void startNewTaskInternal() {
TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
startNewTask(success -> { startNewTask(success -> {
if (!success) { if (!success) {
reset(); reset();
@ -1140,7 +1147,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
endLauncherTransitionController(); endLauncherTransitionController();
updateSysUiFlags(1 /* windowProgress == overview */); updateSysUiFlags(1 /* windowProgress == overview */);
} }
doLogGesture(NEW_TASK); doLogGesture(NEW_TASK, taskToLaunch);
}); });
} }
@ -1285,7 +1292,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
} }
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true); ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
doLogGesture(HOME); doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView());
} }
protected abstract void finishRecentsControllerToHome(Runnable callback); protected abstract void finishRecentsControllerToHome(Runnable callback);
@ -1300,7 +1307,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
mRecentsView.onSwipeUpAnimationSuccess(); mRecentsView.onSwipeUpAnimationSuccess();
SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
doLogGesture(RECENTS); doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView());
reset(); reset();
} }

View File

@ -61,7 +61,6 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.TestLogging;
@ -771,13 +770,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
mOverviewComponentObserver.getActivityInterface(); mOverviewComponentObserver.getActivityInterface();
final Intent overviewIntent = new Intent( final Intent overviewIntent = new Intent(
mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState()); mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
if (activityInterface.getCreatedActivity() == null) { if (activityInterface.getCreatedActivity() != null && fromInit) {
// Make sure that UI states will be initialized.
activityInterface.createActivityInitListener((wasVisible) -> {
AppLaunchTracker.INSTANCE.get(TouchInteractionService.this);
return false;
}).register(overviewIntent);
} else if (fromInit) {
// The activity has been created before the initialization of overview service. It is // The activity has been created before the initialization of overview service. It is
// usually happens when booting or launcher is the top activity, so we should already // usually happens when booting or launcher is the top activity, so we should already
// have the latest state. // have the latest state.

View File

@ -63,12 +63,6 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
mActivity.startHome(); mActivity.startHome();
} }
@Override
public boolean shouldUseMultiWindowTaskSizeStrategy() {
// Just use the activity task size for multi-window as well.
return false;
}
/** /**
* When starting gesture interaction from home, we add a temporary invisible tile corresponding * When starting gesture interaction from home, we add a temporary invisible tile corresponding
* to the home task. This allows us to handle quick-switch similarly to a quick-switching * to the home task. This allows us to handle quick-switch similarly to a quick-switching

View File

@ -31,7 +31,6 @@ import android.animation.ObjectAnimator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.os.UserHandle;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
@ -41,18 +40,15 @@ import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.Hotseat; import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.views.ScrimView; import com.android.launcher3.views.ScrimView;
import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.TransformParams; import com.android.quickstep.util.TransformParams;
import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.RecentsExtraCard; import com.android.systemui.plugins.RecentsExtraCard;
import com.android.systemui.shared.recents.model.Task;
/** /**
* {@link RecentsView} used in Launcher activity * {@link RecentsView} used in Launcher activity
@ -178,18 +174,6 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher>
super.onTaskLaunchAnimationEnd(success); super.onTaskLaunchAnimationEnd(success);
} }
@Override
public void onTaskLaunched(Task task) {
UserHandle user = UserHandle.of(task.key.userId);
AppLaunchTracker.INSTANCE.get(getContext()).onStartApp(task.getTopComponent(), user,
AppLaunchTracker.CONTAINER_OVERVIEW);
}
@Override
public boolean shouldUseMultiWindowTaskSizeStrategy() {
return TraceHelper.whitelistIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode);
}
@Override @Override
public void scrollTo(int x, int y) { public void scrollTo(int x, int y) {
super.scrollTo(x, y); super.scrollTo(x, y);

View File

@ -55,11 +55,8 @@ import android.animation.LayoutTransition.TransitionListener;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Point; import android.graphics.Point;
@ -1997,19 +1994,12 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) { protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) {
} }
public abstract boolean shouldUseMultiWindowTaskSizeStrategy();
protected void onTaskLaunchAnimationEnd(boolean success) { protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) { if (success) {
resetTaskVisuals(); resetTaskVisuals();
} }
} }
/**
* Called when task activity is launched
*/
public void onTaskLaunched(Task task){ }
@Override @Override
protected void notifyPageSwitchListener(int prevPage) { protected void notifyPageSwitchListener(int prevPage) {
super.notifyPageSwitchListener(prevPage); super.notifyPageSwitchListener(prevPage);

View File

@ -30,8 +30,7 @@ import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
import android.animation.Animator; import android.animation.Animator;
@ -385,7 +384,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
} }
}, resultCallbackHandler); }, resultCallbackHandler);
} }
getRecentsView().onTaskLaunched(mTask);
} }
} }

View File

@ -27,7 +27,7 @@ import static com.android.systemui.shared.system.SysUiStatsLog.LAUNCHER_UICHANGE
import android.content.Context; import android.content.Context;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
@ -54,6 +54,7 @@ import com.android.systemui.shared.system.SysUiStatsLog;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.concurrent.CopyOnWriteArrayList;
/** /**
* This class calls StatsLog compile time generated methods. * This class calls StatsLog compile time generated methods.
@ -68,8 +69,6 @@ public class StatsLogCompatManager extends StatsLogManager {
private static final String TAG = "StatsLog"; private static final String TAG = "StatsLog";
private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG); private static final boolean IS_VERBOSE = Utilities.isPropertyEnabled(LogConfig.STATSLOG);
private static Context sContext;
private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0); private static final InstanceId DEFAULT_INSTANCE_ID = InstanceId.fakeInstanceId(0);
// LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates // LauncherAtom.ItemInfo.getDefaultInstance() should be used but until launcher proto migrates
// from nano to lite, bake constant to prevent robo test failure. // from nano to lite, bake constant to prevent robo test failure.
@ -77,8 +76,13 @@ public class StatsLogCompatManager extends StatsLogManager {
private static final int FOLDER_HIERARCHY_OFFSET = 100; private static final int FOLDER_HIERARCHY_OFFSET = 100;
private static final int SEARCH_RESULT_HIERARCHY_OFFSET = 200; private static final int SEARCH_RESULT_HIERARCHY_OFFSET = 200;
public static final CopyOnWriteArrayList<StatsLogConsumer> LOGS_CONSUMER =
new CopyOnWriteArrayList<>();
private final Context mContext;
public StatsLogCompatManager(Context context) { public StatsLogCompatManager(Context context) {
sContext = context; mContext = context;
} }
@Override @Override
@ -86,25 +90,12 @@ public class StatsLogCompatManager extends StatsLogManager {
return new StatsCompatLogger(); return new StatsCompatLogger();
} }
/**
* Logs a ranking event and accompanying {@link InstanceId} and package name.
*/
@Override
public void log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName,
int position) {
SysUiStatsLog.write(SysUiStatsLog.RANKING_SELECTED,
rankingEvent.getId() /* event_id = 1; */,
packageName /* package_name = 2; */,
instanceId.getId() /* instance_id = 3; */,
position /* position_picked = 4; */);
}
/** /**
* Logs the workspace layout information on the model thread. * Logs the workspace layout information on the model thread.
*/ */
@Override @Override
public void logSnapshot() { public void logSnapshot() {
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask(
new SnapshotWorker()); new SnapshotWorker());
} }
@ -175,6 +166,7 @@ public class StatsLogCompatManager extends StatsLogManager {
private static class StatsCompatLogger implements StatsLogger { private static class StatsCompatLogger implements StatsLogger {
private static final ItemInfo DEFAULT_ITEM_INFO = new ItemInfo(); private static final ItemInfo DEFAULT_ITEM_INFO = new ItemInfo();
private ItemInfo mItemInfo = DEFAULT_ITEM_INFO; private ItemInfo mItemInfo = DEFAULT_ITEM_INFO;
private InstanceId mInstanceId = DEFAULT_INSTANCE_ID; private InstanceId mInstanceId = DEFAULT_INSTANCE_ID;
private OptionalInt mRank = OptionalInt.empty(); private OptionalInt mRank = OptionalInt.empty();
@ -253,36 +245,35 @@ public class StatsLogCompatManager extends StatsLogManager {
return; return;
} }
if (mItemInfo.container < 0) { LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
// Item is not within a folder. Write to StatsLog in same thread. if (mItemInfo.container < 0 || appState == null) {
write(event, mInstanceId, applyOverwrites(mItemInfo.buildProto()), mSrcState, // Write log on the model thread so that logs do not go out of order
mDstState); // (for eg: drop comes after drag)
Executors.MODEL_EXECUTOR.execute(
() -> write(event, applyOverwrites(mItemInfo.buildProto())));
} else { } else {
// Item is inside the folder, fetch folder info in a BG thread // Item is inside the folder, fetch folder info in a BG thread
// and then write to StatsLog. // and then write to StatsLog.
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask( appState.getModel().enqueueModelUpdateTask(
new BaseModelUpdateTask() { new BaseModelUpdateTask() {
@Override @Override
public void execute(LauncherAppState app, BgDataModel dataModel, public void execute(LauncherAppState app, BgDataModel dataModel,
AllAppsList apps) { AllAppsList apps) {
FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container); FolderInfo folderInfo = dataModel.folders.get(mItemInfo.container);
write(event, mInstanceId, write(event, applyOverwrites(mItemInfo.buildProto(folderInfo)));
applyOverwrites(mItemInfo.buildProto(folderInfo)),
mSrcState, mDstState);
} }
}); });
} }
} }
private LauncherAtom.ItemInfo applyOverwrites(LauncherAtom.ItemInfo atomInfo) { private LauncherAtom.ItemInfo applyOverwrites(LauncherAtom.ItemInfo atomInfo) {
LauncherAtom.ItemInfo.Builder itemInfoBuilder = LauncherAtom.ItemInfo.Builder itemInfoBuilder = atomInfo.toBuilder();
(LauncherAtom.ItemInfo.Builder) atomInfo.toBuilder();
mRank.ifPresent(itemInfoBuilder::setRank); mRank.ifPresent(itemInfoBuilder::setRank);
mContainerInfo.ifPresent(itemInfoBuilder::setContainerInfo); mContainerInfo.ifPresent(itemInfoBuilder::setContainerInfo);
if (mFromState.isPresent() || mToState.isPresent() || mEditText.isPresent()) { if (mFromState.isPresent() || mToState.isPresent() || mEditText.isPresent()) {
FolderIcon.Builder folderIconBuilder = (FolderIcon.Builder) itemInfoBuilder FolderIcon.Builder folderIconBuilder = itemInfoBuilder
.getFolderIcon() .getFolderIcon()
.toBuilder(); .toBuilder();
mFromState.ifPresent(folderIconBuilder::setFromLabelState); mFromState.ifPresent(folderIconBuilder::setFromLabelState);
@ -293,8 +284,11 @@ public class StatsLogCompatManager extends StatsLogManager {
return itemInfoBuilder.build(); return itemInfoBuilder.build();
} }
private void write(EventEnum event, InstanceId instanceId, LauncherAtom.ItemInfo atomInfo, @WorkerThread
int srcState, int dstState) { private void write(EventEnum event, LauncherAtom.ItemInfo atomInfo) {
InstanceId instanceId = mInstanceId;
int srcState = mSrcState;
int dstState = mDstState;
if (IS_VERBOSE) { if (IS_VERBOSE) {
String name = (event instanceof Enum) ? ((Enum) event).name() : String name = (event instanceof Enum) ? ((Enum) event).name() :
event.getId() + ""; event.getId() + "";
@ -307,6 +301,10 @@ public class StatsLogCompatManager extends StatsLogManager {
atomInfo)); atomInfo));
} }
for (StatsLogConsumer consumer : LOGS_CONSUMER) {
consumer.consume(event, atomInfo);
}
SysUiStatsLog.write( SysUiStatsLog.write(
SysUiStatsLog.LAUNCHER_EVENT, SysUiStatsLog.LAUNCHER_EVENT,
SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */, SysUiStatsLog.LAUNCHER_UICHANGED__ACTION__DEFAULT_ACTION /* deprecated */,
@ -446,7 +444,16 @@ public class StatsLogCompatManager extends StatsLogManager {
return "ALLAPPS"; return "ALLAPPS";
default: default:
return "INVALID"; return "INVALID";
} }
} }
/**
* Interface to get stats log while it is dispatched to the system
*/
public interface StatsLogConsumer {
@WorkerThread
void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo);
}
} }

View File

@ -45,7 +45,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.InstanceIdSequence; 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.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.touch.ItemClickHandler;
@ -154,8 +153,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
public abstract ActivityOptions getActivityLaunchOptions(View v); public abstract ActivityOptions getActivityLaunchOptions(View v);
public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item, public boolean startActivitySafely(View v, Intent intent, @Nullable ItemInfo item) {
@Nullable String sourceContainer) {
if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) { if (mIsSafeModeEnabled && !PackageManagerHelper.isSystemApp(this, intent)) {
Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show();
return false; return false;
@ -176,17 +174,13 @@ public abstract class BaseDraggingActivity extends BaseActivity
&& !((WorkspaceItemInfo) item).isPromise(); && !((WorkspaceItemInfo) item).isPromise();
if (isShortcut) { if (isShortcut) {
// Shortcuts need some special checks due to legacy reasons. // Shortcuts need some special checks due to legacy reasons.
startShortcutIntentSafely(intent, optsBundle, item, sourceContainer); startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) { } else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity // Could be launching some bookkeeping activity
startActivity(intent, optsBundle); startActivity(intent, optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(),
Process.myUserHandle(), sourceContainer);
} else { } else {
getSystemService(LauncherApps.class).startMainActivity( getSystemService(LauncherApps.class).startMainActivity(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle); intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
AppLaunchTracker.INSTANCE.get(this).onStartApp(intent.getComponent(), user,
sourceContainer);
} }
getUserEventDispatcher().logAppLaunch(v, intent, user); getUserEventDispatcher().logAppLaunch(v, intent, user);
if (item != null) { if (item != null) {
@ -206,8 +200,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
.log(LAUNCHER_APP_LAUNCH_TAP); .log(LAUNCHER_APP_LAUNCH_TAP);
} }
private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info, private void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
@Nullable String sourceContainer) {
try { try {
StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy(); StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
try { try {
@ -221,8 +214,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
String id = ((WorkspaceItemInfo) info).getDeepShortcutId(); String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
String packageName = intent.getPackage(); String packageName = intent.getPackage();
startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user); startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
AppLaunchTracker.INSTANCE.get(this).onStartShortcut(packageName, id, info.user,
sourceContainer);
} else { } else {
// Could be launching some bookkeeping activity // Could be launching some bookkeeping activity
startActivity(intent, optsBundle); startActivity(intent, optsBundle);

View File

@ -814,7 +814,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
if (grantResults.length > 0 if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) { && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startActivitySafely(v, intent, null, null); startActivitySafely(v, intent, null);
} else { } else {
// TODO: Show a snack bar with link to settings // TODO: Show a snack bar with link to settings
Toast.makeText(this, getString(R.string.msg_no_phone_permission, Toast.makeText(this, getString(R.string.msg_no_phone_permission,
@ -1862,13 +1862,12 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
} }
@Override @Override
public boolean startActivitySafely(View v, Intent intent, ItemInfo item, public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
@Nullable String sourceContainer) {
if (!hasBeenResumed()) { if (!hasBeenResumed()) {
// Workaround an issue where the WM launch animation is clobbered when finishing the // Workaround an issue where the WM launch animation is clobbered when finishing the
// recents animation into launcher. Defer launching the activity until Launcher is // recents animation into launcher. Defer launching the activity until Launcher is
// next resumed. // next resumed.
addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer)); addOnResumeCallback(() -> startActivitySafely(v, intent, item));
if (mOnDeferredActivityLaunchCallback != null) { if (mOnDeferredActivityLaunchCallback != null) {
mOnDeferredActivityLaunchCallback.run(); mOnDeferredActivityLaunchCallback.run();
mOnDeferredActivityLaunchCallback = null; mOnDeferredActivityLaunchCallback = null;
@ -1876,7 +1875,7 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
return true; return true;
} }
boolean success = super.startActivitySafely(v, intent, item, sourceContainer); boolean success = super.startActivitySafely(v, intent, item);
if (success && v instanceof BubbleTextView) { if (success && v instanceof BubbleTextView) {
// This is set to the view that launched the activity that navigated the user away // This is set to the view that launched the activity that navigated the user away
// from launcher. Since there is no callback for when the activity has finished // from launcher. Since there is no callback for when the activity has finished

View File

@ -39,7 +39,7 @@ import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.FileLog; import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.LoggerUtils; import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon; import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo; import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@ -218,13 +218,16 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
public void onDrop(DragObject d, DragOptions options) { public void onDrop(DragObject d, DragOptions options) {
// Defer onComplete // Defer onComplete
d.dragSource = new DeferredOnComplete(d.dragSource, getContext()); d.dragSource = new DeferredOnComplete(d.dragSource, getContext());
super.onDrop(d, options); super.onDrop(d, options);
StatsLogger logger = mStatsLogManager.logger().withInstanceId(d.logInstanceId);
if (d.originalDragInfo != null) {
logger.withItemInfo(d.originalDragInfo);
}
if (mCurrentAccessibilityAction == UNINSTALL) { if (mCurrentAccessibilityAction == UNINSTALL) {
mStatsLogManager.logger().withInstanceId(d.logInstanceId) logger.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL);
.log(LAUNCHER_ITEM_DROPPED_ON_UNINSTALL);
} else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) { } else if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
mStatsLogManager.logger().withInstanceId(d.logInstanceId) logger.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST);
.log(LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST);
} }
} }
@ -283,8 +286,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList
return null; return null;
} }
if (mCurrentAccessibilityAction == DISMISS_PREDICTION) { if (mCurrentAccessibilityAction == DISMISS_PREDICTION) {
AppLaunchTracker.INSTANCE.get(getContext()).onDismissApp(info.getTargetComponent(), // We sent the log event, nothing else left to do
info.user, AppLaunchTracker.CONTAINER_PREDICTIONS);
return null; return null;
} }
// else: mCurrentAccessibilityAction == UNINSTALL // else: mCurrentAccessibilityAction == UNINSTALL

View File

@ -41,7 +41,6 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView; import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem; import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageManagerHelper;
@ -270,7 +269,7 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market, View searchMarketView = mLayoutInflater.inflate(R.layout.all_apps_search_market,
parent, false); parent, false);
searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely( searchMarketView.setOnClickListener(v -> mLauncher.startActivitySafely(
v, mMarketSearchIntent, null, AppLaunchTracker.CONTAINER_SEARCH)); v, mMarketSearchIntent, null));
return new ViewHolder(searchMarketView); return new ViewHolder(searchMarketView);
case VIEW_TYPE_ALL_APPS_DIVIDER: case VIEW_TYPE_ALL_APPS_DIVIDER:
return new ViewHolder(mLayoutInflater.inflate( return new ViewHolder(mLayoutInflater.inflate(

View File

@ -28,7 +28,6 @@ import android.widget.TextView.OnEditorActionListener;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ExtendedEditText; import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageManagerHelper;
@ -112,8 +111,8 @@ public class AllAppsSearchBarController
return false; return false;
} }
return mLauncher.startActivitySafely(v, return mLauncher.startActivitySafely(v,
PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null, PackageManagerHelper.getMarketSearchIntent(mLauncher, query), null
AppLaunchTracker.CONTAINER_SEARCH); );
} }
@Override @Override

View File

@ -15,7 +15,6 @@
*/ */
package com.android.launcher3.logging; package com.android.launcher3.logging;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_DOWN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_CLOSE_DOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_OPEN_UP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_OPEN_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@ -23,8 +22,6 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import android.content.Context; import android.content.Context;
import androidx.annotation.Nullable;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.logger.LauncherAtom.ContainerInfo; import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
import com.android.launcher3.logger.LauncherAtom.FromState; import com.android.launcher3.logger.LauncherAtom.FromState;
@ -403,19 +400,6 @@ public class StatsLogManager implements ResourceBasedOverride {
return mgr; return mgr;
} }
/**
* Log an event with ranked-choice information along with package. Does nothing if event.getId()
* <= 0.
*
* @param rankingEvent an enum implementing EventEnum interface.
* @param instanceId An identifier obtained from an InstanceIdSequence.
* @param packageName the package name of the relevant app, if known (null otherwise).
* @param position the position picked.
*/
public void log(EventEnum rankingEvent, InstanceId instanceId, @Nullable String packageName,
int position) {
}
/** /**
* Logs snapshot, or impression of the current workspace. * Logs snapshot, or impression of the current workspace.
*/ */

View File

@ -17,13 +17,7 @@ package com.android.launcher3.model;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import android.content.ComponentName;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.MainThreadInitializedObject; import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride; import com.android.launcher3.util.ResourceBasedOverride;
@ -32,28 +26,8 @@ import com.android.launcher3.util.ResourceBasedOverride;
*/ */
public class AppLaunchTracker implements ResourceBasedOverride { public class AppLaunchTracker implements ResourceBasedOverride {
/**
* Derived from LauncherEvent proto.
* TODO: Use proper descriptive constants
*/
public static final String CONTAINER_DEFAULT = Integer.toString(ContainerType.WORKSPACE);
public static final String CONTAINER_ALL_APPS = Integer.toString(ContainerType.ALLAPPS);
public static final String CONTAINER_PREDICTIONS = Integer.toString(ContainerType.PREDICTION);
public static final String CONTAINER_SEARCH = Integer.toString(ContainerType.SEARCHRESULT);
public static final String CONTAINER_OVERVIEW = Integer.toString(ContainerType.OVERVIEW);
public static final MainThreadInitializedObject<AppLaunchTracker> INSTANCE = public static final MainThreadInitializedObject<AppLaunchTracker> INSTANCE =
forOverride(AppLaunchTracker.class, R.string.app_launch_tracker_class); forOverride(AppLaunchTracker.class, R.string.app_launch_tracker_class);
public void onStartShortcut(String packageName, String shortcutId, UserHandle user,
@Nullable String container) { }
public void onStartApp(ComponentName componentName, UserHandle user,
@Nullable String container) { }
public void onDismissApp(ComponentName componentName, UserHandle user,
@Nullable String container){}
public void onReturnedToHome() { } public void onReturnedToHome() { }
} }

View File

@ -53,6 +53,7 @@ import com.android.launcher3.logger.LauncherAtom.SettingsContainer;
import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer; import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer; import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer;
import com.android.launcher3.model.ModelWriter; import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.ContentWriter;
import java.util.Optional; import java.util.Optional;
@ -285,6 +286,13 @@ public class ItemInfo {
.orElse(LauncherAtom.Application.newBuilder())); .orElse(LauncherAtom.Application.newBuilder()));
break; break;
case ITEM_TYPE_DEEP_SHORTCUT: case ITEM_TYPE_DEEP_SHORTCUT:
itemBuilder
.setShortcut(nullableComponent
.map(component -> LauncherAtom.Shortcut.newBuilder()
.setShortcutName(component.flattenToShortString())
.setShortcutId(ShortcutKey.fromItemInfo(this).getId()))
.orElse(LauncherAtom.Shortcut.newBuilder()));
break;
case ITEM_TYPE_SHORTCUT: case ITEM_TYPE_SHORTCUT:
itemBuilder itemBuilder
.setShortcut(nullableComponent .setShortcut(nullableComponent

View File

@ -174,7 +174,7 @@ public abstract class SystemShortcut<T extends BaseDraggingActivity> extends Ite
public void onClick(View view) { public void onClick(View view) {
Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent( Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
mItemInfo.getTargetComponent().getPackageName()); mItemInfo.getTargetComponent().getPackageName());
mTarget.startActivitySafely(view, intent, mItemInfo, null); mTarget.startActivitySafely(view, intent, mItemInfo);
AbstractFloatingView.closeAllOpenViews(mTarget); AbstractFloatingView.closeAllOpenViews(mTarget);
} }
} }

View File

@ -15,8 +15,6 @@
*/ */
package com.android.launcher3.secondarydisplay; package com.android.launcher3.secondarydisplay;
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.app.ActivityOptions; import android.app.ActivityOptions;
@ -327,7 +325,7 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
if (intent == null) { if (intent == null) {
throw new IllegalArgumentException("Input must have a valid intent"); throw new IllegalArgumentException("Input must have a valid intent");
} }
startActivitySafely(v, intent, item, CONTAINER_ALL_APPS); startActivitySafely(v, intent, item);
} }
} }
} }

View File

@ -18,7 +18,6 @@ package com.android.launcher3.touch;
import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET; import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET;
import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET; import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER;
@ -37,8 +36,6 @@ import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView; import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo;
@ -72,13 +69,9 @@ public class ItemClickHandler {
/** /**
* Instance used for click handling on items * Instance used for click handling on items
*/ */
public static final OnClickListener INSTANCE = getInstance(null); public static final OnClickListener INSTANCE = ItemClickHandler::onClick;
public static final OnClickListener getInstance(String sourceContainer) { private static void onClick(View v) {
return v -> onClick(v, sourceContainer);
}
private static void onClick(View v, String sourceContainer) {
// Make sure that rogue clicks don't get through while allapps is launching, or after the // Make sure that rogue clicks don't get through while allapps is launching, or after the
// view has detached (it's possible for this to happen if the view is removed mid touch). // view has detached (it's possible for this to happen if the view is removed mid touch).
if (v.getWindowToken() == null) return; if (v.getWindowToken() == null) return;
@ -88,14 +81,14 @@ public class ItemClickHandler {
Object tag = v.getTag(); Object tag = v.getTag();
if (tag instanceof WorkspaceItemInfo) { if (tag instanceof WorkspaceItemInfo) {
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher, sourceContainer); onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
} else if (tag instanceof FolderInfo) { } else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) { if (v instanceof FolderIcon) {
onClickFolderIcon(v); onClickFolderIcon(v);
} }
} else if (tag instanceof AppInfo) { } else if (tag instanceof AppInfo) {
startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher, startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer); );
} else if (tag instanceof LauncherAppWidgetInfo) { } else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) { if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher); onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
@ -191,7 +184,7 @@ public class ItemClickHandler {
// Fallback to using custom market intent. // Fallback to using custom market intent.
Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName); Intent intent = new PackageManagerHelper(launcher).getMarketIntent(packageName);
launcher.startActivitySafely(v, intent, item, null); launcher.startActivitySafely(v, intent, item);
} }
/** /**
@ -199,8 +192,7 @@ public class ItemClickHandler {
* *
* @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}. * @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}.
*/ */
public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher, public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher) {
@Nullable String sourceContainer) {
if (shortcut.isDisabled()) { if (shortcut.isDisabled()) {
final int disabledFlags = shortcut.runtimeStatusFlags final int disabledFlags = shortcut.runtimeStatusFlags
& WorkspaceItemInfo.FLAG_DISABLED_MASK; & WorkspaceItemInfo.FLAG_DISABLED_MASK;
@ -241,11 +233,10 @@ public class ItemClickHandler {
} }
// Start activities // Start activities
startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer); startAppShortcutOrInfoActivity(v, shortcut, launcher);
} }
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher, private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
@Nullable String sourceContainer) {
TestLogging.recordEvent( TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity"); TestProtocol.SEQUENCE_MAIN, "start: startAppShortcutOrInfoActivity");
Intent intent; Intent intent;
@ -274,6 +265,6 @@ public class ItemClickHandler {
// Preload the icon to reduce latency b/w swapping the floating view with the original. // Preload the icon to reduce latency b/w swapping the floating view with the original.
FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */); FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
} }
launcher.startActivitySafely(v, intent, item, sourceContainer); launcher.startActivitySafely(v, intent, item);
} }
} }

View File

@ -220,7 +220,7 @@ public class OptionsPopupView extends ArrowPopup
if (!TextUtils.isEmpty(pickerPackage)) { if (!TextUtils.isEmpty(pickerPackage)) {
intent.setPackage(pickerPackage); intent.setPackage(pickerPackage);
} }
return launcher.startActivitySafely(v, intent, dummyInfo(intent), null); return launcher.startActivitySafely(v, intent, dummyInfo(intent));
} }
static WorkspaceItemInfo dummyInfo(Intent intent) { static WorkspaceItemInfo dummyInfo(Intent intent) {

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.plugins;
import android.content.ComponentName;
import android.os.UserHandle;
import com.android.systemui.plugins.annotations.ProvidesInterface;
/**
* Plugin interface which sends app launch events.
*/
@ProvidesInterface(action = AppLaunchEventsPlugin.ACTION, version = AppLaunchEventsPlugin.VERSION)
public interface AppLaunchEventsPlugin extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_APP_EVENTS";
int VERSION = 1;
/**
* Receives onStartShortcut event from
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
*/
void onStartShortcut(String packageName, String shortcutId, UserHandle user, String container);
/**
* Receives onStartApp event from
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
*/
void onStartApp(ComponentName componentName, UserHandle user, String container);
/**
* Receives onDismissApp event from
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
*/
void onDismissApp(ComponentName componentName, UserHandle user, String container);
/**
* Receives onReturnedToHome event from
* {@link com.android.launcher3.appprediction.PredictionAppTracker}.
*/
void onReturnedToHome();
}