Implements LAUNCHER_ITEM_DROP_FOLDER_CREATED event.

When item is dropped on a existing item resulting in new folder creation, triggers LAUNCHER_ITEM_DROP_FOLDER_CREATED event with details of the destination package.
This change also introduces new FolderIcon item to launcher_atom.proto to represent folder icon.

Screencast and sample logs: https://docs.google.com/document/d/1CBP2yTcXdFhPdNG5ZmWFKSgd8mDbMevY-akVlUXPLDo/edit#bookmark=id.tmbucd1f44qp

Bug: 152978018

Change-Id: Ib4d343ba9075aa8853652f128457c4638541ec59
This commit is contained in:
thiruram 2020-05-04 17:49:37 -07:00
parent d13dd3bc44
commit 5a01f0ec51
9 changed files with 96 additions and 35 deletions

View File

@ -26,6 +26,7 @@ message ItemInfo {
Task task = 2; Task task = 2;
Shortcut shortcut = 3; Shortcut shortcut = 3;
Widget widget = 4; Widget widget = 4;
FolderIcon folder_icon = 9;
} }
// When used for launch event, stores the global predictive rank // When used for launch event, stores the global predictive rank
optional int32 rank = 5; optional int32 rank = 5;
@ -92,6 +93,11 @@ message Task {
optional int32 index = 3; optional int32 index = 3;
} }
// Represents folder in a closed state.
message FolderIcon {
optional int32 cardinality = 1;
}
////////////////////////////////////////////// //////////////////////////////////////////////
// Containers // Containers

View File

@ -78,7 +78,7 @@ public interface DropTarget {
public DraggableView originalView = null; public DraggableView originalView = null;
/** Used for matching DROP event with its corresponding DRAG event on the server side. */ /** Used for matching DROP event with its corresponding DRAG event on the server side. */
final InstanceId mLogInstanceId = public final InstanceId logInstanceId =
new InstanceIdSequence(1 << 20 /*InstanceId.INSTANCE_ID_MAX*/) new InstanceIdSequence(1 << 20 /*InstanceId.INSTANCE_ID_MAX*/)
.newInstanceId(); .newInstanceId();

View File

@ -416,8 +416,12 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
mLauncher.getStateManager().goToState(SPRING_LOADED); mLauncher.getStateManager().goToState(SPRING_LOADED);
mStatsLogManager.log( mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED, LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED,
dragObject.mLogInstanceId, dragObject.logInstanceId,
dragObject.originalDragInfo.buildProto(null)); dragObject.originalDragInfo.buildProto(
dragObject.dragSource instanceof Folder
? ((Folder) dragObject.dragSource).mInfo
: null)
);
} }
public void deferRemoveExtraEmptyScreen() { public void deferRemoveExtraEmptyScreen() {
@ -1645,7 +1649,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
Rect folderLocation = new Rect(); Rect folderLocation = new Rect();
float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation); float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
target.removeView(v); target.removeView(v);
mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED,
d.logInstanceId,
destInfo.buildProto(null));
FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0], FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0],
targetCell[1]); targetCell[1]);
destInfo.cellX = -1; destInfo.cellX = -1;
@ -1683,6 +1690,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
if (dropOverView instanceof FolderIcon) { if (dropOverView instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) dropOverView; FolderIcon fi = (FolderIcon) dropOverView;
if (fi.acceptDrop(d.dragInfo)) { if (fi.acceptDrop(d.dragInfo)) {
mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
d.logInstanceId,
fi.mInfo.buildProto(null));
fi.onDrop(d, false /* itemReturnedOnFailedDrop */); fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
// if the drag started here, we need to remove it from the workspace // if the drag started here, we need to remove it from the workspace
@ -1885,15 +1896,15 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
mLauncher.getStateManager().goToState( mLauncher.getStateManager().goToState(
NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable); NORMAL, SPRING_LOADED_EXIT_DELAY, onCompleteRunnable);
mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
d.logInstanceId,
d.dragInfo.buildProto(null));
} }
if (d.stateAnnouncer != null && !droppedOnOriginalCell) { if (d.stateAnnouncer != null && !droppedOnOriginalCell) {
d.stateAnnouncer.completeAction(R.string.item_moved); d.stateAnnouncer.completeAction(R.string.item_moved);
} }
mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
d.mLogInstanceId,
d.dragInfo.buildProto(null));
} }
public void onNoCellFound(View dropTargetLayout) { public void onNoCellFound(View dropTargetLayout) {
@ -2515,6 +2526,10 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
resetTransitionTransform(); resetTransitionTransform();
} }
} }
mStatsLogManager.log(
LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
d.logInstanceId,
d.dragInfo.buildProto(null));
} }
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) { public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {

View File

@ -186,8 +186,7 @@ public class DragController implements DragDriver.EventListener, TouchController
mDragObject.dragSource = source; mDragObject.dragSource = source;
mDragObject.dragInfo = dragInfo; mDragObject.dragInfo = dragInfo;
mDragObject.originalDragInfo = new ItemInfo(); mDragObject.originalDragInfo = mDragObject.dragInfo.makeShallowCopy();
mDragObject.originalDragInfo.copyFrom(dragInfo);
if (dragOffset != null) { if (dragOffset != null) {
dragView.setDragVisualizeOffset(new Point(dragOffset)); dragView.setDragVisualizeOffset(new Point(dragOffset));

View File

@ -87,6 +87,7 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener; import com.android.launcher3.model.data.FolderInfo.FolderListener;
@ -1346,6 +1347,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
if (d.stateAnnouncer != null) { if (d.stateAnnouncer != null) {
d.stateAnnouncer.completeAction(R.string.item_moved); d.stateAnnouncer.completeAction(R.string.item_moved);
} }
StatsLogManager.newInstance(getContext())
.log(StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED,
d.logInstanceId,
d.dragInfo.buildProto(mInfo));
} }
// This is used so the item doesn't immediately appear in the folder when added. In one case // This is used so the item doesn't immediately appear in the folder when added. In one case

View File

@ -85,7 +85,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
@Thunk ActivityContext mActivity; @Thunk ActivityContext mActivity;
@Thunk Folder mFolder; @Thunk Folder mFolder;
private FolderInfo mInfo; public FolderInfo mInfo;
private CheckLongPressHelper mLongPressHelper; private CheckLongPressHelper mLongPressHelper;

View File

@ -47,7 +47,10 @@ public class StatsLogManager implements ResourceBasedOverride {
@LauncherUiEvent(doc = "User dragged a launcher item") @LauncherUiEvent(doc = "User dragged a launcher item")
LAUNCHER_ITEM_DRAG_STARTED(383), LAUNCHER_ITEM_DRAG_STARTED(383),
@LauncherUiEvent(doc = "A dragged launcher item is successfully dropped") @LauncherUiEvent(doc = "A dragged launcher item is successfully dropped")
LAUNCHER_ITEM_DROP_COMPLETED(385); LAUNCHER_ITEM_DROP_COMPLETED(385),
@LauncherUiEvent(doc = "A dragged launcher item is successfully dropped on another item "
+ "resulting in new folder creation")
LAUNCHER_ITEM_DROP_FOLDER_CREATED(386);
// ADD MORE // ADD MORE
private final int mId; private final int mId;

View File

@ -21,6 +21,7 @@ import android.os.Process;
import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.model.ModelWriter; import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.util.ContentWriter; import com.android.launcher3.util.ContentWriter;
@ -155,4 +156,20 @@ public class FolderInfo extends ItemInfo {
return super.dumpProperties() return super.dumpProperties()
+ " manuallyTypedTitle=" + hasOption(FLAG_MANUAL_FOLDER_NAME); + " manuallyTypedTitle=" + hasOption(FLAG_MANUAL_FOLDER_NAME);
} }
@Override
public LauncherAtom.ItemInfo buildProto(FolderInfo fInfo) {
return getDefaultItemInfoBuilder()
.setFolderIcon(LauncherAtom.FolderIcon.newBuilder().setCardinality(contents.size()))
.setContainerInfo(getContainerInfo())
.build();
}
@Override
public ItemInfo makeShallowCopy() {
FolderInfo folderInfo = new FolderInfo();
folderInfo.copyFrom(this);
folderInfo.contents = this.contents;
return folderInfo;
}
} }

View File

@ -253,8 +253,7 @@ public class ItemInfo {
* Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info. * Creates {@link LauncherAtom.ItemInfo} with important fields and parent container info.
*/ */
public LauncherAtom.ItemInfo buildProto(FolderInfo fInfo) { public LauncherAtom.ItemInfo buildProto(FolderInfo fInfo) {
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder(); LauncherAtom.ItemInfo.Builder itemBuilder = getDefaultItemInfoBuilder();
itemBuilder.setIsWork(user != Process.myUserHandle());
Optional<ComponentName> nullableComponent = Optional.ofNullable(getTargetComponent()); Optional<ComponentName> nullableComponent = Optional.ofNullable(getTargetComponent());
switch (itemType) { switch (itemType) {
case ITEM_TYPE_APPLICATION: case ITEM_TYPE_APPLICATION:
@ -305,28 +304,45 @@ public class ItemInfo {
} }
itemBuilder.setContainerInfo(ContainerInfo.newBuilder().setFolder(folderBuilder)); itemBuilder.setContainerInfo(ContainerInfo.newBuilder().setFolder(folderBuilder));
} else { } else {
switch (container) { itemBuilder.setContainerInfo(getContainerInfo());
case CONTAINER_HOTSEAT:
case CONTAINER_HOTSEAT_PREDICTION:
itemBuilder.setContainerInfo(
ContainerInfo.newBuilder().setHotseat(
LauncherAtom.HotseatContainer.newBuilder().setIndex(screenId)));
break;
case CONTAINER_DESKTOP:
itemBuilder.setContainerInfo(
ContainerInfo.newBuilder().setWorkspace(
LauncherAtom.WorkspaceContainer.newBuilder()
.setGridX(cellX)
.setGridY(cellY)
.setPageIndex(screenId)));
break;
case CONTAINER_ALL_APPS:
itemBuilder.setContainerInfo(
ContainerInfo.newBuilder().setAllAppsContainer(
AllAppsContainer.getDefaultInstance()));
break;
}
} }
return itemBuilder.build(); return itemBuilder.build();
} }
LauncherAtom.ItemInfo.Builder getDefaultItemInfoBuilder() {
LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
itemBuilder.setIsWork(user != Process.myUserHandle());
return itemBuilder;
}
ContainerInfo getContainerInfo() {
switch (container) {
case CONTAINER_HOTSEAT:
case CONTAINER_HOTSEAT_PREDICTION:
return ContainerInfo.newBuilder()
.setHotseat(LauncherAtom.HotseatContainer.newBuilder().setIndex(screenId))
.build();
case CONTAINER_DESKTOP:
return ContainerInfo.newBuilder()
.setWorkspace(
LauncherAtom.WorkspaceContainer.newBuilder()
.setGridX(cellX)
.setGridY(cellY)
.setPageIndex(screenId))
.build();
case CONTAINER_ALL_APPS:
return ContainerInfo.newBuilder()
.setAllAppsContainer(
AllAppsContainer.getDefaultInstance())
.build();
}
return ContainerInfo.getDefaultInstance();
}
/** Returns shallow copy of the object. */
public ItemInfo makeShallowCopy() {
ItemInfo itemInfo = new ItemInfo();
itemInfo.copyFrom(this);
return itemInfo;
}
} }