From d184e5ffa1d0099e4628398317a0383b1bf72176 Mon Sep 17 00:00:00 2001 From: Nicolo' Mazzucato Date: Mon, 16 Jan 2023 14:47:14 +0000 Subject: [PATCH] Optimize DeviceFoldStateProvider#onHingeAngle isClosingThresholdMet calculation turn out to cause some binder transaction to know if the current top task is home activity. As it is very rarely used, it is now moved to the last position of the AND chain. Instead of querying ActivityManager each time, now a listener is registered for top task changes. This removes many useless binder transactions (but adds a binder transaction when DeviceFoldStateProvider is initialized) Test: DeviceFoldStateProviderTest Bug: 265666399 Change-Id: I9b44d7409261882a3b72ad5d7f5eb44a2eb3c2b1 --- .../ActivityManagerActivityTypeProvider.kt | 44 ++++++++++++++++--- .../unfold/updates/DeviceFoldStateProvider.kt | 11 +++-- .../util/CurrentActivityTypeProvider.kt | 5 +++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt index 7f2933e44b326..c9e57b45612c4 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt @@ -15,21 +15,51 @@ package com.android.systemui.unfold.system import android.app.ActivityManager +import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration +import android.os.Trace +import com.android.systemui.shared.system.TaskStackChangeListener +import com.android.systemui.shared.system.TaskStackChangeListeners import com.android.systemui.unfold.util.CurrentActivityTypeProvider import javax.inject.Inject import javax.inject.Singleton @Singleton -class ActivityManagerActivityTypeProvider @Inject constructor( - private val activityManager: ActivityManager -) : CurrentActivityTypeProvider { +class ActivityManagerActivityTypeProvider +@Inject +constructor(private val activityManager: ActivityManager) : CurrentActivityTypeProvider { override val isHomeActivity: Boolean? - get() { - val activityType = activityManager.getRunningTasks(/* maxNum= */ 1) - ?.getOrNull(0)?.topActivityType ?: return null + get() = _isHomeActivity - return activityType == WindowConfiguration.ACTIVITY_TYPE_HOME + private var _isHomeActivity: Boolean? = null + + + override fun init() { + _isHomeActivity = activityManager.isOnHomeActivity() + TaskStackChangeListeners.getInstance().registerTaskStackListener(taskStackChangeListener) + } + + override fun uninit() { + TaskStackChangeListeners.getInstance().unregisterTaskStackListener(taskStackChangeListener) + } + + private val taskStackChangeListener = + object : TaskStackChangeListener { + override fun onTaskMovedToFront(taskInfo: RunningTaskInfo) { + _isHomeActivity = taskInfo.isHomeActivity() + } } + + private fun RunningTaskInfo.isHomeActivity(): Boolean = + topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME + + private fun ActivityManager.isOnHomeActivity(): Boolean? { + try { + Trace.beginSection("isOnHomeActivity") + return getRunningTasks(/* maxNum= */ 1)?.firstOrNull()?.isHomeActivity() + } finally { + Trace.endSection() + } + } } diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt index 5b458975fa348..97c9ba99f096d 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt @@ -79,6 +79,7 @@ constructor( screenStatusProvider.addCallback(screenListener) hingeAngleProvider.addCallback(hingeAngleListener) rotationChangeProvider.addCallback(rotationListener) + activityTypeProvider.init() } override fun stop() { @@ -87,6 +88,7 @@ constructor( hingeAngleProvider.removeCallback(hingeAngleListener) hingeAngleProvider.stop() rotationChangeProvider.removeCallback(rotationListener) + activityTypeProvider.uninit() } override fun addCallback(listener: FoldUpdatesListener) { @@ -115,19 +117,17 @@ constructor( } val isClosing = angle < lastHingeAngle - val closingThreshold = getClosingThreshold() - val closingThresholdMet = closingThreshold == null || angle < closingThreshold val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING val screenAvailableEventSent = isUnfoldHandled if (isClosing // hinge angle should be decreasing since last update - && closingThresholdMet // hinge angle is below certain threshold && !closingEventDispatched // we haven't sent closing event already && !isFullyOpened // do not send closing event if we are in fully opened hinge // angle range as closing threshold could overlap this range && screenAvailableEventSent // do not send closing event if we are still in // the process of turning on the inner display + && isClosingThresholdMet(angle) // hinge angle is below certain threshold. ) { notifyFoldUpdate(FOLD_UPDATE_START_CLOSING) } @@ -146,6 +146,11 @@ constructor( outputListeners.forEach { it.onHingeAngleUpdate(angle) } } + private fun isClosingThresholdMet(currentAngle: Float) : Boolean { + val closingThreshold = getClosingThreshold() + return closingThreshold == null || currentAngle < closingThreshold + } + /** * Fold animation should be started only after the threshold returned here. * diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CurrentActivityTypeProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CurrentActivityTypeProvider.kt index d0e6cdc9a3c66..34e7c38c1e597 100644 --- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CurrentActivityTypeProvider.kt +++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CurrentActivityTypeProvider.kt @@ -16,6 +16,11 @@ package com.android.systemui.unfold.util interface CurrentActivityTypeProvider { val isHomeActivity: Boolean? + + /** Starts listening for task updates. */ + fun init() {} + /** Stop listening for task updates. */ + fun uninit() {} } class EmptyCurrentActivityTypeProvider(override val isHomeActivity: Boolean? = null) :