Extract unfold classes to a separate library
No behaviour changes in this CL.
Extracted classes related to the fold/unfold
animation (that plays on foldable devices) to
a separate library that does not depend on
system classes. This is necessary to ease
reusing these classes in live wallpapers.
Bug: 231936088
Test: fold/unfold device
Change-Id: Ic1e1ec742867fca9c1209b930accd5738de18e39
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 3cf5bc1..9f790c6 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -47,6 +47,7 @@
],
static_libs: [
"PluginCoreLib",
+ "SystemUIUnfoldLib",
"androidx.dynamicanimation_dynamicanimation",
"androidx.concurrent_concurrent-futures",
"dagger2",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
deleted file mode 100644
index d1b0639..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.config
-
-import android.content.Context
-import android.os.SystemProperties
-
-internal class ResourceUnfoldTransitionConfig(private val context: Context) :
- UnfoldTransitionConfig {
-
- override val isEnabled: Boolean
- get() = readIsEnabledResource() && isPropertyEnabled
-
- override val isHingeAngleEnabled: Boolean
- get() = readIsHingeAngleEnabled()
-
- private val isPropertyEnabled: Boolean
- get() =
- SystemProperties.getInt(
- UNFOLD_TRANSITION_MODE_PROPERTY_NAME, UNFOLD_TRANSITION_PROPERTY_ENABLED) ==
- UNFOLD_TRANSITION_PROPERTY_ENABLED
-
- private fun readIsEnabledResource(): Boolean =
- context.resources.getBoolean(com.android.internal.R.bool.config_unfoldTransitionEnabled)
-
- private fun readIsHingeAngleEnabled(): Boolean =
- context.resources.getBoolean(com.android.internal.R.bool.config_unfoldTransitionHingeAngle)
-}
-
-/**
- * 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_enabled"
-private const val UNFOLD_TRANSITION_PROPERTY_ENABLED = 1
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
new file mode 100644
index 0000000..7f2933e
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 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.system
+
+import android.app.ActivityManager
+import android.app.WindowConfiguration
+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 {
+
+ override val isHomeActivity: Boolean?
+ get() {
+ val activityType = activityManager.getRunningTasks(/* maxNum= */ 1)
+ ?.getOrNull(0)?.topActivityType ?: return null
+
+ return activityType == WindowConfiguration.ACTIVITY_TYPE_HOME
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt
new file mode 100644
index 0000000..3b8d318
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.system
+
+import android.content.Context
+import android.hardware.devicestate.DeviceStateManager
+import com.android.systemui.unfold.updates.FoldProvider
+import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
+import java.util.concurrent.Executor
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class DeviceStateManagerFoldProvider @Inject constructor(
+ private val deviceStateManager: DeviceStateManager,
+ private val context: Context
+) : FoldProvider {
+
+ private val callbacks: MutableMap<FoldCallback,
+ DeviceStateManager.DeviceStateCallback> = hashMapOf()
+
+ override fun registerCallback(callback: FoldCallback, executor: Executor) {
+ val listener = FoldStateListener(context, callback)
+ deviceStateManager.registerCallback(executor, listener)
+ callbacks[callback] = listener
+ }
+
+ override fun unregisterCallback(callback: FoldCallback) {
+ val listener = callbacks.remove(callback)
+ listener?.let {
+ deviceStateManager.unregisterCallback(it)
+ }
+ }
+
+ private inner class FoldStateListener(
+ context: Context,
+ listener: FoldCallback
+ ) : DeviceStateManager.FoldStateListener(context, { listener.onFoldUpdated(it) })
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
new file mode 100644
index 0000000..24ae42a
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 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.system
+
+import android.os.Handler
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dagger.qualifiers.UiBackground
+import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.dagger.UnfoldBackground
+import com.android.systemui.unfold.dagger.UnfoldMain
+import com.android.systemui.unfold.updates.FoldProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
+import dagger.Binds
+import dagger.Module
+import java.util.concurrent.Executor
+
+/**
+ * Dagger module with system-only dependencies for the unfold animation.
+ * The code that is used to calculate unfold transition progress
+ * depends on some hidden APIs that are not available in normal
+ * apps. In order to re-use this code and use alternative implementations
+ * of these classes in other apps and hidden APIs here.
+ */
+@Module
+abstract class SystemUnfoldSharedModule {
+
+ @Binds
+ abstract fun activityTypeProvider(executor: ActivityManagerActivityTypeProvider):
+ CurrentActivityTypeProvider
+
+ @Binds
+ abstract fun config(config: ResourceUnfoldTransitionConfig): UnfoldTransitionConfig
+
+ @Binds
+ abstract fun foldState(provider: DeviceStateManagerFoldProvider): FoldProvider
+
+ @Binds
+ @UnfoldMain
+ abstract fun mainExecutor(@Main executor: Executor): Executor
+
+ @Binds
+ @UnfoldMain
+ abstract fun mainHandler(@Main handler: Handler): Handler
+
+ @Binds
+ @UnfoldBackground
+ abstract fun backgroundExecutor(@UiBackground executor: Executor): Executor
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
deleted file mode 100644
index b351585..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.android.systemui.unfold.updates.hinge
-
-import androidx.core.util.Consumer
-
-internal object EmptyHingeAngleProvider : HingeAngleProvider {
- override fun start() {}
-
- override fun stop() {}
-
- override fun removeCallback(listener: Consumer<Float>) {}
-
- override fun addCallback(listener: Consumer<Float>) {}
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
deleted file mode 100644
index 48a5b12..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.android.systemui.unfold.updates.hinge
-
-import androidx.core.util.Consumer
-import com.android.systemui.statusbar.policy.CallbackController
-
-/**
- * Emits device hinge angle values (angle between two integral parts of the device).
- *
- * The hinge angle could be from 0 to 360 degrees inclusive. For foldable devices usually 0
- * corresponds to fully closed (folded) state and 180 degrees corresponds to fully open (flat)
- * state.
- */
-interface HingeAngleProvider : CallbackController<Consumer<Float>> {
- fun start()
- fun stop()
-}
-
-const val FULLY_OPEN_DEGREES = 180f
-const val FULLY_CLOSED_DEGREES = 0f
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt
index 53c528f..ec938b2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2022 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.util
import android.content.Context
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index d2d2361..eea6ac0e 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -20,6 +20,7 @@
import android.view.IWindowManager
import com.android.systemui.keyguard.LifecycleScreenStatusProvider
import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.system.SystemUnfoldSharedModule
import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
@@ -34,7 +35,7 @@
import javax.inject.Named
import javax.inject.Singleton
-@Module(includes = [UnfoldSharedModule::class])
+@Module(includes = [UnfoldSharedModule::class, SystemUnfoldSharedModule::class])
class UnfoldTransitionModule {
@Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui"
@@ -62,11 +63,6 @@
@Provides
@Singleton
- fun provideUnfoldTransitionConfig(context: Context): UnfoldTransitionConfig =
- createConfig(context)
-
- @Provides
- @Singleton
fun provideNaturalRotationProgressProvider(
context: Context,
windowManager: IWindowManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 3231415..a4a89a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2022 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.shared.animation
import android.testing.AndroidTestingRunner
@@ -7,31 +21,24 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.Direction
import com.android.systemui.shared.animation.UnfoldConstantTranslateAnimator.ViewIdToTranslate
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.TestUnfoldTransitionProvider
import org.junit.Assert.assertEquals
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.`when` as whenever
import org.mockito.MockitoAnnotations
+import org.mockito.Mockito.`when` as whenever
@SmallTest
@RunWith(AndroidTestingRunner::class)
class UnfoldConstantTranslateAnimatorTest : SysuiTestCase() {
- @Mock private lateinit var progressProvider: UnfoldTransitionProgressProvider
+ private val progressProvider = TestUnfoldTransitionProvider()
@Mock private lateinit var parent: ViewGroup
- @Captor private lateinit var progressListenerCaptor: ArgumentCaptor<TransitionProgressListener>
-
private lateinit var animator: UnfoldConstantTranslateAnimator
- private lateinit var progressListener: TransitionProgressListener
private val viewsIdToRegister =
setOf(
@@ -46,17 +53,14 @@
UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
animator.init(parent, MAX_TRANSLATION)
-
- verify(progressProvider).addCallback(progressListenerCaptor.capture())
- progressListener = progressListenerCaptor.value
}
@Test
fun onTransition_noMatchingIds() {
// GIVEN no views matching any ids
// WHEN the transition starts
- progressListener.onTransitionStarted()
- progressListener.onTransitionProgress(.1f)
+ progressProvider.onTransitionStarted()
+ progressProvider.onTransitionProgress(.1f)
// THEN nothing... no exceptions
}
@@ -86,22 +90,22 @@
// Compare values as ints because -0f != 0f
// WHEN the transition starts
- progressListener.onTransitionStarted()
- progressListener.onTransitionProgress(0f)
+ progressProvider.onTransitionStarted()
+ progressProvider.onTransitionProgress(0f)
list.forEach { (view, direction) ->
assertEquals((-MAX_TRANSLATION * direction).toInt(), view.translationX.toInt())
}
// WHEN the transition progresses, translation is updated
- progressListener.onTransitionProgress(.5f)
+ progressProvider.onTransitionProgress(.5f)
list.forEach { (view, direction) ->
assertEquals((-MAX_TRANSLATION / 2f * direction).toInt(), view.translationX.toInt())
}
// WHEN the transition ends, translation is completed
- progressListener.onTransitionProgress(1f)
- progressListener.onTransitionFinished()
+ progressProvider.onTransitionProgress(1f)
+ progressProvider.onTransitionFinished()
list.forEach { (view, _) -> assertEquals(0, view.translationX.toInt()) }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 9ab88dc..ba29e95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -136,6 +136,7 @@
private class UnfoldConfig : UnfoldTransitionConfig {
override var isEnabled: Boolean = false
override var isHingeAngleEnabled: Boolean = false
+ override val halfFoldedTimeoutMillis: Int = 0
}
private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
index 8076b4e..39e4e64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
@@ -25,28 +25,20 @@
import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FoldStateProvider
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
+import com.android.systemui.unfold.util.TestFoldStateProvider
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
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.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class FoldStateLoggingProviderTest : SysuiTestCase() {
- @Captor
- private lateinit var foldUpdatesListener: ArgumentCaptor<FoldStateProvider.FoldUpdatesListener>
-
- @Mock private lateinit var foldStateProvider: FoldStateProvider
-
+ private val testFoldStateProvider = TestFoldStateProvider()
private val fakeClock = FakeSystemClock()
private lateinit var foldStateLoggingProvider: FoldStateLoggingProvider
@@ -65,12 +57,10 @@
MockitoAnnotations.initMocks(this)
foldStateLoggingProvider =
- FoldStateLoggingProviderImpl(foldStateProvider, fakeClock).apply {
+ FoldStateLoggingProviderImpl(testFoldStateProvider, fakeClock).apply {
addCallback(foldStateLoggingListener)
init()
}
-
- verify(foldStateProvider).addCallback(foldUpdatesListener.capture())
}
@Test
@@ -183,10 +173,10 @@
fun uninit_removesCallback() {
foldStateLoggingProvider.uninit()
- verify(foldStateProvider).removeCallback(foldUpdatesListener.value)
+ assertThat(testFoldStateProvider.hasListeners).isFalse()
}
private fun sendFoldUpdate(@FoldUpdate foldUpdate: Int) {
- foldUpdatesListener.value.onFoldUpdate(foldUpdate)
+ testFoldStateProvider.sendFoldUpdate(foldUpdate)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
new file mode 100644
index 0000000..ab450e2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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.config
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+
+/**
+ * A test that checks that we load correct resources in
+ * ResourceUnfoldTransitionConfig as we use strings there instead of R constants.
+ * Internal Android resource constants are not available in public APIs,
+ * so we can't use them there directly.
+ */
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class ResourceUnfoldTransitionConfigTest : SysuiTestCase() {
+
+ private val config = ResourceUnfoldTransitionConfig()
+
+ @Test
+ fun testIsEnabled() {
+ assertThat(config.isEnabled).isEqualTo(mContext.resources
+ .getBoolean(com.android.internal.R.bool.config_unfoldTransitionEnabled))
+ }
+
+ @Test
+ fun testHingeAngleEnabled() {
+ assertThat(config.isHingeAngleEnabled).isEqualTo(mContext.resources
+ .getBoolean(com.android.internal.R.bool.config_unfoldTransitionHingeAngle))
+ }
+
+ @Test
+ fun testHalfFoldedTimeout() {
+ assertThat(config.halfFoldedTimeoutMillis).isEqualTo(mContext.resources
+ .getInteger(com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout))
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 1f1f88b..87fca1f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -16,82 +16,69 @@
package com.android.systemui.unfold.updates
-import android.app.ActivityManager
-import android.app.ActivityManager.RunningTaskInfo
-import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
-import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
-import android.app.WindowConfiguration.ActivityType
-import android.hardware.devicestate.DeviceStateManager
-import android.hardware.devicestate.DeviceStateManager.FoldStateListener
import android.os.Handler
import android.testing.AndroidTestingRunner
import androidx.core.util.Consumer
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
+import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
-import com.android.systemui.unfold.util.FoldableDeviceStates
-import com.android.systemui.unfold.util.FoldableTestUtils
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
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.`when` as whenever
import org.mockito.MockitoAnnotations
+import java.util.concurrent.Executor
+import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidTestingRunner::class)
@SmallTest
class DeviceFoldStateProviderTest : SysuiTestCase() {
- @Mock private lateinit var hingeAngleProvider: HingeAngleProvider
+ @Mock
+ private lateinit var activityTypeProvider: ActivityManagerActivityTypeProvider
- @Mock private lateinit var screenStatusProvider: ScreenStatusProvider
+ @Mock
+ private lateinit var handler: Handler
- @Mock private lateinit var deviceStateManager: DeviceStateManager
-
- @Mock private lateinit var activityManager: ActivityManager
-
- @Mock private lateinit var handler: Handler
-
- @Captor private lateinit var foldStateListenerCaptor: ArgumentCaptor<FoldStateListener>
-
- @Captor private lateinit var screenOnListenerCaptor: ArgumentCaptor<ScreenListener>
-
- @Captor private lateinit var hingeAngleCaptor: ArgumentCaptor<Consumer<Float>>
+ private val foldProvider = TestFoldProvider()
+ private val screenOnStatusProvider = TestScreenOnStatusProvider()
+ private val testHingeAngleProvider = TestHingeAngleProvider()
private lateinit var foldStateProvider: DeviceFoldStateProvider
private val foldUpdates: MutableList<Int> = arrayListOf()
private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
- private lateinit var deviceStates: FoldableDeviceStates
-
private var scheduledRunnable: Runnable? = null
private var scheduledRunnableDelay: Long? = null
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- overrideResource(
- com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout,
- HALF_OPENED_TIMEOUT_MILLIS.toInt())
- deviceStates = FoldableTestUtils.findDeviceStates(context)
+
+ val config = object : UnfoldTransitionConfig by ResourceUnfoldTransitionConfig() {
+ override val halfFoldedTimeoutMillis: Int
+ get() = HALF_OPENED_TIMEOUT_MILLIS.toInt()
+ }
foldStateProvider =
DeviceFoldStateProvider(
- context,
- hingeAngleProvider,
- screenStatusProvider,
- deviceStateManager,
- activityManager,
+ config,
+ testHingeAngleProvider,
+ screenOnStatusProvider,
+ foldProvider,
+ activityTypeProvider,
context.mainExecutor,
- handler)
+ handler
+ )
foldStateProvider.addCallback(
object : FoldStateProvider.FoldUpdatesListener {
@@ -105,10 +92,6 @@
})
foldStateProvider.start()
- verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture())
- verify(screenStatusProvider).addCallback(screenOnListenerCaptor.capture())
- verify(hingeAngleProvider).addCallback(hingeAngleCaptor.capture())
-
whenever(handler.postDelayed(any<Runnable>(), any())).then { invocationOnMock ->
scheduledRunnable = invocationOnMock.getArgument<Runnable>(0)
scheduledRunnableDelay = invocationOnMock.getArgument<Long>(1)
@@ -125,7 +108,7 @@
}
// By default, we're on launcher.
- setupForegroundActivityType(ACTIVITY_TYPE_HOME)
+ setupForegroundActivityType(isHomeActivity = true)
}
@Test
@@ -146,14 +129,14 @@
fun testOnFolded_stopsHingeAngleProvider() {
setFoldState(folded = true)
- verify(hingeAngleProvider).stop()
+ assertThat(testHingeAngleProvider.isStarted).isFalse()
}
@Test
fun testOnUnfolded_startsHingeAngleProvider() {
setFoldState(folded = false)
- verify(hingeAngleProvider).start()
+ assertThat(testHingeAngleProvider.isStarted).isTrue()
}
@Test
@@ -310,7 +293,7 @@
@Test
fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
- setupForegroundActivityType(ACTIVITY_TYPE_STANDARD)
+ setupForegroundActivityType(isHomeActivity = false)
sendHingeAngleEvent(180)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
@@ -319,8 +302,28 @@
}
@Test
+ fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
+ setupForegroundActivityType(isHomeActivity = null)
+ sendHingeAngleEvent(180)
+
+ sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
+ fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
+ setupForegroundActivityType(isHomeActivity = true)
+ sendHingeAngleEvent(180)
+
+ sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
+
+ assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+ }
+
+ @Test
fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
- setupForegroundActivityType(ACTIVITY_TYPE_STANDARD)
+ setupForegroundActivityType(isHomeActivity = false)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
@@ -328,9 +331,8 @@
assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
}
- private fun setupForegroundActivityType(@ActivityType type: Int) {
- val taskInfo = RunningTaskInfo().apply { topActivityType = type }
- whenever(activityManager.getRunningTasks(1)).thenReturn(listOf(taskInfo))
+ private fun setupForegroundActivityType(isHomeActivity: Boolean?) {
+ whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
}
private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
@@ -348,16 +350,72 @@
}
private fun setFoldState(folded: Boolean) {
- val state = if (folded) deviceStates.folded else deviceStates.unfolded
- foldStateListenerCaptor.value.onStateChanged(state)
+ foldProvider.notifyFolded(folded)
}
private fun fireScreenOnEvent() {
- screenOnListenerCaptor.value.onScreenTurnedOn()
+ screenOnStatusProvider.notifyScreenTurnedOn()
}
private fun sendHingeAngleEvent(angle: Int) {
- hingeAngleCaptor.value.accept(angle.toFloat())
+ testHingeAngleProvider.notifyAngle(angle.toFloat())
+ }
+
+ private class TestFoldProvider : FoldProvider {
+ private val callbacks = arrayListOf<FoldCallback>()
+
+ override fun registerCallback(callback: FoldCallback, executor: Executor) {
+ callbacks += callback
+ }
+
+ override fun unregisterCallback(callback: FoldCallback) {
+ callbacks -= callback
+ }
+
+ fun notifyFolded(isFolded: Boolean) {
+ callbacks.forEach { it.onFoldUpdated(isFolded) }
+ }
+ }
+
+ private class TestScreenOnStatusProvider : ScreenStatusProvider {
+ private val callbacks = arrayListOf<ScreenListener>()
+
+ override fun addCallback(listener: ScreenListener) {
+ callbacks += listener
+ }
+
+ override fun removeCallback(listener: ScreenListener) {
+ callbacks -= listener
+ }
+
+ fun notifyScreenTurnedOn() {
+ callbacks.forEach { it.onScreenTurnedOn() }
+ }
+ }
+
+ private class TestHingeAngleProvider : HingeAngleProvider {
+ private val callbacks = arrayListOf<Consumer<Float>>()
+ var isStarted: Boolean = false
+
+ override fun start() {
+ isStarted = true;
+ }
+
+ override fun stop() {
+ isStarted = false;
+ }
+
+ override fun addCallback(listener: Consumer<Float>) {
+ callbacks += listener
+ }
+
+ override fun removeCallback(listener: Consumer<Float>) {
+ callbacks -= listener
+ }
+
+ fun notifyAngle(angle: Float) {
+ callbacks.forEach { it.accept(angle) }
+ }
}
companion object {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
index a3f17aa..b2cedbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
@@ -20,18 +20,18 @@
import android.view.IWindowManager
import android.view.Surface
import androidx.test.filters.SmallTest
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.unfold.TestUnfoldTransitionProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.util.mockito.any
-import com.android.systemui.SysuiTestCase
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
-import org.mockito.Mockito.verify
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -41,16 +41,13 @@
@Mock
lateinit var windowManager: IWindowManager
- @Mock
- lateinit var sourceProvider: UnfoldTransitionProgressProvider
+ private val sourceProvider = TestUnfoldTransitionProvider()
@Mock
lateinit var transitionListener: TransitionProgressListener
lateinit var progressProvider: NaturalRotationUnfoldProgressProvider
- private val sourceProviderListenerCaptor =
- ArgumentCaptor.forClass(TransitionProgressListener::class.java)
private val rotationWatcherCaptor =
ArgumentCaptor.forClass(IRotationWatcher.Stub::class.java)
@@ -66,7 +63,6 @@
progressProvider.init()
- verify(sourceProvider).addCallback(sourceProviderListenerCaptor.capture())
verify(windowManager).watchRotation(rotationWatcherCaptor.capture(), any())
progressProvider.addCallback(transitionListener)
@@ -76,7 +72,7 @@
fun testNaturalRotation0_sendTransitionStartedEvent_eventReceived() {
onRotationChanged(Surface.ROTATION_0)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
verify(transitionListener).onTransitionStarted()
}
@@ -85,7 +81,7 @@
fun testNaturalRotation0_sendTransitionProgressEvent_eventReceived() {
onRotationChanged(Surface.ROTATION_0)
- source.onTransitionProgress(0.5f)
+ sourceProvider.onTransitionProgress(0.5f)
verify(transitionListener).onTransitionProgress(0.5f)
}
@@ -94,7 +90,7 @@
fun testNotNaturalRotation90_sendTransitionStartedEvent_eventNotReceived() {
onRotationChanged(Surface.ROTATION_90)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
verify(transitionListener, never()).onTransitionStarted()
}
@@ -103,7 +99,7 @@
fun testNaturalRotation90_sendTransitionProgressEvent_eventNotReceived() {
onRotationChanged(Surface.ROTATION_90)
- source.onTransitionProgress(0.5f)
+ sourceProvider.onTransitionProgress(0.5f)
verify(transitionListener, never()).onTransitionProgress(0.5f)
}
@@ -111,7 +107,7 @@
@Test
fun testRotationBecameUnnaturalDuringTransition_sendsTransitionFinishedEvent() {
onRotationChanged(Surface.ROTATION_0)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
clearInvocations(transitionListener)
onRotationChanged(Surface.ROTATION_90)
@@ -122,7 +118,7 @@
@Test
fun testRotationBecameNaturalDuringTransition_sendsTransitionStartedEvent() {
onRotationChanged(Surface.ROTATION_90)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
clearInvocations(transitionListener)
onRotationChanged(Surface.ROTATION_0)
@@ -133,7 +129,4 @@
private fun onRotationChanged(rotation: Int) {
rotationWatcherCaptor.value.onRotationChanged(rotation)
}
-
- private val source: TransitionProgressListener
- get() = sourceProviderListenerCaptor.value
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
index db7a8516..fc2a78a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
@@ -21,6 +21,7 @@
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.unfold.TestUnfoldTransitionProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
import com.android.systemui.util.mockito.any
@@ -41,15 +42,11 @@
lateinit var contentResolver: ContentResolver
@Mock
- lateinit var sourceProvider: UnfoldTransitionProgressProvider
-
- @Mock
lateinit var sinkProvider: TransitionProgressListener
- lateinit var progressProvider: ScaleAwareTransitionProgressProvider
+ private val sourceProvider = TestUnfoldTransitionProvider()
- private val sourceProviderListenerCaptor =
- ArgumentCaptor.forClass(TransitionProgressListener::class.java)
+ lateinit var progressProvider: ScaleAwareTransitionProgressProvider
private val animatorDurationScaleListenerCaptor =
ArgumentCaptor.forClass(ContentObserver::class.java)
@@ -63,7 +60,6 @@
contentResolver
)
- verify(sourceProvider).addCallback(sourceProviderListenerCaptor.capture())
verify(contentResolver).registerContentObserver(any(), any(),
animatorDurationScaleListenerCaptor.capture())
@@ -74,7 +70,7 @@
fun onTransitionStarted_animationsEnabled_eventReceived() {
setAnimationsEnabled(true)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
verify(sinkProvider).onTransitionStarted()
}
@@ -83,7 +79,7 @@
fun onTransitionStarted_animationsNotEnabled_eventNotReceived() {
setAnimationsEnabled(false)
- source.onTransitionStarted()
+ sourceProvider.onTransitionStarted()
verifyNoMoreInteractions(sinkProvider)
}
@@ -92,7 +88,7 @@
fun onTransitionEnd_animationsEnabled_eventReceived() {
setAnimationsEnabled(true)
- source.onTransitionFinished()
+ sourceProvider.onTransitionFinished()
verify(sinkProvider).onTransitionFinished()
}
@@ -101,7 +97,7 @@
fun onTransitionEnd_animationsNotEnabled_eventNotReceived() {
setAnimationsEnabled(false)
- source.onTransitionFinished()
+ sourceProvider.onTransitionFinished()
verifyNoMoreInteractions(sinkProvider)
}
@@ -110,7 +106,7 @@
fun onTransitionProgress_animationsEnabled_eventReceived() {
setAnimationsEnabled(true)
- source.onTransitionProgress(42f)
+ sourceProvider.onTransitionProgress(42f)
verify(sinkProvider).onTransitionProgress(42f)
}
@@ -119,7 +115,7 @@
fun onTransitionProgress_animationsNotEnabled_eventNotReceived() {
setAnimationsEnabled(false)
- source.onTransitionProgress(42f)
+ sourceProvider.onTransitionProgress(42f)
verifyNoMoreInteractions(sinkProvider)
}
@@ -133,7 +129,4 @@
ValueAnimator.setDurationScale(durationScale)
animatorDurationScaleListenerCaptor.value.dispatchChange(/* selfChange= */false)
}
-
- private val source: TransitionProgressListener
- get() = sourceProviderListenerCaptor.value
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index 8f851ec..a064e8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -24,6 +24,8 @@
class TestFoldStateProvider : FoldStateProvider {
private val listeners: MutableList<FoldUpdatesListener> = arrayListOf()
+ val hasListeners: Boolean
+ get() = listeners.isNotEmpty()
override fun start() {
}
diff --git a/packages/SystemUI/unfold/Android.bp b/packages/SystemUI/unfold/Android.bp
new file mode 100644
index 0000000..108295b
--- /dev/null
+++ b/packages/SystemUI/unfold/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_library {
+ name: "SystemUIUnfoldLib",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ "src/**/*.aidl",
+ ],
+ static_libs: [
+ "androidx.dynamicanimation_dynamicanimation",
+ "dagger2",
+ "jsr330",
+ ],
+ java_version: "1.8",
+ min_sdk_version: "current",
+ plugins: ["dagger2-compiler"],
+}
diff --git a/packages/SystemUI/unfold/AndroidManifest.xml b/packages/SystemUI/unfold/AndroidManifest.xml
new file mode 100644
index 0000000..ee8afe1
--- /dev/null
+++ b/packages/SystemUI/unfold/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.unfold">
+
+
+</manifest>
diff --git a/packages/SystemUI/unfold/lint-baseline.xml b/packages/SystemUI/unfold/lint-baseline.xml
new file mode 100644
index 0000000..449ed2e
--- /dev/null
+++ b/packages/SystemUI/unfold/lint-baseline.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" name="" variant="all" version="7.1.0-dev">
+</issues>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
similarity index 79%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
index 9e5aeb8..a5ec0a4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedComponent.kt
@@ -16,16 +16,16 @@
package com.android.systemui.unfold
-import android.app.ActivityManager
import android.content.ContentResolver
import android.content.Context
import android.hardware.SensorManager
-import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.dagger.UnfoldBackground
+import com.android.systemui.unfold.dagger.UnfoldMain
+import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix
import dagger.BindsInstance
import dagger.Component
@@ -51,12 +51,12 @@
@BindsInstance context: Context,
@BindsInstance config: UnfoldTransitionConfig,
@BindsInstance screenStatusProvider: ScreenStatusProvider,
- @BindsInstance deviceStateManager: DeviceStateManager,
- @BindsInstance activityManager: ActivityManager,
+ @BindsInstance foldProvider: FoldProvider,
+ @BindsInstance activityTypeProvider: CurrentActivityTypeProvider,
@BindsInstance sensorManager: SensorManager,
- @BindsInstance @Main handler: Handler,
- @BindsInstance @Main executor: Executor,
- @BindsInstance @UiBackground backgroundExecutor: Executor,
+ @BindsInstance @UnfoldMain handler: Handler,
+ @BindsInstance @UnfoldMain executor: Executor,
+ @BindsInstance @UnfoldBackground backgroundExecutor: Executor,
@BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String,
@BindsInstance contentResolver: ContentResolver = context.contentResolver
): UnfoldSharedComponent
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
similarity index 96%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
index c612995..8f4ee4d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
@@ -17,8 +17,8 @@
package com.android.systemui.unfold
import android.hardware.SensorManager
-import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.dagger.UnfoldBackground
import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider
import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider
import com.android.systemui.unfold.updates.DeviceFoldStateProvider
@@ -70,7 +70,7 @@
fun hingeAngleProvider(
config: UnfoldTransitionConfig,
sensorManager: SensorManager,
- @UiBackground executor: Executor
+ @UnfoldBackground executor: Executor
): HingeAngleProvider =
if (config.isHingeAngleEnabled) {
HingeSensorAngleProvider(sensorManager, executor)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
similarity index 83%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
index cc56007c..402dd84 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
@@ -17,14 +17,13 @@
package com.android.systemui.unfold
-import android.app.ActivityManager
import android.content.Context
import android.hardware.SensorManager
-import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
-import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig
import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.updates.FoldProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import java.util.concurrent.Executor
/**
@@ -39,8 +38,8 @@
context: Context,
config: UnfoldTransitionConfig,
screenStatusProvider: ScreenStatusProvider,
- deviceStateManager: DeviceStateManager,
- activityManager: ActivityManager,
+ foldProvider: FoldProvider,
+ activityTypeProvider: CurrentActivityTypeProvider,
sensorManager: SensorManager,
mainHandler: Handler,
mainExecutor: Executor,
@@ -52,8 +51,8 @@
context,
config,
screenStatusProvider,
- deviceStateManager,
- activityManager,
+ foldProvider,
+ activityTypeProvider,
sensorManager,
mainHandler,
mainExecutor,
@@ -64,5 +63,3 @@
?: throw IllegalStateException(
"Trying to create " +
"UnfoldTransitionProgressProvider when the transition is disabled")
-
-fun createConfig(context: Context): UnfoldTransitionConfig = ResourceUnfoldTransitionConfig(context)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
similarity index 93%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
index 409dc95..d54481c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
@@ -15,9 +15,9 @@
*/
package com.android.systemui.unfold
-import android.annotation.FloatRange
-import com.android.systemui.statusbar.policy.CallbackController
+import androidx.annotation.FloatRange
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.util.CallbackController
/**
* Interface that allows to receive unfold transition progress updates.
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
new file mode 100644
index 0000000..2044f05
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.compat
+
+import android.content.Context
+import android.content.res.Configuration
+import com.android.systemui.unfold.updates.FoldProvider
+import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
+import java.util.concurrent.Executor
+
+/**
+ * Fold provider that notifies about fold state based on the screen size
+ * It could be used when no activity context is available
+ * TODO(b/232369816): use Jetpack WM library when non-activity contexts supported b/169740873
+ */
+class ScreenSizeFoldProvider(private val context: Context) : FoldProvider {
+
+ private var callbacks: MutableList<FoldCallback> = arrayListOf()
+ private var lastWidth: Int = 0
+
+ override fun registerCallback(callback: FoldCallback, executor: Executor) {
+ callbacks += callback
+ onConfigurationChange(context.resources.configuration)
+ }
+
+ override fun unregisterCallback(callback: FoldCallback) {
+ callbacks -= callback
+ }
+
+ fun onConfigurationChange(newConfig: Configuration) {
+ if (lastWidth == newConfig.smallestScreenWidthDp) {
+ return
+ }
+
+ if (newConfig.smallestScreenWidthDp > INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP) {
+ callbacks.forEach { it.onFoldUpdated(false) }
+ } else {
+ callbacks.forEach { it.onFoldUpdated(true) }
+ }
+ lastWidth = newConfig.smallestScreenWidthDp
+ }
+}
+
+private const val INNER_SCREEN_SMALLEST_SCREEN_WIDTH_THRESHOLD_DP = 600
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
new file mode 100644
index 0000000..c405f31
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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.compat
+
+import com.android.systemui.unfold.updates.FoldProvider
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
+import java.util.concurrent.Executor
+
+class SizeScreenStatusProvider(
+ private val foldProvider: FoldProvider,
+ private val executor: Executor
+) : ScreenStatusProvider {
+
+ private val listeners: MutableList<ScreenListener> = arrayListOf()
+ private val callback = object : FoldProvider.FoldCallback {
+ override fun onFoldUpdated(isFolded: Boolean) {
+ if (!isFolded) {
+ listeners.forEach { it.onScreenTurnedOn() }
+ }
+ }
+ }
+
+ fun start() {
+ foldProvider.registerCallback(
+ callback,
+ executor
+ )
+ }
+
+ fun stop() {
+ foldProvider.unregisterCallback(callback)
+ }
+
+ override fun addCallback(listener: ScreenListener) {
+ listeners.add(listener)
+ }
+
+ override fun removeCallback(listener: ScreenListener) {
+ listeners.remove(listener)
+ }
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
new file mode 100644
index 0000000..c513729
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.config
+
+import android.content.res.Resources
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class ResourceUnfoldTransitionConfig @Inject constructor() : UnfoldTransitionConfig {
+
+ override val isEnabled: Boolean by lazy {
+ val id = Resources.getSystem()
+ .getIdentifier("config_unfoldTransitionEnabled", "bool", "android")
+ Resources.getSystem().getBoolean(id)
+ }
+
+ override val isHingeAngleEnabled: Boolean by lazy {
+ val id = Resources.getSystem()
+ .getIdentifier("config_unfoldTransitionHingeAngle", "bool", "android")
+ Resources.getSystem().getBoolean(id)
+ }
+
+ override val halfFoldedTimeoutMillis: Int by lazy {
+ val id = Resources.getSystem()
+ .getIdentifier("config_unfoldTransitionHalfFoldedTimeout", "integer", "android")
+ Resources.getSystem().getInteger(id)
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
similarity index 95%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
index 5b187b3..765e862 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/config/UnfoldTransitionConfig.kt
@@ -18,4 +18,5 @@
interface UnfoldTransitionConfig {
val isEnabled: Boolean
val isHingeAngleEnabled: Boolean
+ val halfFoldedTimeoutMillis: Int
}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
new file mode 100644
index 0000000..6074795
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 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.dagger
+
+import javax.inject.Qualifier
+
+/**
+ * Alternative to [UiBackground] qualifier annotation in unfold module.
+ * It is needed as we can't depend on SystemUI code in this module.
+ */
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class UnfoldBackground
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
new file mode 100644
index 0000000..5553690f
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 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.dagger
+
+import javax.inject.Qualifier
+
+/**
+ * Alternative to [Main] qualifier annotation in unfold module.
+ * It is needed as we can't depend on SystemUI code in this module.
+ */
+@Qualifier
+@Retention(AnnotationRetention.RUNTIME)
+annotation class UnfoldMain
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
similarity index 100%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 04d920c..2ab28c6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -16,7 +16,6 @@
package com.android.systemui.unfold.progress
import android.util.Log
-import android.util.MathUtils.saturate
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringAnimation
@@ -70,6 +69,9 @@
springAnimation.animateToFinalPosition(progress)
}
+ private fun saturate(amount: Float, low: Float = 0f, high: Float = 1f): Float =
+ if (amount < low) low else if (amount > high) high else amount
+
override fun onFoldUpdate(@FoldUpdate update: Int) {
when (update) {
FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
similarity index 74%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 14581cc..e8038fd 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -15,46 +15,46 @@
*/
package com.android.systemui.unfold.updates
-import android.annotation.FloatRange
-import android.app.ActivityManager
-import android.app.WindowConfiguration.ACTIVITY_TYPE_HOME
-import android.content.Context
-import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import android.util.Log
+import androidx.annotation.FloatRange
import androidx.annotation.VisibleForTesting
import androidx.core.util.Consumer
-import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.dagger.UnfoldMain
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
import com.android.systemui.unfold.updates.hinge.FULLY_CLOSED_DEGREES
import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
+import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import java.util.concurrent.Executor
import javax.inject.Inject
class DeviceFoldStateProvider
@Inject
constructor(
- context: Context,
+ config: UnfoldTransitionConfig,
private val hingeAngleProvider: HingeAngleProvider,
private val screenStatusProvider: ScreenStatusProvider,
- private val deviceStateManager: DeviceStateManager,
- private val activityManager: ActivityManager,
- @Main private val mainExecutor: Executor,
- @Main private val handler: Handler
+ private val foldProvider: FoldProvider,
+ private val activityTypeProvider: CurrentActivityTypeProvider,
+ @UnfoldMain private val mainExecutor: Executor,
+ @UnfoldMain private val handler: Handler
) : FoldStateProvider {
private val outputListeners: MutableList<FoldUpdatesListener> = mutableListOf()
- @FoldUpdate private var lastFoldUpdate: Int? = null
+ @FoldUpdate
+ private var lastFoldUpdate: Int? = null
- @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+ @FloatRange(from = 0.0, to = 180.0)
+ private var lastHingeAngle: Float = 0f
private val hingeAngleListener = HingeAngleListener()
private val screenListener = ScreenStatusListener()
- private val foldStateListener = FoldStateListener(context)
+ private val foldStateListener = FoldStateListener()
private val timeoutRunnable = TimeoutRunnable()
/**
@@ -62,22 +62,20 @@
* [FOLD_UPDATE_START_CLOSING] or [FOLD_UPDATE_START_OPENING] event, if an end state is not
* reached.
*/
- private val halfOpenedTimeoutMillis: Int =
- context.resources.getInteger(
- com.android.internal.R.integer.config_unfoldTransitionHalfFoldedTimeout)
+ private val halfOpenedTimeoutMillis: Int = config.halfFoldedTimeoutMillis
private var isFolded = false
private var isUnfoldHandled = true
override fun start() {
- deviceStateManager.registerCallback(mainExecutor, foldStateListener)
+ foldProvider.registerCallback(foldStateListener, mainExecutor)
screenStatusProvider.addCallback(screenListener)
hingeAngleProvider.addCallback(hingeAngleListener)
}
override fun stop() {
screenStatusProvider.removeCallback(screenListener)
- deviceStateManager.unregisterCallback(foldStateListener)
+ foldProvider.unregisterCallback(foldStateListener)
hingeAngleProvider.removeCallback(hingeAngleListener)
hingeAngleProvider.stop()
}
@@ -92,13 +90,13 @@
override val isFinishedOpening: Boolean
get() = !isFolded &&
- (lastFoldUpdate == FOLD_UPDATE_FINISH_FULL_OPEN ||
- lastFoldUpdate == FOLD_UPDATE_FINISH_HALF_OPEN)
+ (lastFoldUpdate == FOLD_UPDATE_FINISH_FULL_OPEN ||
+ lastFoldUpdate == FOLD_UPDATE_FINISH_HALF_OPEN)
private val isTransitionInProgress: Boolean
get() =
lastFoldUpdate == FOLD_UPDATE_START_OPENING ||
- lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+ lastFoldUpdate == FOLD_UPDATE_START_CLOSING
private fun onHingeAngle(angle: Float) {
if (DEBUG) {
@@ -136,39 +134,36 @@
* apps that support table-top/HALF_FOLDED mode. Only for launcher, there is no threshold.
*/
private fun getClosingThreshold(): Int? {
- val activityType =
- activityManager.getRunningTasks(/* maxNum= */ 1)?.getOrNull(0)?.topActivityType
- ?: return null
+ val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null
if (DEBUG) {
- Log.d(TAG, "activityType=" + activityType)
+ Log.d(TAG, "isHomeActivity=$isHomeActivity")
}
- return if (activityType == ACTIVITY_TYPE_HOME) {
+ return if (isHomeActivity) {
null
} else {
START_CLOSING_ON_APPS_THRESHOLD_DEGREES
}
}
- private inner class FoldStateListener(context: Context) :
- DeviceStateManager.FoldStateListener(
- context,
- { folded: Boolean ->
- isFolded = folded
- lastHingeAngle = FULLY_CLOSED_DEGREES
+ private inner class FoldStateListener : FoldProvider.FoldCallback {
+ override fun onFoldUpdated(isFolded: Boolean) {
+ this@DeviceFoldStateProvider.isFolded = isFolded
+ lastHingeAngle = FULLY_CLOSED_DEGREES
- if (folded) {
- hingeAngleProvider.stop()
- notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
- cancelTimeout()
- isUnfoldHandled = false
- } else {
- notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
- rescheduleAbortAnimationTimeout()
- hingeAngleProvider.start()
- }
- })
+ if (isFolded) {
+ hingeAngleProvider.stop()
+ notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+ cancelTimeout()
+ isUnfoldHandled = false
+ } else {
+ notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+ rescheduleAbortAnimationTimeout()
+ hingeAngleProvider.start()
+ }
+ }
+ }
private fun notifyFoldUpdate(@FoldUpdate update: Int) {
if (DEBUG) {
@@ -234,7 +229,9 @@
private const val DEBUG = false
/** Threshold after which we consider the device fully unfolded. */
-@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
+@VisibleForTesting
+const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
/** Fold animation on top of apps only when the angle exceeds this threshold. */
-@VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
+@VisibleForTesting
+const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldProvider.kt
new file mode 100644
index 0000000..6e87bee
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldProvider.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.updates
+
+import java.util.concurrent.Executor
+
+interface FoldProvider {
+ fun registerCallback(callback: FoldCallback, executor: Executor)
+ fun unregisterCallback(callback: FoldCallback)
+
+ interface FoldCallback {
+ fun onFoldUpdated(isFolded: Boolean)
+ }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
similarity index 91%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index 14a3a70..c7a8bf3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -15,10 +15,10 @@
*/
package com.android.systemui.unfold.updates
-import android.annotation.FloatRange
-import android.annotation.IntDef
-import com.android.systemui.statusbar.policy.CallbackController
+import androidx.annotation.FloatRange
+import androidx.annotation.IntDef
import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
+import com.android.systemui.unfold.util.CallbackController
/**
* Allows to subscribe to main events related to fold/unfold process such as hinge angle update,
@@ -36,7 +36,6 @@
}
@IntDef(
- prefix = ["FOLD_UPDATE_"],
value =
[
FOLD_UPDATE_START_OPENING,
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
new file mode 100644
index 0000000..e985506
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/EmptyHingeAngleProvider.kt
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 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.updates.hinge
+
+import androidx.core.util.Consumer
+
+internal object EmptyHingeAngleProvider : HingeAngleProvider {
+ override fun start() {}
+
+ override fun stop() {}
+
+ override fun removeCallback(listener: Consumer<Float>) {}
+
+ override fun addCallback(listener: Consumer<Float>) {}
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
new file mode 100644
index 0000000..e464c3f
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeAngleProvider.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.updates.hinge
+
+import androidx.core.util.Consumer
+import com.android.systemui.unfold.util.CallbackController
+
+/**
+ * Emits device hinge angle values (angle between two integral parts of the device).
+ *
+ * The hinge angle could be from 0 to 360 degrees inclusive. For foldable devices usually 0
+ * corresponds to fully closed (folded) state and 180 degrees corresponds to fully open (flat)
+ * state.
+ */
+interface HingeAngleProvider : CallbackController<Consumer<Float>> {
+ fun start()
+ fun stop()
+}
+
+const val FULLY_OPEN_DEGREES = 180f
+const val FULLY_CLOSED_DEGREES = 0f
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
similarity index 71%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
index c93412b..3fc5d61 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2022 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.updates.hinge
import android.hardware.Sensor
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
similarity index 93%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
index 668c694..d95e050 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
@@ -15,8 +15,8 @@
*/
package com.android.systemui.unfold.updates.screen
-import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
+import com.android.systemui.unfold.util.CallbackController
interface ScreenStatusProvider : CallbackController<ScreenListener> {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt
similarity index 65%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt
index 1574c8d..d8bc018 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2022 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.util
import android.os.Trace
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CallbackController.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CallbackController.kt
new file mode 100644
index 0000000..46ad534
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CallbackController.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 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.util
+
+interface CallbackController<T> {
+ fun addCallback(listener: T)
+ fun removeCallback(listener: T)
+}
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
new file mode 100644
index 0000000..d0e6cdc
--- /dev/null
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/CurrentActivityTypeProvider.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 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.util
+
+interface CurrentActivityTypeProvider {
+ val isHomeActivity: Boolean?
+}
+
+class EmptyCurrentActivityTypeProvider(override val isHomeActivity: Boolean? = null) :
+ CurrentActivityTypeProvider
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
similarity index 78%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
index dfe8792..5c92b34 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
@@ -1,3 +1,17 @@
+/*
+ * Copyright (C) 2022 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.util
import android.animation.ValueAnimator
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
similarity index 100%
rename from packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
rename to packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt