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:
parent
514dfa2deb
commit
7ac0ef1cb1
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue