Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * 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 android.util.Log import com.android.internal.logging.InstanceId import com.android.internal.logging.InstanceIdSequence import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.wm.shell.dagger.WMSingleton import javax.inject.Inject /** * Log Aster UIEvents for desktop windowing mode. */ @WMSingleton class DesktopModeUiEventLogger @Inject constructor( private val mUiEventLogger: UiEventLogger, private val mInstanceIdSequence: InstanceIdSequence ) { /** * Logs an event for a CUI, on a particular package. * * @param uid The user id associated with the package the user is interacting with * @param packageName The name of the package the user is interacting with * @param event The event type to generate */ fun log(uid: Int, packageName: String, event: DesktopUiEventEnum) { if (packageName.isEmpty() || uid < 0) { Log.d(TAG, "Skip logging since package name is empty or bad uid") return } mUiEventLogger.log(event, uid, packageName) } /** * Retrieves a new instance id for a new interaction. */ fun getNewInstanceId(): InstanceId = mInstanceIdSequence.newInstanceId() /** * Logs an event as part of a particular CUI, on a particular package. * * @param instanceId The id identifying an interaction, potentially taking place across multiple * surfaces. There should be a new id generated for each distinct CUI. * @param uid The user id associated with the package the user is interacting with * @param packageName The name of the package the user is interacting with * @param event The event type to generate */ fun logWithInstanceId( instanceId: InstanceId, uid: Int, packageName: String, event: DesktopUiEventEnum ) { if (packageName.isEmpty() || uid < 0) { Log.d(TAG, "Skip logging since package name is empty or bad uid") return } mUiEventLogger.logWithInstanceId(event, uid, packageName, instanceId) } companion object { /** * Enums for logging desktop windowing mode UiEvents. */ enum class DesktopUiEventEnum(private val mId: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "Resize the window in desktop windowing mode by dragging the edge") DESKTOP_WINDOW_EDGE_DRAG_RESIZE(1721), @UiEvent(doc = "Resize the window in desktop windowing mode by dragging the corner") DESKTOP_WINDOW_CORNER_DRAG_RESIZE(1722), @UiEvent(doc = "Tap on the window header maximize button in desktop windowing mode") DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP(1723), @UiEvent(doc = "Double tap on window header to maximize it in desktop windowing mode") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724); override fun getId(): Int = mId } private const val TAG = "DesktopModeUiEventLogger" } } No newline at end of file libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * 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 android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.InstanceIdSequence import com.android.internal.logging.testing.UiEventLoggerFake import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.Companion.DesktopUiEventEnum.DESKTOP_WINDOW_EDGE_DRAG_RESIZE import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith /** * Test class for [DesktopModeUiEventLogger] * * Usage: atest WMShellUnitTests:DesktopModeUiEventLoggerTest */ @SmallTest @RunWith(AndroidTestingRunner::class) class DesktopModeUiEventLoggerTest : ShellTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: DesktopModeUiEventLogger private val instanceIdSequence = InstanceIdSequence(10) @Before fun setUp() { uiEventLoggerFake = UiEventLoggerFake() logger = DesktopModeUiEventLogger(uiEventLoggerFake, instanceIdSequence) } @Test fun log_invalidUid_eventNotLogged() { logger.log(-1, PACKAGE_NAME, DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun log_emptyPackageName_eventNotLogged() { logger.log(UID, "", DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun log_eventLogged() { val event = DESKTOP_WINDOW_EDGE_DRAG_RESIZE logger.log(UID, PACKAGE_NAME, event) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(event.id) assertThat(uiEventLoggerFake[0].instanceId).isNull() assertThat(uiEventLoggerFake[0].uid).isEqualTo(UID) assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) } @Test fun getNewInstanceId() { val first = logger.getNewInstanceId() assertThat(first).isNotEqualTo(logger.getNewInstanceId()) } @Test fun logWithInstanceId_invalidUid_eventNotLogged() { logger.logWithInstanceId(INSTANCE_ID, -1, PACKAGE_NAME, DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun logWithInstanceId_emptyPackageName_eventNotLogged() { logger.logWithInstanceId(INSTANCE_ID, UID, "", DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun logWithInstanceId_eventLogged() { val event = DESKTOP_WINDOW_EDGE_DRAG_RESIZE logger.logWithInstanceId(INSTANCE_ID, UID, PACKAGE_NAME, event) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(event.id) assertThat(uiEventLoggerFake[0].instanceId).isEqualTo(INSTANCE_ID) assertThat(uiEventLoggerFake[0].uid).isEqualTo(UID) assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) } companion object { private val INSTANCE_ID = InstanceId.fakeInstanceId(0) private const val UID = 10 private const val PACKAGE_NAME = "com.foo" } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt 0 → 100644 +100 −0 Original line number Diff line number Diff line /* * 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 android.util.Log import com.android.internal.logging.InstanceId import com.android.internal.logging.InstanceIdSequence import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.wm.shell.dagger.WMSingleton import javax.inject.Inject /** * Log Aster UIEvents for desktop windowing mode. */ @WMSingleton class DesktopModeUiEventLogger @Inject constructor( private val mUiEventLogger: UiEventLogger, private val mInstanceIdSequence: InstanceIdSequence ) { /** * Logs an event for a CUI, on a particular package. * * @param uid The user id associated with the package the user is interacting with * @param packageName The name of the package the user is interacting with * @param event The event type to generate */ fun log(uid: Int, packageName: String, event: DesktopUiEventEnum) { if (packageName.isEmpty() || uid < 0) { Log.d(TAG, "Skip logging since package name is empty or bad uid") return } mUiEventLogger.log(event, uid, packageName) } /** * Retrieves a new instance id for a new interaction. */ fun getNewInstanceId(): InstanceId = mInstanceIdSequence.newInstanceId() /** * Logs an event as part of a particular CUI, on a particular package. * * @param instanceId The id identifying an interaction, potentially taking place across multiple * surfaces. There should be a new id generated for each distinct CUI. * @param uid The user id associated with the package the user is interacting with * @param packageName The name of the package the user is interacting with * @param event The event type to generate */ fun logWithInstanceId( instanceId: InstanceId, uid: Int, packageName: String, event: DesktopUiEventEnum ) { if (packageName.isEmpty() || uid < 0) { Log.d(TAG, "Skip logging since package name is empty or bad uid") return } mUiEventLogger.logWithInstanceId(event, uid, packageName, instanceId) } companion object { /** * Enums for logging desktop windowing mode UiEvents. */ enum class DesktopUiEventEnum(private val mId: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "Resize the window in desktop windowing mode by dragging the edge") DESKTOP_WINDOW_EDGE_DRAG_RESIZE(1721), @UiEvent(doc = "Resize the window in desktop windowing mode by dragging the corner") DESKTOP_WINDOW_CORNER_DRAG_RESIZE(1722), @UiEvent(doc = "Tap on the window header maximize button in desktop windowing mode") DESKTOP_WINDOW_MAXIMIZE_BUTTON_TAP(1723), @UiEvent(doc = "Double tap on window header to maximize it in desktop windowing mode") DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724); override fun getId(): Int = mId } private const val TAG = "DesktopModeUiEventLogger" } } No newline at end of file
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLoggerTest.kt 0 → 100644 +111 −0 Original line number Diff line number Diff line /* * 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 android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest import com.android.internal.logging.InstanceId import com.android.internal.logging.InstanceIdSequence import com.android.internal.logging.testing.UiEventLoggerFake import com.android.wm.shell.ShellTestCase import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.Companion.DesktopUiEventEnum.DESKTOP_WINDOW_EDGE_DRAG_RESIZE import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith /** * Test class for [DesktopModeUiEventLogger] * * Usage: atest WMShellUnitTests:DesktopModeUiEventLoggerTest */ @SmallTest @RunWith(AndroidTestingRunner::class) class DesktopModeUiEventLoggerTest : ShellTestCase() { private lateinit var uiEventLoggerFake: UiEventLoggerFake private lateinit var logger: DesktopModeUiEventLogger private val instanceIdSequence = InstanceIdSequence(10) @Before fun setUp() { uiEventLoggerFake = UiEventLoggerFake() logger = DesktopModeUiEventLogger(uiEventLoggerFake, instanceIdSequence) } @Test fun log_invalidUid_eventNotLogged() { logger.log(-1, PACKAGE_NAME, DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun log_emptyPackageName_eventNotLogged() { logger.log(UID, "", DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun log_eventLogged() { val event = DESKTOP_WINDOW_EDGE_DRAG_RESIZE logger.log(UID, PACKAGE_NAME, event) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(event.id) assertThat(uiEventLoggerFake[0].instanceId).isNull() assertThat(uiEventLoggerFake[0].uid).isEqualTo(UID) assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) } @Test fun getNewInstanceId() { val first = logger.getNewInstanceId() assertThat(first).isNotEqualTo(logger.getNewInstanceId()) } @Test fun logWithInstanceId_invalidUid_eventNotLogged() { logger.logWithInstanceId(INSTANCE_ID, -1, PACKAGE_NAME, DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun logWithInstanceId_emptyPackageName_eventNotLogged() { logger.logWithInstanceId(INSTANCE_ID, UID, "", DESKTOP_WINDOW_EDGE_DRAG_RESIZE) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(0) } @Test fun logWithInstanceId_eventLogged() { val event = DESKTOP_WINDOW_EDGE_DRAG_RESIZE logger.logWithInstanceId(INSTANCE_ID, UID, PACKAGE_NAME, event) assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1) assertThat(uiEventLoggerFake.eventId(0)).isEqualTo(event.id) assertThat(uiEventLoggerFake[0].instanceId).isEqualTo(INSTANCE_ID) assertThat(uiEventLoggerFake[0].uid).isEqualTo(UID) assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME) } companion object { private val INSTANCE_ID = InstanceId.fakeInstanceId(0) private const val UID = 10 private const val PACKAGE_NAME = "com.foo" } }