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

Commit 3e69cf98 authored by Liran Binyamin's avatar Liran Binyamin
Browse files

Log bubble session events

Update BubbleSessionTrackerImpl to log session start and session
end events to BubbleLogger.

Bug: 438484702
Flag: EXEMPT new metric events
Test: atest BubbleSessionTrackerImplTest
Change-Id: I3339d02b95d69d702c86378e7d950a328808402f
parent c9b15227
Loading
Loading
Loading
Loading
+52 −13
Original line number Diff line number Diff line
@@ -20,7 +20,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
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.internal.protolog.ProtoLog
import com.android.wm.shell.bubbles.BubbleLogger
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_BAR_SESSION_ENDED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_BAR_SESSION_STARTED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_SESSION_ENDED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_SESSION_STARTED
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -32,7 +38,9 @@ import org.junit.runner.RunWith
class BubbleSessionTrackerImplTest {

    private val instanceIdSequence = FakeInstanceIdSequence()
    private val bubbleSessionTracker = BubbleSessionTrackerImpl(instanceIdSequence)
    private val uiEventLoggerFake = UiEventLoggerFake()
    private val bubbleLogger = BubbleLogger(uiEventLoggerFake)
    private val bubbleSessionTracker = BubbleSessionTrackerImpl(instanceIdSequence, bubbleLogger)

    @Before
    fun setUp() {
@@ -41,24 +49,55 @@ class BubbleSessionTrackerImplTest {
    }

    @Test
    fun startSession_generatesNewSessionId() {
        bubbleSessionTracker.start()
        val firstSessionId = instanceIdSequence.id
        bubbleSessionTracker.stop()
    fun startSession_logsNewSessionId() {
        bubbleSessionTracker.startBubbleBar()
        bubbleSessionTracker.stopBubbleBar()
        bubbleSessionTracker.startBubbleBar()

        bubbleSessionTracker.start()
        val secondSessionId = instanceIdSequence.id
        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(3)
        val firstSessionStart = uiEventLoggerFake.logs.first()
        val secondSessionStart = uiEventLoggerFake.logs.last()
        assertThat(firstSessionStart.eventId).isEqualTo(BUBBLE_BAR_SESSION_STARTED.id)
        assertThat(secondSessionStart.eventId).isEqualTo(BUBBLE_BAR_SESSION_STARTED.id)
        assertThat(firstSessionStart.instanceId).isNotEqualTo(secondSessionStart.instanceId)
    }

    @Test
    fun endSession_logsSameSessionId() {
        bubbleSessionTracker.startBubbleBar()
        bubbleSessionTracker.stopBubbleBar()

        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(2)
        val sessionStart = uiEventLoggerFake.logs.first()
        val sessionEnd = uiEventLoggerFake.logs.last()
        assertThat(sessionStart.eventId).isEqualTo(BUBBLE_BAR_SESSION_STARTED.id)
        assertThat(sessionEnd.eventId).isEqualTo(BUBBLE_BAR_SESSION_ENDED.id)
        assertThat(sessionStart.instanceId).isEqualTo(sessionEnd.instanceId)
    }

    @Test
    fun logCorrectEventId() {
        bubbleSessionTracker.startBubbleBar()
        bubbleSessionTracker.stopBubbleBar()
        bubbleSessionTracker.startFloating()
        bubbleSessionTracker.stopFloating()

        assertThat(firstSessionId).isNotEqualTo(secondSessionId)
        assertThat(uiEventLoggerFake.numLogs()).isEqualTo(4)
        assertThat(uiEventLoggerFake.logs.map { it.eventId })
            .containsExactly(
                BUBBLE_BAR_SESSION_STARTED.id,
                BUBBLE_BAR_SESSION_ENDED.id,
                BUBBLE_SESSION_STARTED.id,
                BUBBLE_SESSION_ENDED.id
            )
            .inOrder()
    }

    @Test
    fun endSession_shouldNotGenerateNewId() {
        bubbleSessionTracker.start()
        val currentId = instanceIdSequence.id
        bubbleSessionTracker.stop()
    fun stopSession_noActiveSession_shouldNotLog() {
        bubbleSessionTracker.stopBubbleBar()

        assertThat(currentId).isEqualTo(instanceIdSequence.id)
        assertThat(uiEventLoggerFake.logs).isEmpty()
    }

    class FakeInstanceIdSequence : InstanceIdSequence(/* instanceIdMax= */ 10) {
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.bubbles;

import com.android.internal.logging.InstanceId;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.FrameworkStatsLog;
@@ -208,6 +209,11 @@ public class BubbleLogger {
        mUiEventLogger.logWithInstanceId(e, b.getAppUid(), b.getPackageName(), b.getInstanceId());
    }

    /** Log a UiEvent for the specified {@code sessionId}. */
    public void logWithSessionId(UiEventLogger.UiEventEnum e, InstanceId sessionId) {
        mUiEventLogger.log(e, sessionId);
    }

    /**
     * Log when a bubble is removed from overflow in stack view
     *
+10 −4
Original line number Diff line number Diff line
@@ -23,9 +23,15 @@ package com.android.wm.shell.bubbles.logging
 */
interface BubbleSessionTracker {

    /** Starts tracking a new session. */
    fun start()
    /** Starts tracking a new bubble bar session. */
    fun startBubbleBar()

    /** Stops tracking the current session. */
    fun stop()
    /** Stops tracking the current bubble bar session. */
    fun stopBubbleBar()

    /** Starts tracking a new floating bubble session. */
    fun startFloating()

    /** Stops tracking the current floating bubble session. */
    fun stopFloating()
}
+38 −8
Original line number Diff line number Diff line
@@ -19,6 +19,12 @@ package com.android.wm.shell.bubbles.logging
import com.android.internal.logging.InstanceId
import com.android.internal.logging.InstanceIdSequence
import com.android.internal.protolog.ProtoLog
import com.android.wm.shell.bubbles.BubbleLogger
import com.android.wm.shell.bubbles.BubbleLogger.Event
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_BAR_SESSION_ENDED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_BAR_SESSION_STARTED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_SESSION_ENDED
import com.android.wm.shell.bubbles.BubbleLogger.Event.BUBBLE_SESSION_STARTED
import com.android.wm.shell.dagger.Bubbles
import com.android.wm.shell.dagger.WMSingleton
import com.android.wm.shell.protolog.ShellProtoLogGroup
@@ -30,30 +36,54 @@ import javax.inject.Inject
 * Sessions are identified using an [InstanceId].
 */
@WMSingleton
class BubbleSessionTrackerImpl @Inject constructor(
    @Bubbles private val instanceIdSequence: InstanceIdSequence
class BubbleSessionTrackerImpl
@Inject
constructor(
    @param:Bubbles private val instanceIdSequence: InstanceIdSequence,
    private val logger: BubbleLogger
) : BubbleSessionTracker {

    private var currentSession: InstanceId? = null

    override fun start() {
    override fun startBubbleBar() {
        start(BUBBLE_BAR_SESSION_STARTED)
    }

    override fun startFloating() {
        start(BUBBLE_SESSION_STARTED)
    }

    private fun start(event: Event) {
        if (currentSession != null) {
            ProtoLog.d(
                ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY,
                "BubbleSessionTracker: starting to track a new session. "
                        + "previous session still active"
                "BubbleSessionTracker: starting to track a new session. " +
                    "previous session still active"
            )
        }
        currentSession = instanceIdSequence.newInstanceId()
        val sessionId = instanceIdSequence.newInstanceId()
        logger.logWithSessionId(event, sessionId)
        currentSession = sessionId
    }

    override fun stopBubbleBar() {
        stop(BUBBLE_BAR_SESSION_ENDED)
    }

    override fun stopFloating() {
        stop(BUBBLE_SESSION_ENDED)
    }

    override fun stop() {
        if (currentSession == null) {
    fun stop(event: Event) {
        val sessionId = currentSession
        if (sessionId == null) {
            ProtoLog.d(
                ShellProtoLogGroup.WM_SHELL_BUBBLES_NOISY,
                "BubbleSessionTracker: session tracking stopped but current session is null"
            )
            return
        }
        logger.logWithSessionId(event, sessionId)
        currentSession = null
    }
}