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

Commit 9975e2c4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add ACTION_SWITCH_DISPLAY_UNFOLD to LatencyTracker"

parents 93a7072c ea41bd1c
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -122,6 +122,11 @@ public class LatencyTracker {
     */
    public static final int ACTION_USER_SWITCH = 12;

    /**
     * Time it takes to turn on the inner screen for a foldable device.
     */
    public static final int ACTION_SWITCH_DISPLAY_UNFOLD = 13;

    private static final int[] ACTIONS_ALL = {
        ACTION_EXPAND_PANEL,
        ACTION_TOGGLE_RECENTS,
@@ -135,7 +140,8 @@ public class LatencyTracker {
        ACTION_ROTATE_SCREEN_SENSOR,
        ACTION_ROTATE_SCREEN_CAMERA_CHECK,
        ACTION_LOCKSCREEN_UNLOCK,
        ACTION_USER_SWITCH
        ACTION_USER_SWITCH,
        ACTION_SWITCH_DISPLAY_UNFOLD
    };

    /** @hide */
@@ -152,7 +158,8 @@ public class LatencyTracker {
        ACTION_ROTATE_SCREEN_SENSOR,
        ACTION_ROTATE_SCREEN_CAMERA_CHECK,
        ACTION_LOCKSCREEN_UNLOCK,
        ACTION_USER_SWITCH
        ACTION_USER_SWITCH,
        ACTION_SWITCH_DISPLAY_UNFOLD
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Action {
@@ -171,7 +178,8 @@ public class LatencyTracker {
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_SENSOR,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN_CAMERA_CHECK,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_LOCKSCREEN_UNLOCK,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_USER_SWITCH,
            FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_SWITCH_DISPLAY_UNFOLD
    };

    private static LatencyTracker sLatencyTracker;
@@ -257,6 +265,8 @@ public class LatencyTracker {
                return "ACTION_LOCKSCREEN_UNLOCK";
            case 13:
                return "ACTION_USER_SWITCH";
            case 14:
                return "ACTION_SWITCH_DISPLAY_UNFOLD";
            default:
                throw new IllegalArgumentException("Invalid action");
        }
+6 −0
Original line number Diff line number Diff line
@@ -33,6 +33,12 @@ import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
import java.lang.IllegalStateException
import java.util.concurrent.Executor

/**
 * Factory for [UnfoldTransitionProgressProvider].
 *
 * This is needed as Launcher has to create the object manually.
 * Sysui create it using dagger (see [UnfoldTransitionModule]).
 */
fun createUnfoldTransitionProgressProvider(
    context: Context,
    config: UnfoldTransitionConfig,
+8 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper;
import com.android.systemui.people.PeopleProvider;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.unfold.UnfoldLatencyTracker;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.TaskViewFactory;
@@ -135,6 +136,7 @@ public interface SysUIComponent {
        // No init method needed, just needs to be gotten so that it's created.
        getMediaTttChipController();
        getMediaTttCommandLineHelper();
        getUnfoldLatencyTracker().init();
    }

    /**
@@ -155,6 +157,12 @@ public interface SysUIComponent {
    @SysUISingleton
    ContextComponentHelper getContextComponentHelper();

    /**
     * Creates a UnfoldLatencyTracker.
     */
    @SysUISingleton
    UnfoldLatencyTracker getUnfoldLatencyTracker();

    /**
     * Main dependency providing module.
     */
+83 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.unfold

import android.content.Context
import android.hardware.devicestate.DeviceStateManager
import com.android.internal.util.LatencyTracker
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.keyguard.ScreenLifecycle
import java.util.concurrent.Executor
import javax.inject.Inject

/**
 * Logs performance metrics regarding time to turn the inner screen on.
 *
 * This class assumes that [onFoldEvent] is always called before [onScreenTurnedOn].
 * This should be used from only one process.
 * For now, the focus is on the time the inner display is visible, but in the future, it is easily
 * possible to monitor the time to go from the inner screen to the outer.
 */
@SysUISingleton
class UnfoldLatencyTracker @Inject constructor(
    private val latencyTracker: LatencyTracker,
    private val deviceStateManager: DeviceStateManager,
    @UiBackground private val uiBgExecutor: Executor,
    private val context: Context,
    private val screenLifecycle: ScreenLifecycle
) : ScreenLifecycle.Observer {

    private var folded: Boolean? = null
    private val foldStateListener = FoldStateListener(context)
    private val isFoldable: Boolean
        get() = context.resources.getIntArray(
            com.android.internal.R.array.config_foldedDeviceStates).isNotEmpty()

    /** Registers for relevant events only if the device is foldable. */
    fun init() {
        if (!isFoldable) {
            return
        }
        deviceStateManager.registerCallback(uiBgExecutor, foldStateListener)
        screenLifecycle.addObserver(this)
    }

    /**
     * To be called when the screen becomes visible.
     *
     * This is safe to call also when unsure whether the device is not a foldable, as it emits the
     * end action event only if we previously received a fold state.
     */
    override fun onScreenTurnedOn() {
        if (folded == false) {
            latencyTracker.onActionEnd(LatencyTracker.ACTION_SWITCH_DISPLAY_UNFOLD)
        }
    }

    private fun onFoldEvent(folded: Boolean) {
        if (this.folded != folded) {
            this.folded = folded
            if (!folded) { // unfolding started
                latencyTracker.onActionStart(LatencyTracker.ACTION_SWITCH_DISPLAY_UNFOLD)
            }
        }
    }

    private inner class FoldStateListener(context: Context) :
        DeviceStateManager.FoldStateListener(context, { onFoldEvent(it) })
}
+110 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.unfold

import android.hardware.devicestate.DeviceStateManager
import android.hardware.devicestate.DeviceStateManager.FoldStateListener
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.internal.util.LatencyTracker
import com.android.systemui.SysuiTestCase
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.unfold.util.FoldableDeviceStates
import com.android.systemui.unfold.util.FoldableTestUtils
import com.android.systemui.util.mockito.any
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations

@RunWith(AndroidTestingRunner::class)
@SmallTest
class UnfoldLatencyTrackerTest : SysuiTestCase() {

    @Mock
    lateinit var latencyTracker: LatencyTracker

    @Mock
    lateinit var deviceStateManager: DeviceStateManager

    @Mock
    lateinit var screenLifecycle: ScreenLifecycle

    @Captor
    private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>

    @Captor
    private lateinit var screenLifecycleCaptor: ArgumentCaptor<ScreenLifecycle.Observer>

    private lateinit var deviceStates: FoldableDeviceStates

    private lateinit var unfoldLatencyTracker: UnfoldLatencyTracker

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        unfoldLatencyTracker = UnfoldLatencyTracker(
            latencyTracker,
            deviceStateManager,
            context.mainExecutor,
            context,
            screenLifecycle
        )
        deviceStates = FoldableTestUtils.findDeviceStates(context)

        verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture())
        verify(screenLifecycle).addObserver(screenLifecycleCaptor.capture())
    }

    @Test
    fun unfold_eventPropagated() {
        sendFoldEvent(folded = false)
        sendScreenTurnedOnEvent()

        verify(latencyTracker).onActionStart(any())
        verify(latencyTracker).onActionEnd(any())
    }

    @Test
    fun fold_eventNotPropagated() {
        sendFoldEvent(folded = true)
        sendScreenTurnedOnEvent() // outer display on.

        verifyNoMoreInteractions(latencyTracker)
    }

    @Test
    fun onScreenTurnedOn_stateNeverSet_eventNotPropagated() {
        sendScreenTurnedOnEvent()

        verifyNoMoreInteractions(latencyTracker)
    }

    private fun sendFoldEvent(folded: Boolean) {
        val state = if (folded) deviceStates.folded else deviceStates.unfolded
        foldStateListenerCaptor.value.onStateChanged(state)
    }

    private fun sendScreenTurnedOnEvent() {
        screenLifecycleCaptor.value.onScreenTurnedOn()
    }
}
 No newline at end of file
Loading