Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03639132 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Log DESKTOP_WINDOW_APP_HANDLE_TAP metrics" into main

parents 6eccef6f 1f3f4ac5
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.UserManager;
@@ -893,7 +894,8 @@ public abstract class WMShellModule {
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            FocusTransitionObserver focusTransitionObserver,
            DesktopModeEventLogger desktopModeEventLogger
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopModeUiEventLogger desktopModeUiEventLogger
    ) {
        if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) {
            return Optional.empty();
@@ -906,7 +908,7 @@ public abstract class WMShellModule {
                assistContentRequester, multiInstanceHelper, desktopTasksLimiter,
                appHandleEducationController, appToWebEducationController,
                windowDecorCaptionHandleRepository, activityOrientationChangeHandler,
                focusTransitionObserver, desktopModeEventLogger));
                focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger));
    }

    @WMSingleton
@@ -1234,9 +1236,10 @@ public abstract class WMShellModule {
    @WMSingleton
    @Provides
    static DesktopModeUiEventLogger provideDesktopUiEventLogger(
            UiEventLogger uiEventLogger
            UiEventLogger uiEventLogger,
            PackageManager packageManager
    ) {
        return new DesktopModeUiEventLogger(uiEventLogger);
        return new DesktopModeUiEventLogger(uiEventLogger, packageManager);
    }

    //
+24 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.desktopmode

import android.app.ActivityManager.RunningTaskInfo
import android.content.pm.PackageManager
import com.android.internal.logging.InstanceId
import com.android.internal.logging.InstanceIdSequence
import com.android.internal.logging.UiEvent
@@ -27,6 +29,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
/** Log Aster UIEvents for desktop windowing mode. */
class DesktopModeUiEventLogger(
    private val uiEventLogger: UiEventLogger,
    private val packageManager: PackageManager,
) {
    private val instanceIdSequence = InstanceIdSequence(Integer.MAX_VALUE)

@@ -45,6 +48,17 @@ class DesktopModeUiEventLogger(
        uiEventLogger.log(event, uid, packageName)
    }

    /** Logs an event for a CUI on a particular task. */
    fun log(taskInfo: RunningTaskInfo, event: DesktopUiEventEnum) {
        val packageName = taskInfo.baseActivity?.packageName
        if (packageName == null) {
            logD("Skip logging due to null base activity")
            return
        }
        val uid = getUid(packageName, taskInfo.userId)
        log(uid, packageName, event)
    }

    /** Retrieves a new instance id for a new interaction. */
    fun getNewInstanceId(): InstanceId = instanceIdSequence.newInstanceId()

@@ -70,6 +84,12 @@ class DesktopModeUiEventLogger(
        uiEventLogger.logWithInstanceId(event, uid, packageName, instanceId)
    }

    private fun getUid(packageName: String, userId: Int): Int = try {
        packageManager.getApplicationInfoAsUser(packageName, /* flags= */ 0, userId).uid
    } catch (e: PackageManager.NameNotFoundException) {
        INVALID_PACKAGE_UID
    }

    private fun logD(msg: String, vararg arguments: Any?) {
        ProtoLog.d(WM_SHELL_DESKTOP_MODE, "%s: $msg", TAG, *arguments)
    }
@@ -84,12 +104,15 @@ class DesktopModeUiEventLogger(
        @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);
        DESKTOP_WINDOW_HEADER_DOUBLE_TAP_TO_MAXIMIZE(1724),
        @UiEvent(doc = "Tap on the window Handle to open the Handle Menu")
        DESKTOP_WINDOW_APP_HANDLE_TAP(1998);

        override fun getId(): Int = mId
    }

    companion object {
        private const val TAG = "DesktopModeUiEventLogger"
        private const val INVALID_PACKAGE_UID = -1
    }
}
+15 −3
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIController;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.DesktopUiEventEnum;
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -228,6 +230,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
    private final TaskPositionerFactory mTaskPositionerFactory;
    private final FocusTransitionObserver mFocusTransitionObserver;
    private final DesktopModeEventLogger mDesktopModeEventLogger;
    private final DesktopModeUiEventLogger mDesktopModeUiEventLogger;

    public DesktopModeWindowDecorViewModel(
            Context context,
@@ -257,7 +260,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            FocusTransitionObserver focusTransitionObserver,
            DesktopModeEventLogger desktopModeEventLogger) {
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopModeUiEventLogger desktopModeUiEventLogger) {
        this(
                context,
                shellExecutor,
@@ -292,7 +296,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
                activityOrientationChangeHandler,
                new TaskPositionerFactory(),
                focusTransitionObserver,
                desktopModeEventLogger);
                desktopModeEventLogger,
                desktopModeUiEventLogger);
    }

    @VisibleForTesting
@@ -330,7 +335,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
            TaskPositionerFactory taskPositionerFactory,
            FocusTransitionObserver focusTransitionObserver,
            DesktopModeEventLogger desktopModeEventLogger) {
            DesktopModeEventLogger desktopModeEventLogger,
            DesktopModeUiEventLogger desktopModeUiEventLogger) {
        mContext = context;
        mMainExecutor = shellExecutor;
        mMainHandler = mainHandler;
@@ -393,6 +399,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
        mTaskPositionerFactory = taskPositionerFactory;
        mFocusTransitionObserver = focusTransitionObserver;
        mDesktopModeEventLogger = desktopModeEventLogger;
        mDesktopModeUiEventLogger = desktopModeUiEventLogger;

        shellInit.addInitCallback(this::onInit, this);
    }
@@ -803,6 +810,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
            } else if (id == R.id.back_button) {
                mTaskOperations.injectBackKey(mDisplayId);
            } else if (id == R.id.caption_handle || id == R.id.open_menu_button) {
                if (id == R.id.caption_handle && !decoration.mTaskInfo.isFreeform()) {
                    // Clicking the App Handle.
                    mDesktopModeUiEventLogger.log(decoration.mTaskInfo,
                            DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_TAP);
                }
                if (!decoration.isHandleMenuActive()) {
                    moveTaskToFront(decoration.mTaskInfo);
                    openHandleMenu(mTaskId);
+19 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
@@ -42,7 +43,9 @@ public final class TestRunningTaskInfoBuilder {
    private int mParentTaskId = INVALID_TASK_ID;
    private int mUid = INVALID_TASK_ID;
    private int mTaskId = INVALID_TASK_ID;
    private int mUserId = -1;
    private Intent mBaseIntent = new Intent();
    private ComponentName mBaseActivity = null;
    private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD;
    private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED;
    private @WindowConfiguration.ActivityType int mTopActivityType = ACTIVITY_TYPE_STANDARD;
@@ -88,6 +91,12 @@ public final class TestRunningTaskInfoBuilder {
        return this;
    }

    /** Sets the task info's user id. */
    public TestRunningTaskInfoBuilder setUserId(int userId) {
        mUserId = userId;
        return this;
    }

    /**
     * Set {@link ActivityManager.RunningTaskInfo#baseIntent} for the task info, by default
     * an empty intent is assigned
@@ -97,6 +106,14 @@ public final class TestRunningTaskInfoBuilder {
        return this;
    }

    /**
     * Set {@link ActivityManager.RunningTaskInfo#baseActivity} for the task info.
     */
    public TestRunningTaskInfoBuilder setBaseActivity(@NonNull ComponentName activity) {
        mBaseActivity = activity;
        return this;
    }

    public TestRunningTaskInfoBuilder setActivityType(
            @WindowConfiguration.ActivityType int activityType) {
        mActivityType = activityType;
@@ -172,6 +189,8 @@ public final class TestRunningTaskInfoBuilder {
        info.isTopActivityTransparent = mIsTopActivityTransparent;
        info.numActivities = mNumActivities;
        info.lastActiveTime = mLastActiveTime;
        info.userId = mUserId;
        info.baseActivity = mBaseActivity;
        return info;
    }
}
+26 −1
Original line number Diff line number Diff line
@@ -17,16 +17,22 @@
package com.android.wm.shell.desktopmode


import android.content.ComponentName
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.wm.shell.ShellTestCase
import com.android.wm.shell.TestRunningTaskInfoBuilder
import com.android.wm.shell.desktopmode.DesktopModeUiEventLogger.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
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

/**
 * Test class for [DesktopModeUiEventLogger]
@@ -39,11 +45,12 @@ class DesktopModeUiEventLoggerTest : ShellTestCase() {
    private lateinit var uiEventLoggerFake: UiEventLoggerFake
    private lateinit var logger: DesktopModeUiEventLogger

    private val mockPackageManager: PackageManager = mock<PackageManager>()

    @Before
    fun setUp() {
        uiEventLoggerFake = UiEventLoggerFake()
        logger = DesktopModeUiEventLogger(uiEventLoggerFake)
        logger = DesktopModeUiEventLogger(uiEventLoggerFake, mockPackageManager)
    }

    @Test
@@ -100,10 +107,28 @@ class DesktopModeUiEventLoggerTest : ShellTestCase() {
        assertThat(uiEventLoggerFake[0].packageName).isEqualTo(PACKAGE_NAME)
    }

    @Test
    fun logWithTaskInfo_eventLogged() {
        val event =
            DESKTOP_WINDOW_EDGE_DRAG_RESIZE
        val taskInfo = TestRunningTaskInfoBuilder()
            .setUserId(USER_ID)
            .setBaseActivity(ComponentName(PACKAGE_NAME, "test"))
            .build()
        whenever(mockPackageManager.getApplicationInfoAsUser(PACKAGE_NAME, /* flags= */ 0, USER_ID))
            .thenReturn(ApplicationInfo().apply { uid = UID })
        logger.log(taskInfo, 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)
    }

    companion object {
        private val INSTANCE_ID = InstanceId.fakeInstanceId(0)
        private const val UID = 10
        private const val USER_ID = 2
        private const val PACKAGE_NAME = "com.foo"
    }
}
Loading