From 1acaeb5b664c8e11cd85d6f75ae259f1f6f98b6c Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 11 Aug 2021 22:11:20 -0700 Subject: [PATCH] Add logging for app drag and drop - Allow source to specify an instance id for the drag instance (we'll create one otherwise if not specified) - Log start/drop/end as per go/dragdrop_splitscreen_logging Bug: 191686897 Test: statsd_testdrive -terse 90 Change-Id: I215208777e3627859079abac90520b1772478c5e --- .../java/android/content/ClipDescription.java | 10 ++ .../draganddrop/DragAndDropController.java | 13 +- .../draganddrop/DragAndDropEventLogger.java | 131 ++++++++++++++++++ .../systemui/wmshell/WMShellBaseModule.java | 4 +- 4 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java index f49362e9300e8..2ecd71bc1f06b 100644 --- a/core/java/android/content/ClipDescription.java +++ b/core/java/android/content/ClipDescription.java @@ -124,6 +124,16 @@ public class ClipDescription implements Parcelable { */ public static final String EXTRA_ACTIVITY_OPTIONS = "android.intent.extra.ACTIVITY_OPTIONS"; + /** + * An instance id used for logging. + *

+ * Type: {@link com.android.internal.logging.InstanceId} + *

+ * @hide + */ + public static final String EXTRA_LOGGING_INSTANCE_ID = + "android.intent.extra.LOGGING_INSTANCE_ID"; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 58bf22ad29b2f..d8a7f61d26158 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -34,6 +34,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; +import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.res.Configuration; @@ -48,6 +49,7 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; +import com.android.internal.logging.UiEventLogger; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; @@ -67,14 +69,17 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange private final Context mContext; private final DisplayController mDisplayController; + private final DragAndDropEventLogger mLogger; private SplitScreenController mSplitScreen; private final SparseArray mDisplayDropTargets = new SparseArray<>(); private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); - public DragAndDropController(Context context, DisplayController displayController) { + public DragAndDropController(Context context, DisplayController displayController, + UiEventLogger uiEventLogger) { mContext = context; mDisplayController = displayController; + mLogger = new DragAndDropEventLogger(uiEventLogger); } public void initialize(Optional splitscreen) { @@ -179,6 +184,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId), event.getClipData()); setDropTargetWindowVisibility(pd, View.VISIBLE); + mLogger.logStart(event); break; case ACTION_DRAG_ENTERED: pd.dragLayout.show(); @@ -198,7 +204,9 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange case ACTION_DRAG_ENDED: // TODO(b/169894807): Ensure sure it's not possible to get ENDED without DROP // or EXITED - if (!pd.dragLayout.hasDropped()) { + if (pd.dragLayout.hasDropped()) { + mLogger.logDrop(); + } else { pd.activeDragCount--; pd.dragLayout.hide(event, () -> { if (pd.activeDragCount == 0) { @@ -208,6 +216,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange } }); } + mLogger.logEnd(); break; } return true; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java new file mode 100644 index 0000000000000..2d3f395bb8eb3 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropEventLogger.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2021 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.wm.shell.draganddrop; + +import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; +import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; +import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; + +import android.content.ClipData; +import android.content.ClipDescription; +import android.content.pm.ActivityInfo; +import android.view.DragEvent; + +import com.android.internal.logging.InstanceId; +import com.android.internal.logging.InstanceIdSequence; +import com.android.internal.logging.UiEvent; +import com.android.internal.logging.UiEventLogger; + +/** + * Helper class that to log Drag & Drop UIEvents for a single session, see also go/uievent + */ +public class DragAndDropEventLogger { + + private final UiEventLogger mUiEventLogger; + // Used to generate instance ids for this drag if one is not provided + private final InstanceIdSequence mIdSequence; + + // Tracks the current drag session + private ActivityInfo mActivityInfo; + private InstanceId mInstanceId; + + public DragAndDropEventLogger(UiEventLogger uiEventLogger) { + mUiEventLogger = uiEventLogger; + mIdSequence = new InstanceIdSequence(Integer.MAX_VALUE); + } + + /** + * Logs the start of a drag. + */ + public void logStart(DragEvent event) { + final ClipDescription description = event.getClipDescription(); + final ClipData data = event.getClipData(); + final ClipData.Item item = data.getItemAt(0); + mInstanceId = item.getIntent().getParcelableExtra( + ClipDescription.EXTRA_LOGGING_INSTANCE_ID); + if (mInstanceId == null) { + mInstanceId = mIdSequence.newInstanceId(); + } + mActivityInfo = item.getActivityInfo(); + mUiEventLogger.logWithInstanceId(getStartEnum(description), + mActivityInfo.applicationInfo.uid, + mActivityInfo.applicationInfo.packageName, mInstanceId); + } + + /** + * Logs a successful drop. + */ + public void logDrop() { + mUiEventLogger.logWithInstanceId(DragAndDropUiEventEnum.GLOBAL_APP_DRAG_DROPPED, + mActivityInfo.applicationInfo.uid, + mActivityInfo.applicationInfo.packageName, mInstanceId); + } + + /** + * Logs the end of a drag. + */ + public void logEnd() { + mUiEventLogger.logWithInstanceId(DragAndDropUiEventEnum.GLOBAL_APP_DRAG_END, + mActivityInfo.applicationInfo.uid, + mActivityInfo.applicationInfo.packageName, mInstanceId); + } + + /** + * Returns the start logging enum for the given drag description. + */ + private DragAndDropUiEventEnum getStartEnum(ClipDescription description) { + if (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY)) { + return DragAndDropUiEventEnum.GLOBAL_APP_DRAG_START_ACTIVITY; + } else if (description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT)) { + return DragAndDropUiEventEnum.GLOBAL_APP_DRAG_START_SHORTCUT; + } else if (description.hasMimeType(MIMETYPE_APPLICATION_TASK)) { + return DragAndDropUiEventEnum.GLOBAL_APP_DRAG_START_TASK; + } + throw new IllegalArgumentException("Not an app drag"); + } + + /** + * Enums for logging Drag & Drop UiEvents + */ + public enum DragAndDropUiEventEnum implements UiEventLogger.UiEventEnum { + @UiEvent(doc = "Starting a global drag and drop of an activity") + GLOBAL_APP_DRAG_START_ACTIVITY(884), + + @UiEvent(doc = "Starting a global drag and drop of a shortcut") + GLOBAL_APP_DRAG_START_SHORTCUT(885), + + @UiEvent(doc = "Starting a global drag and drop of a task") + GLOBAL_APP_DRAG_START_TASK(888), + + @UiEvent(doc = "A global app drag was successfully dropped") + GLOBAL_APP_DRAG_DROPPED(887), + + @UiEvent(doc = "Ending a global app drag and drop") + GLOBAL_APP_DRAG_END(886); + + private final int mId; + + DragAndDropUiEventEnum(int id) { + mId = id; + } + + @Override + public int getId() { + return mId; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 7937dfd0dbdc4..c178b29326f7f 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -126,8 +126,8 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides static DragAndDropController provideDragAndDropController(Context context, - DisplayController displayController) { - return new DragAndDropController(context, displayController); + DisplayController displayController, UiEventLogger uiEventLogger) { + return new DragAndDropController(context, displayController, uiEventLogger); } @WMSingleton