summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt218
-rw-r--r--libs/WindowManager/Shell/tests/unittest/Android.bp5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt169
3 files changed, 391 insertions, 1 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
new file mode 100644
index 000000000000..95d47146e834
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2024 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.desktopmode
+
+import com.android.internal.util.FrameworkStatsLog
+import com.android.wm.shell.protolog.ShellProtoLogGroup
+import com.android.wm.shell.util.KtProtoLog
+
+/**
+ * Event logger for logging desktop mode session events
+ */
+class DesktopModeEventLogger {
+ /**
+ * Logs the enter of desktop mode having session id [sessionId] and the reason [enterReason] for
+ * entering desktop mode
+ */
+ fun logSessionEnter(sessionId: Int, enterReason: EnterReason) {
+ KtProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging session enter, session: %s reason: %s",
+ sessionId, enterReason.name
+ )
+ FrameworkStatsLog.write(DESKTOP_MODE_ATOM_ID,
+ /* event */ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__ENTER,
+ /* enterReason */ enterReason.reason,
+ /* exitReason */ 0,
+ /* session_id */ sessionId)
+ }
+
+ /**
+ * Logs the exit of desktop mode having session id [sessionId] and the reason [exitReason] for
+ * exiting desktop mode
+ */
+ fun logSessionExit(sessionId: Int, exitReason: ExitReason) {
+ KtProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging session exit, session: %s reason: %s",
+ sessionId, exitReason.name
+ )
+ FrameworkStatsLog.write(DESKTOP_MODE_ATOM_ID,
+ /* event */ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__EXIT,
+ /* enterReason */ 0,
+ /* exitReason */ exitReason.reason,
+ /* session_id */ sessionId)
+ }
+
+ /**
+ * Logs that the task with update [taskUpdate] was added in the desktop mode session having
+ * session id [sessionId]
+ */
+ fun logTaskAdded(sessionId: Int, taskUpdate: TaskUpdate) {
+ KtProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging task added, session: %s taskId: %s",
+ sessionId, taskUpdate.instanceId
+ )
+ FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID,
+ /* task_event */
+ FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED,
+ /* instance_id */
+ taskUpdate.instanceId,
+ /* uid */
+ taskUpdate.uid,
+ /* task_height */
+ taskUpdate.taskHeight,
+ /* task_width */
+ taskUpdate.taskWidth,
+ /* task_x */
+ taskUpdate.taskX,
+ /* task_y */
+ taskUpdate.taskY,
+ /* session_id */
+ sessionId)
+ }
+
+ /**
+ * Logs that the task with update [taskUpdate] was removed in the desktop mode session having
+ * session id [sessionId]
+ */
+ fun logTaskRemoved(sessionId: Int, taskUpdate: TaskUpdate) {
+ KtProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging task remove, session: %s taskId: %s",
+ sessionId, taskUpdate.instanceId
+ )
+ FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID,
+ /* task_event */
+ FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED,
+ /* instance_id */
+ taskUpdate.instanceId,
+ /* uid */
+ taskUpdate.uid,
+ /* task_height */
+ taskUpdate.taskHeight,
+ /* task_width */
+ taskUpdate.taskWidth,
+ /* task_x */
+ taskUpdate.taskX,
+ /* task_y */
+ taskUpdate.taskY,
+ /* session_id */
+ sessionId)
+ }
+
+ /**
+ * Logs that the task with update [taskUpdate] had it's info changed in the desktop mode session
+ * having session id [sessionId]
+ */
+ fun logTaskInfoChanged(sessionId: Int, taskUpdate: TaskUpdate) {
+ KtProtoLog.v(
+ ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE,
+ "DesktopModeLogger: Logging task info changed, session: %s taskId: %s",
+ sessionId, taskUpdate.instanceId
+ )
+ FrameworkStatsLog.write(DESKTOP_MODE_TASK_UPDATE_ATOM_ID,
+ /* task_event */
+ FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED,
+ /* instance_id */
+ taskUpdate.instanceId,
+ /* uid */
+ taskUpdate.uid,
+ /* task_height */
+ taskUpdate.taskHeight,
+ /* task_width */
+ taskUpdate.taskWidth,
+ /* task_x */
+ taskUpdate.taskX,
+ /* task_y */
+ taskUpdate.taskY,
+ /* session_id */
+ sessionId)
+ }
+
+ companion object {
+ data class TaskUpdate(
+ val instanceId: Int,
+ val uid: Int,
+ val taskHeight: Int = Int.MIN_VALUE,
+ val taskWidth: Int = Int.MIN_VALUE,
+ val taskX: Int = Int.MIN_VALUE,
+ val taskY: Int = Int.MIN_VALUE,
+ )
+
+ /**
+ * Enum EnterReason mapped to the EnterReason definition in
+ * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+ */
+ enum class EnterReason(val reason: Int) {
+ UNKNOWN_ENTER(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__UNKNOWN_ENTER
+ ),
+ OVERVIEW(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__OVERVIEW
+ ),
+ APP_HANDLE_DRAG(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_HANDLE_DRAG
+ ),
+ APP_HANDLE_MENU_BUTTON(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_HANDLE_MENU_BUTTON
+ ),
+ APP_FREEFORM_INTENT(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__APP_FREEFORM_INTENT
+ ),
+ KEYBOARD_SHORTCUT_ENTER(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__KEYBOARD_SHORTCUT_ENTER
+ ),
+ SCREEN_ON(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__SCREEN_ON
+ );
+ }
+
+ /**
+ * Enum ExitReason mapped to the ExitReason definition in
+ * stats/atoms/desktopmode/desktopmode_extensions_atoms.proto
+ */
+ enum class ExitReason(val reason: Int) {
+ UNKNOWN_EXIT(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__UNKNOWN_EXIT
+ ),
+ DRAG_TO_EXIT(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__DRAG_TO_EXIT
+ ),
+ APP_HANDLE_MENU_BUTTON_EXIT(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__APP_HANDLE_MENU_BUTTON_EXIT
+ ),
+ KEYBOARD_SHORTCUT_EXIT(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__KEYBOARD_SHORTCUT_EXIT
+ ),
+ RETURN_HOME_OR_OVERVIEW(
+ FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME
+ ),
+ TASK_FINISHED(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__TASK_FINISHED
+ ),
+ SCREEN_OFF(
+ FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__SCREEN_OFF
+ )
+ }
+
+ private const val DESKTOP_MODE_ATOM_ID = FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED
+ private const val DESKTOP_MODE_TASK_UPDATE_ATOM_ID =
+ FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 8c4711603904..32c070305e05 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -24,7 +24,10 @@ package {
android_test {
name: "WMShellUnitTests",
-
+ defaults: [
+ // For ExtendedMockito dependencies.
+ "modules-utils-testable-device-config-defaults",
+ ],
srcs: [
"**/*.java",
"**/*.kt",
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
new file mode 100644
index 000000000000..4548fcb06c55
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2024 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.desktopmode
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.internal.util.FrameworkStatsLog
+import com.android.modules.utils.testing.ExtendedMockitoRule
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.TaskUpdate
+import kotlinx.coroutines.runBlocking
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.kotlin.eq
+
+/**
+ * Tests for [DesktopModeEventLogger].
+ */
+class DesktopModeEventLoggerTest {
+
+ private val desktopModeEventLogger = DesktopModeEventLogger()
+
+ @JvmField
+ @Rule
+ val extendedMockitoRule = ExtendedMockitoRule.Builder(this)
+ .mockStatic(FrameworkStatsLog::class.java).build()!!
+
+ @Test
+ fun logSessionEnter_enterReason() = runBlocking {
+ desktopModeEventLogger.logSessionEnter(sessionId = SESSION_ID, EnterReason.UNKNOWN_ENTER)
+
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(
+ eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED),
+ /* event */
+ eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__ENTER),
+ /* enter_reason */
+ eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__ENTER_REASON__UNKNOWN_ENTER),
+ /* exit_reason */
+ eq(0),
+ /* sessionId */
+ eq(SESSION_ID)
+ )
+ }
+ }
+
+ @Test
+ fun logSessionExit_exitReason() = runBlocking {
+ desktopModeEventLogger.logSessionExit(sessionId = SESSION_ID, ExitReason.UNKNOWN_EXIT)
+
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(
+ eq(FrameworkStatsLog.DESKTOP_MODE_UI_CHANGED),
+ /* event */
+ eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EVENT__EXIT),
+ /* enter_reason */
+ eq(0),
+ /* exit_reason */
+ eq(FrameworkStatsLog.DESKTOP_MODE_UICHANGED__EXIT_REASON__UNKNOWN_EXIT),
+ /* sessionId */
+ eq(SESSION_ID)
+ )
+ }
+ }
+
+ @Test
+ fun logTaskAdded_taskUpdate() = runBlocking {
+ desktopModeEventLogger.logTaskAdded(sessionId = SESSION_ID, TASK_UPDATE)
+
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE),
+ /* task_event */
+ eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_ADDED),
+ /* instance_id */
+ eq(TASK_UPDATE.instanceId),
+ /* uid */
+ eq(TASK_UPDATE.uid),
+ /* task_height */
+ eq(TASK_UPDATE.taskHeight),
+ /* task_width */
+ eq(TASK_UPDATE.taskWidth),
+ /* task_x */
+ eq(TASK_UPDATE.taskX),
+ /* task_y */
+ eq(TASK_UPDATE.taskY),
+ /* session_id */
+ eq(SESSION_ID))
+ }
+ }
+
+ @Test
+ fun logTaskRemoved_taskUpdate() = runBlocking {
+ desktopModeEventLogger.logTaskRemoved(sessionId = SESSION_ID, TASK_UPDATE)
+
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE),
+ /* task_event */
+ eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_REMOVED),
+ /* instance_id */
+ eq(TASK_UPDATE.instanceId),
+ /* uid */
+ eq(TASK_UPDATE.uid),
+ /* task_height */
+ eq(TASK_UPDATE.taskHeight),
+ /* task_width */
+ eq(TASK_UPDATE.taskWidth),
+ /* task_x */
+ eq(TASK_UPDATE.taskX),
+ /* task_y */
+ eq(TASK_UPDATE.taskY),
+ /* session_id */
+ eq(SESSION_ID))
+ }
+ }
+
+ @Test
+ fun logTaskInfoChanged_taskUpdate() = runBlocking {
+ desktopModeEventLogger.logTaskInfoChanged(sessionId = SESSION_ID, TASK_UPDATE)
+
+ ExtendedMockito.verify {
+ FrameworkStatsLog.write(eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE),
+ /* task_event */
+ eq(FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INFO_CHANGED),
+ /* instance_id */
+ eq(TASK_UPDATE.instanceId),
+ /* uid */
+ eq(TASK_UPDATE.uid),
+ /* task_height */
+ eq(TASK_UPDATE.taskHeight),
+ /* task_width */
+ eq(TASK_UPDATE.taskWidth),
+ /* task_x */
+ eq(TASK_UPDATE.taskX),
+ /* task_y */
+ eq(TASK_UPDATE.taskY),
+ /* session_id */
+ eq(SESSION_ID))
+ }
+ }
+
+ companion object {
+ private const val SESSION_ID = 1
+ private const val TASK_ID = 1
+ private const val TASK_UID = 1
+ private const val TASK_X = 0
+ private const val TASK_Y = 0
+ private const val TASK_HEIGHT = 100
+ private const val TASK_WIDTH = 100
+
+ private val TASK_UPDATE = TaskUpdate(
+ TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y
+ )
+ }
+} \ No newline at end of file