ItemInfo supports lite proto builder (1/n)

Bug: 144953948
Bug: 137777105

The new lite proto builder is used to send two types of logging to statsd
1) Snapshot logging
2) App launch, task launch, task dismiss

Statsd will be connected once platform CL is submitted

Change-Id: If606cee5288fe4bd6c522605ae84eb0f24174f5b
This commit is contained in:
Hyunyoung Song 2020-03-26 01:48:24 -07:00
parent 514dfa2deb
commit 7ac0ef1cb1
11 changed files with 343 additions and 221 deletions

108
protos/launcher_atom.proto Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2020 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.
*/
syntax = "proto2";
option java_package = "com.android.launcher3.logger";
option java_outer_classname = "LauncherAtom";
//
// ItemInfos
message ItemInfo {
oneof Item {
Application application = 1;
Task task= 2;
Shortcut shortcut = 3;
Widget widget = 4;
}
// When used for launch event, stores the global predictive rank
optional int32 rank = 5;
// Stores whether the Item belows to non primary user
optional bool is_work = 6;
// Item can be child node to parent container or parent containers (nested)
oneof Container {
WorkspaceContainer workspace = 7;
HotseatContainer hotseat = 8;
FolderContainer folder = 9;
}
// Stores the origin of the Item
optional Origin source = 10;
}
enum Origin {
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
BACKUP_RESTORE = 2; // icon layout restored from backup
PINITEM = 3; // from another app (e.g., Chrome's "Add to Home screen")
ALLAPPS_ATOZ = 4; // within launcher surface, all aps a-z
WIDGETS = 5; // within launcher, widgets tray
ADD_TO_HOMESCREEN = 6; // play install + launcher home setting
ALLAPPS_PREDICTION = 7; // from prediction bar in all apps container
HOTSEAT_PREDICTION = 8; // from prediction bar in hotseat container
}
// Main app icons
message Application {
optional string package_name = 1;
optional string component_name = 2;
}
// Legacy shortcuts and shortcuts handled by ShortcutManager
message Shortcut {
optional string shortcut_name = 1;
}
// AppWidgets handled by AppWidgetManager
message Widget {
optional int32 span_x = 1;
optional int32 span_y = 2;
optional int32 app_widget_id = 3;
optional string package_name = 4; // only populated during snapshot if from workspace
optional string component_name = 5; // only populated during snapshot if from workspace
}
// Tasks handled by PackageManager
message Task {
optional string package_name = 1;
optional string component_name = 2;
optional int32 index = 3;
}
//////////////////////////////////////////////
// Containers
message WorkspaceContainer {
optional int32 page_index = 1; // range [-1, l], 0 is the index of the main homescreen
optional int32 grid_x = 2; // [0, m], m varies based on the display density and resolution
optional int32 grid_y = 3; // [0, n], n varies based on the display density and resolution
}
message HotseatContainer {
optional int32 index = 1;
}
message FolderContainer {
optional int32 page_index = 1;
optional int32 grid_x = 2;
optional int32 grid_y = 3;
oneof Container {
WorkspaceContainer workspace = 4;
HotseatContainer hotseat = 5;
}
}

View File

@ -30,6 +30,8 @@ import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
@ -1183,13 +1185,13 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
verticalFactor * secondaryTaskDimension).setDuration(duration), LINEAR, sp);
}
private void removeTask(Task task, int index, EndState endState) {
if (task != null) {
ActivityManagerWrapper.getInstance().removeTask(task.key.id);
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
private void removeTask(TaskView taskView, int index, EndState endState) {
if (taskView.getTask() != null) {
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key);
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
endState.logAction, Direction.UP, index, componentKey);
mActivity.getStatsLogManager().logTaskDismiss(this, componentKey);
endState.logAction, Direction.UP, index, compKey);
mActivity.getStatsLogManager().log(TASK_DISMISS_SWIPE_UP, taskView.buildProto());
}
}
@ -1284,7 +1286,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private void onEnd(EndState endState) {
if (endState.isSuccess) {
if (shouldRemoveTask) {
removeTask(taskView.getTask(), draggedIndex, endState);
removeTask(taskView, draggedIndex, endState);
}
int pageToSnapTo = mCurrentPage;
@ -1733,6 +1735,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
endState.logAction, Direction.DOWN, indexOfChild(tv),
TaskUtils.getLaunchComponentKeyForTask(task.key));
mActivity.getStatsLogManager().log(TASK_LAUNCH_SWIPE_DOWN, tv.buildProto()
);
}
} else {
onTaskLaunched(false);

View File

@ -29,6 +29,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.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_TAP;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@ -43,6 +44,7 @@ import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Process;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.Log;
@ -59,6 +61,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.states.RotationHelper;
@ -68,6 +71,7 @@ import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ViewPool.Reusable;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
@ -217,8 +221,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
mActivity.getStatsLogManager().logTaskLaunch(getRecentsView(),
TaskUtils.getLaunchComponentKeyForTask(getTask().key));
mActivity.getStatsLogManager().log(TASK_LAUNCH_TAP, buildProto());
});
mCornerRadius = TaskCornerRadius.get(context);
mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
@ -229,6 +232,17 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
setOutlineProvider(mOutlineProvider);
}
/* Builds proto for logging */
protected LauncherAtom.ItemInfo buildProto() {
ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(getTask().key);
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(componentKey.user != Process.myUserHandle());
itemBuilder.setTask(LauncherAtom.Task.newBuilder()
.setComponentName(componentKey.componentName.flattenToShortString())
.setIndex(getRecentsView().indexOfChild(this)));
return itemBuilder.build();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();

View File

@ -18,36 +18,22 @@ package com.android.quickstep.logging;
import static android.stats.launcher.nano.Launcher.ALLAPPS;
import static android.stats.launcher.nano.Launcher.BACKGROUND;
import static android.stats.launcher.nano.Launcher.DISMISS_TASK;
import static android.stats.launcher.nano.Launcher.HOME;
import static android.stats.launcher.nano.Launcher.LAUNCH_APP;
import static android.stats.launcher.nano.Launcher.LAUNCH_TASK;
import static android.stats.launcher.nano.Launcher.OVERVIEW;
import static com.android.launcher3.logging.UserEventDispatcher.makeTargetsList;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.stats.launcher.nano.Launcher;
import android.stats.launcher.nano.LauncherExtension;
import android.stats.launcher.nano.LauncherTarget;
import android.util.Log;
import android.view.View;
import androidx.annotation.Nullable;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogUtils;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ComponentKey;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.google.protobuf.nano.MessageNano;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.util.IntSparseArrayMap;
import java.util.ArrayList;
@ -62,186 +48,17 @@ import java.util.ArrayList;
public class StatsLogCompatManager extends StatsLogManager {
private static final int SUPPORTED_TARGET_DEPTH = 2;
private static final String TAG = "StatsLogCompatManager";
private static final String TAG = "StatsLog";
private static final boolean DEBUG = false;
private static Context sContext;
public StatsLogCompatManager(Context context) {
sContext = context;
}
@Override
public void logAppLaunch(View v, Intent intent, @Nullable UserHandle userHandle) {
LauncherExtension ext = new LauncherExtension();
ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
int srcState = mStateProvider.getCurrentState();
fillInLauncherExtension(v, ext);
if (ext.srcTarget[0] != null) {
ext.srcTarget[0].item = LauncherTarget.APP_ICON;
}
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, LAUNCH_APP, srcState,
BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
}
@Override
public void logTaskLaunch(View v, ComponentKey componentKey) {
LauncherExtension ext = new LauncherExtension();
ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
int srcState = OVERVIEW;
fillInLauncherExtension(v, ext);
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, LAUNCH_TASK, srcState,
BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
}
@Override
public void logTaskDismiss(View v, ComponentKey componentKey) {
LauncherExtension ext = new LauncherExtension();
ext.srcTarget = new LauncherTarget[SUPPORTED_TARGET_DEPTH];
int srcState = OVERVIEW;
fillInLauncherExtension(v, ext);
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, DISMISS_TASK, srcState,
BACKGROUND /* dstState */, MessageNano.toByteArray(ext), true);
}
@Override
public void logSwipeOnContainer(boolean isSwipingToLeft, int pageId) {
LauncherExtension ext = new LauncherExtension();
ext.srcTarget = new LauncherTarget[1];
int srcState = mStateProvider.getCurrentState();
fillInLauncherExtensionWithPageId(ext, pageId);
int launcherAction = isSwipingToLeft ? Launcher.SWIPE_LEFT : Launcher.SWIPE_RIGHT;
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_EVENT, launcherAction, srcState, srcState,
MessageNano.toByteArray(ext), true);
}
public static boolean fillInLauncherExtension(View v, LauncherExtension extension) {
if (DEBUG) {
Log.d(TAG, "fillInLauncherExtension");
}
StatsLogUtils.LogContainerProvider provider = StatsLogUtils.getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || provider == null) {
if (DEBUG) {
Log.d(TAG, "View or provider is null, or view doesn't have an ItemInfo tag.");
}
return false;
}
Target child = new Target();
ArrayList<Target> targets = makeTargetsList(child);
targets.add(child);
provider.fillInLogContainerData((ItemInfo) v.getTag(), child, targets);
int maxDepth = Math.min(SUPPORTED_TARGET_DEPTH, targets.size());
extension.srcTarget = new LauncherTarget[maxDepth];
for (int i = 0; i < maxDepth; i++) {
extension.srcTarget[i] = new LauncherTarget();
copy(targets.get(i), extension.srcTarget[i]);
}
return true;
}
public static boolean fillInLauncherExtensionWithPageId(LauncherExtension ext, int pageId) {
if (DEBUG) {
Log.d(TAG, "fillInLauncherExtensionWithPageId, pageId = " + pageId);
}
Target target = new Target();
target.pageIndex = pageId;
ext.srcTarget[0] = new LauncherTarget();
copy(target, ext.srcTarget[0]);
return true;
}
private static void copy(Target src, LauncherTarget dst) {
if (DEBUG) {
Log.d(TAG, "copy target information from clearcut Target to LauncherTarget.");
}
// Fill in type
switch (src.type) {
case Target.Type.ITEM:
dst.type = LauncherTarget.ITEM_TYPE;
break;
case Target.Type.CONTROL:
dst.type = LauncherTarget.CONTROL_TYPE;
break;
case Target.Type.CONTAINER:
dst.type = LauncherTarget.CONTAINER_TYPE;
break;
default:
dst.type = LauncherTarget.NONE;
break;
}
// Fill in item
switch (src.itemType) {
case ItemType.APP_ICON:
dst.item = LauncherTarget.APP_ICON;
break;
case ItemType.SHORTCUT:
dst.item = LauncherTarget.SHORTCUT;
break;
case ItemType.WIDGET:
dst.item = LauncherTarget.WIDGET;
break;
case ItemType.FOLDER_ICON:
dst.item = LauncherTarget.FOLDER_ICON;
break;
case ItemType.DEEPSHORTCUT:
dst.item = LauncherTarget.DEEPSHORTCUT;
break;
case ItemType.SEARCHBOX:
dst.item = LauncherTarget.SEARCHBOX;
break;
case ItemType.EDITTEXT:
dst.item = LauncherTarget.EDITTEXT;
break;
case ItemType.NOTIFICATION:
dst.item = LauncherTarget.NOTIFICATION;
break;
case ItemType.TASK:
dst.item = LauncherTarget.TASK;
break;
default:
dst.item = LauncherTarget.DEFAULT_ITEM;
break;
}
// Fill in container
switch (src.containerType) {
case ContainerType.HOTSEAT:
dst.container = LauncherTarget.HOTSEAT;
break;
case ContainerType.FOLDER:
dst.container = LauncherTarget.FOLDER;
break;
case ContainerType.PREDICTION:
dst.container = LauncherTarget.PREDICTION;
break;
case ContainerType.SEARCHRESULT:
dst.container = LauncherTarget.SEARCHRESULT;
break;
default:
dst.container = LauncherTarget.DEFAULT_CONTAINER;
break;
}
// Fill in control
switch (src.controlType) {
case ControlType.UNINSTALL_TARGET:
dst.control = LauncherTarget.UNINSTALL;
break;
case ControlType.REMOVE_TARGET:
dst.control = LauncherTarget.REMOVE;
break;
default:
dst.control = LauncherTarget.DEFAULT_CONTROL;
break;
}
// Fill in other fields
dst.pageId = src.pageIndex;
dst.gridX = src.gridX;
dst.gridY = src.gridY;
public void log(LauncherEvent eventId, LauncherAtom.ItemInfo item) {
// Call StatsLog method
}
@Override
@ -254,4 +71,36 @@ public class StatsLogCompatManager extends StatsLogManager {
"StatsLogUtil constants doesn't match enums in launcher.proto");
}
}
/**
* Logs the workspace layout information on the model thread.
*/
public void logSnapshot() {
LauncherAppState.getInstance(sContext).getModel().enqueueModelUpdateTask(
new SnapshotWorker());
}
private class SnapshotWorker extends BaseModelUpdateTask {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
IntSparseArrayMap<FolderInfo> folders = dataModel.folders.clone();
ArrayList<ItemInfo> workspaceItems = (ArrayList) dataModel.workspaceItems.clone();
ArrayList<LauncherAppWidgetInfo> appWidgets = (ArrayList) dataModel.appWidgets.clone();
for (ItemInfo info : workspaceItems) {
LauncherAtom.ItemInfo atomInfo = info.buildProto(null, null);
// call StatsLog method
}
for (FolderInfo fInfo : folders) {
for (ItemInfo info : fInfo.contents) {
LauncherAtom.ItemInfo atomInfo = info.buildProto(null, fInfo);
// call StatsLog method
}
}
for (ItemInfo info : appWidgets) {
LauncherAtom.ItemInfo atomInfo = info.buildProto(null, null);
// call StatsLog method
}
}
}
}

View File

@ -16,6 +16,7 @@
package com.android.launcher3;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.APP_LAUNCH_TAP;
import static com.android.launcher3.util.DefaultDisplay.CHANGE_ROTATION;
import android.app.ActivityOptions;
@ -181,7 +182,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
sourceContainer);
}
getUserEventDispatcher().logAppLaunch(v, intent, user);
getStatsLogManager().logAppLaunch(v, intent, user);
getStatsLogManager().log(APP_LAUNCH_TAP, item.buildProto(null, null));
return true;
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();

View File

@ -16,6 +16,13 @@
package com.android.launcher3;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Intent;
@ -24,13 +31,17 @@ import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.ContentWriter;
/**
* Represents an item in the launcher.
*/
public class ItemInfo {
public static final boolean DEBUG = true;
public static final int NO_ID = -1;
/**
@ -190,6 +201,7 @@ public class ItemInfo {
return "id=" + id
+ " type=" + LauncherSettings.Favorites.itemTypeToString(itemType)
+ " container=" + LauncherSettings.Favorites.containerToString((int)container)
+ " targetComponent=" + getTargetComponent()
+ " screen=" + screenId
+ " cell(" + cellX + "," + cellY + ")"
+ " span(" + spanX + "," + spanY + ")"
@ -221,4 +233,70 @@ public class ItemInfo {
return container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION
|| container == LauncherSettings.Favorites.CONTAINER_PREDICTION;
}
/**
* Can be overridden by inherited classes to fill in {@link LauncherAtom.ItemInfo}
*/
public void setItemBuilder(LauncherAtom.ItemInfo.Builder builder) {
}
/**
* Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
*/
public LauncherAtom.ItemInfo buildProto(Intent intent, FolderInfo fInfo) {
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(user != Process.myUserHandle());
ComponentName cn = getTargetComponent();
switch (itemType) {
case ITEM_TYPE_APPLICATION:
itemBuilder.setApplication(LauncherAtom.Application.newBuilder()
.setComponentName(cn.flattenToShortString())
.setPackageName(cn.getPackageName()));
break;
case ITEM_TYPE_DEEP_SHORTCUT:
case ITEM_TYPE_SHORTCUT:
itemBuilder.setShortcut(LauncherAtom.Shortcut.newBuilder()
.setShortcutName(cn.flattenToShortString()));
break;
case ITEM_TYPE_APPWIDGET:
setItemBuilder(itemBuilder);
break;
default:
break;
}
if (fInfo != null) {
LauncherAtom.FolderContainer.Builder folderBuilder =
LauncherAtom.FolderContainer.newBuilder();
folderBuilder.setGridX(cellX).setGridY(cellY).setPageIndex(screenId);
switch (fInfo.container) {
case CONTAINER_HOTSEAT:
folderBuilder.setHotseat(LauncherAtom.HotseatContainer.newBuilder()
.setIndex(fInfo.screenId));
break;
case CONTAINER_DESKTOP:
folderBuilder.setWorkspace(LauncherAtom.WorkspaceContainer.newBuilder()
.setPageIndex(fInfo.screenId)
.setGridX(fInfo.cellX).setGridY(fInfo.cellY));
break;
}
itemBuilder.setFolder(folderBuilder);
} else {
switch (container) {
case CONTAINER_HOTSEAT:
itemBuilder.setHotseat(LauncherAtom.HotseatContainer.newBuilder()
.setIndex(screenId));
break;
case CONTAINER_DESKTOP:
itemBuilder.setWorkspace(LauncherAtom.WorkspaceContainer.newBuilder()
.setGridX(cellX)
.setGridY(cellY)
.setPageIndex(screenId));
break;
}
}
return itemBuilder.build();
}
}

View File

@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Intent;
import android.os.Process;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.util.ContentWriter;
@ -162,7 +163,9 @@ public class LauncherAppWidgetInfo extends ItemInfo {
@Override
protected String dumpProperties() {
return super.dumpProperties() + " appWidgetId=" + appWidgetId;
return super.dumpProperties()
+ " providerName=" + providerName
+ " appWidgetId=" + appWidgetId;
}
public final boolean isWidgetIdAllocated() {
@ -182,4 +185,13 @@ public class LauncherAppWidgetInfo extends ItemInfo {
public final boolean hasOptionFlag(int option) {
return (options & option) != 0;
}
@Override
public void setItemBuilder(LauncherAtom.ItemInfo.Builder builder) {
builder.setWidget(LauncherAtom.Widget.newBuilder()
.setSpanX(spanX)
.setSpanY(spanY)
.setComponentName(providerName.toString())
.setPackageName(providerName.getPackageName()));
}
}

View File

@ -991,7 +991,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
if (!mOverlayShown) {
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
Action.Direction.LEFT, ContainerType.WORKSPACE, 0);
mLauncher.getStatsLogManager().logSwipeOnContainer(true, 0);
}
mOverlayShown = true;
// Not announcing the overlay page for accessibility since it announces itself.
@ -1001,7 +1000,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
if (!ued.isPreviousHomeGesture()) {
mLauncher.getUserEventDispatcher().logActionOnContainer(Action.Touch.SWIPE,
Action.Direction.RIGHT, ContainerType.WORKSPACE, -1);
mLauncher.getStatsLogManager().logSwipeOnContainer(false, -1);
}
} else if (Float.compare(mOverlayTranslation, 0f) != 0) {
// When arriving to 0 overscroll from non-zero overscroll, announce page for

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 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.launcher3.logging;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(SOURCE)
@Target(FIELD)
public @interface LauncherUiEvent {
/** An explanation, suitable for Android analysts, of the UI event that this log represents. */
String doc();
}

View File

@ -16,23 +16,44 @@
package com.android.launcher3.logging;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.view.View;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.ItemInfo;
import com.android.launcher3.logging.StatsLogUtils.LogStateProvider;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ResourceBasedOverride;
/**
* Handles the user event logging in Q.
* Handles the user event logging in R+.
*/
public class StatsLogManager implements ResourceBasedOverride {
interface EventEnum {
int getId();
}
public enum LauncherEvent implements EventEnum {
@LauncherUiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
APP_LAUNCH_TAP(1),
@LauncherUiEvent(doc = "Task launched from overview using TAP")
TASK_LAUNCH_TAP(2),
@LauncherUiEvent(doc = "Task launched from overview using SWIPE DOWN")
TASK_LAUNCH_SWIPE_DOWN(2),
@LauncherUiEvent(doc = "TASK dismissed from overview using SWIPE UP")
TASK_DISMISS_SWIPE_UP(3);
// ADD MORE
private final int mId;
LauncherEvent(int id) {
mId = id;
}
public int getId() {
return mId;
}
}
protected LogStateProvider mStateProvider;
public static StatsLogManager newInstance(Context context, LogStateProvider stateProvider) {
StatsLogManager mgr = Overrides.getObject(StatsLogManager.class,
context.getApplicationContext(), R.string.stats_log_manager_class);
@ -42,11 +63,14 @@ public class StatsLogManager implements ResourceBasedOverride {
}
/**
* Logs app launches
* Logs an event and accompanying {@link ItemInfo}
*/
public void logAppLaunch(View v, Intent intent, @Nullable UserHandle userHandle) { }
public void logTaskLaunch(View v, ComponentKey key) { }
public void logTaskDismiss(View v, ComponentKey key) { }
public void logSwipeOnContainer(boolean isSwipingToLeft, int pageId) { }
public void log(LauncherEvent eventId, LauncherAtom.ItemInfo itemInfo) { }
/**
* Logs snapshot, or impression of the current workspace.
*/
public void logSnapshot() { }
public void verify() {} // TODO: should move into robo tests
}

View File

@ -35,6 +35,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.LongSparseArray;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.AppInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
@ -150,8 +152,10 @@ public class LoaderCursor extends CursorWrapper {
}
}
@VisibleForTesting
public WorkspaceItemInfo loadSimpleWorkspaceItem() {
final WorkspaceItemInfo info = new WorkspaceItemInfo();
info.intent = new Intent();
// Non-app shortcuts are only supported for current user.
info.user = user;
info.itemType = itemType;