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

Commit a250b92e authored by Nick Chameyev's avatar Nick Chameyev
Browse files

Use hinge angle sensor based unfold animation by default

Enables hinge angle driven unfold animation by default
on devices where hinge angle sensor is available,
uses fixed timing transition otherwise.

Bug: 195404647
Test: manual
Change-Id: I36e85a67664dcc579c18bfef870158e86aa921b9
parent 5c9e2243
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.hardware.SensorManager
import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.config.ANIMATION_MODE_HINGE_ANGLE
import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
import com.android.systemui.unfold.config.UnfoldTransitionConfig
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
@@ -30,7 +29,6 @@ import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgress
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
import com.android.systemui.unfold.updates.hinge.RotationSensorHingeAngleProvider
import java.lang.IllegalStateException
import java.util.concurrent.Executor

@@ -50,14 +48,8 @@ fun createUnfoldTransitionProgressProvider(
    }

    val hingeAngleProvider =
        if (config.mode == ANIMATION_MODE_HINGE_ANGLE) {
            // TODO: after removing temporary "config.mode" we should just
            //       switch between fixed timing and hinge sensor based on this flag
        if (config.isHingeAngleEnabled) {
            HingeSensorAngleProvider(sensorManager)
            } else {
                RotationSensorHingeAngleProvider(sensorManager)
            }
        } else {
            EmptyHingeAngleProvider()
        }
@@ -70,7 +62,7 @@ fun createUnfoldTransitionProgressProvider(
        mainExecutor
    )

    return if (config.mode == ANIMATION_MODE_HINGE_ANGLE) {
    return if (config.isHingeAngleEnabled) {
        PhysicsBasedUnfoldTransitionProgressProvider(
            mainHandler,
            foldStateProvider
+6 −6
Original line number Diff line number Diff line
@@ -23,17 +23,16 @@ internal class ResourceUnfoldTransitionConfig(
) : UnfoldTransitionConfig {

    override val isEnabled: Boolean
        get() = readIsEnabled() && mode != ANIMATION_MODE_DISABLED
        get() = readIsEnabledResource() && isPropertyEnabled

    override val isHingeAngleEnabled: Boolean
        get() = readIsHingeAngleEnabled()

    @AnimationMode
    override val mode: Int
    private val isPropertyEnabled: Boolean
        get() = SystemProperties.getInt(UNFOLD_TRANSITION_MODE_PROPERTY_NAME,
            ANIMATION_MODE_FIXED_TIMING)
            UNFOLD_TRANSITION_PROPERTY_ENABLED) == UNFOLD_TRANSITION_PROPERTY_ENABLED

    private fun readIsEnabled(): Boolean = context.resources
    private fun readIsEnabledResource(): Boolean = context.resources
        .getBoolean(com.android.internal.R.bool.config_unfoldTransitionEnabled)

    private fun readIsHingeAngleEnabled(): Boolean = context.resources
@@ -44,4 +43,5 @@ internal class ResourceUnfoldTransitionConfig(
 * Temporary persistent property to control unfold transition mode
 * See [com.android.unfold.config.AnimationMode]
 */
private const val UNFOLD_TRANSITION_MODE_PROPERTY_NAME = "persist.unfold.transition_mode"
private const val UNFOLD_TRANSITION_MODE_PROPERTY_NAME = "persist.unfold.transition_enabled"
private const val UNFOLD_TRANSITION_PROPERTY_ENABLED = 1
+0 −18
Original line number Diff line number Diff line
@@ -15,25 +15,7 @@
 */
package com.android.systemui.unfold.config

import android.annotation.IntDef

interface UnfoldTransitionConfig {
    val isEnabled: Boolean
    val isHingeAngleEnabled: Boolean

    @AnimationMode
    val mode: Int
}

@IntDef(prefix = ["ANIMATION_MODE_"], value = [
    ANIMATION_MODE_DISABLED,
    ANIMATION_MODE_FIXED_TIMING,
    ANIMATION_MODE_HINGE_ANGLE
])

@Retention(AnnotationRetention.SOURCE)
annotation class AnimationMode

const val ANIMATION_MODE_DISABLED = 0
const val ANIMATION_MODE_FIXED_TIMING = 1
const val ANIMATION_MODE_HINGE_ANGLE = 2
+0 −67
Original line number Diff line number Diff line
package com.android.systemui.unfold.updates.hinge

import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import androidx.core.util.Consumer
import com.android.systemui.shared.recents.utilities.Utilities

/**
 * Temporary hinge angle provider that uses rotation sensor instead.
 * It requires to have the device in a certain position to work correctly
 * (flat to the ground)
 */
internal class RotationSensorHingeAngleProvider(
    private val sensorManager: SensorManager
) : HingeAngleProvider {

    private val sensorListener = HingeAngleSensorListener()
    private val listeners: MutableList<Consumer<Float>> = arrayListOf()

    override fun start() {
        val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)
        sensorManager.registerListener(sensorListener, sensor, SensorManager.SENSOR_DELAY_FASTEST)
    }

    override fun stop() {
        sensorManager.unregisterListener(sensorListener)
    }

    override fun removeCallback(listener: Consumer<Float>) {
        listeners.remove(listener)
    }

    override fun addCallback(listener: Consumer<Float>) {
        listeners.add(listener)
    }

    private fun onHingeAngle(angle: Float) {
        listeners.forEach { it.accept(angle) }
    }

    private inner class HingeAngleSensorListener : SensorEventListener {

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        }

        override fun onSensorChanged(event: SensorEvent) {
            // Jumbojack sends incorrect sensor reading 1.0f event in the beginning, let's ignore it
            if (event.values[3] == 1.0f) return

            val angleRadians = event.values.convertToAngle()
            val hingeAngleDegrees = Math.toDegrees(angleRadians).toFloat()
            val angle = Utilities.clamp(hingeAngleDegrees, FULLY_CLOSED_DEGREES, FULLY_OPEN_DEGREES)
            onHingeAngle(angle)
        }

        private val rotationMatrix = FloatArray(9)
        private val resultOrientation = FloatArray(9)

        private fun FloatArray.convertToAngle(): Double {
            SensorManager.getRotationMatrixFromVector(rotationMatrix, this)
            SensorManager.getOrientation(rotationMatrix, resultOrientation)
            return resultOrientation[2] + Math.PI
        }
    }
}