1 package com.android.systemui.unfold.util
2 
3 import android.content.Context
4 import android.os.RemoteException
5 import android.view.IRotationWatcher
6 import android.view.IWindowManager
7 import android.view.Surface
8 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
9 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
10 
11 /**
12  * [UnfoldTransitionProgressProvider] that emits transition progress only when the display has
13  * default rotation or 180 degrees opposite rotation (ROTATION_0 or ROTATION_180).
14  * It could be helpful to run the animation only when the display's rotation is perpendicular
15  * to the fold.
16  */
17 class NaturalRotationUnfoldProgressProvider(
18     private val context: Context,
19     private val windowManagerInterface: IWindowManager,
20     unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider
21 ) : UnfoldTransitionProgressProvider {
22 
23     private val scopedUnfoldTransitionProgressProvider =
24             ScopedUnfoldTransitionProgressProvider(unfoldTransitionProgressProvider)
25     private val rotationWatcher = RotationWatcher()
26 
27     private var isNaturalRotation: Boolean = false
28 
29     fun init() {
30         try {
31             windowManagerInterface.watchRotation(rotationWatcher, context.display.displayId)
32         } catch (e: RemoteException) {
33             throw e.rethrowFromSystemServer()
34         }
35 
36         onRotationChanged(context.display.rotation)
37     }
38 
39     private fun onRotationChanged(rotation: Int) {
40         val isNewRotationNatural = rotation == Surface.ROTATION_0 ||
41                 rotation == Surface.ROTATION_180
42 
43         if (isNaturalRotation != isNewRotationNatural) {
44             isNaturalRotation = isNewRotationNatural
45             scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(isNewRotationNatural)
46         }
47     }
48 
49     override fun destroy() {
50         try {
51             windowManagerInterface.removeRotationWatcher(rotationWatcher)
52         } catch (e: RemoteException) {
53             e.rethrowFromSystemServer()
54         }
55 
56         scopedUnfoldTransitionProgressProvider.destroy()
57     }
58 
59     override fun addCallback(listener: TransitionProgressListener) {
60         scopedUnfoldTransitionProgressProvider.addCallback(listener)
61     }
62 
63     override fun removeCallback(listener: TransitionProgressListener) {
64         scopedUnfoldTransitionProgressProvider.removeCallback(listener)
65     }
66 
67     private inner class RotationWatcher : IRotationWatcher.Stub() {
68         override fun onRotationChanged(rotation: Int) {
69             this@NaturalRotationUnfoldProgressProvider.onRotationChanged(rotation)
70         }
71     }
72 }
73