From 6fb25a666517964fdb839c90e5050d8a187eba9c Mon Sep 17 00:00:00 2001 From: Nicolo' Mazzucato Date: Mon, 10 Jan 2022 19:56:02 +0100 Subject: [PATCH] Enhance dagger usage in UnfoldSharedModule UnfoldTransitionProgressProvider is used in sysui and in other places that don't use dagger (e.g. Launcher). However, we want to use dagger for all unfold transition related classes. The solution in this cl is to create FoldSharedComponent. If an app that doesn't use dagger need UnfoldTransitionProgressProvider (or other shared classes), it can create the component with the factory, and get those object (now created by dagger, previously manually created). If the app uses dagger, UnfoldSharedModule should be used instead. The external interface is not changed in this cl: createUnfoldTransitionProgressProvider is left as it was before, therefore launcher doesn't require any change and continues to work as before. Test: atest com.android.systemui.unfold Test: Manually tested Bug: 213908821 Change-Id: I22885ec15fed99254405e26ed2fe99a9567625b6 --- packages/SystemUI/shared/Android.bp | 3 + .../systemui/dagger/qualifiers/Main.java | 0 .../systemui/unfold/UnfoldSharedComponent.kt | 62 +++++++++++++++ .../systemui/unfold/UnfoldSharedModule.kt | 77 +++++++++++++++++++ .../unfold/UnfoldTransitionFactory.kt | 75 ++++-------------- .../unfold/updates/DeviceFoldStateProvider.kt | 10 ++- .../updates/hinge/EmptyHingeAngleProvider.kt | 2 +- ...ATraceLoggerTransitionProgressListener.kt} | 9 ++- .../ScaleAwareTransitionProgressProvider.kt | 18 ++++- .../systemui/unfold/UnfoldTransitionModule.kt | 72 ++++------------- 10 files changed, 200 insertions(+), 128 deletions(-) rename packages/SystemUI/{ => shared}/src/com/android/systemui/dagger/qualifiers/Main.java (100%) create mode 100644 packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt create mode 100644 packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt rename packages/SystemUI/shared/src/com/android/systemui/unfold/util/{ATraceLoggerTransitionProgressProvider.kt => ATraceLoggerTransitionProgressListener.kt} (76%) diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp index d172006d986d8..3cf5bc1bf13a9 100644 --- a/packages/SystemUI/shared/Android.bp +++ b/packages/SystemUI/shared/Android.bp @@ -49,9 +49,12 @@ android_library { "PluginCoreLib", "androidx.dynamicanimation_dynamicanimation", "androidx.concurrent_concurrent-futures", + "dagger2", + "jsr330", ], java_version: "1.8", min_sdk_version: "current", + plugins: ["dagger2-compiler"], } java_library { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Main.java b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Main.java similarity index 100% rename from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/Main.java rename to packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/Main.java diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt new file mode 100644 index 0000000000000..ac62cf9f9d5bb --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedComponent.kt @@ -0,0 +1,62 @@ +/* + * 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 + +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.unfold.config.UnfoldTransitionConfig +import com.android.systemui.unfold.updates.screen.ScreenStatusProvider +import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix +import dagger.BindsInstance +import dagger.Component +import java.util.Optional +import java.util.concurrent.Executor +import javax.inject.Singleton + +/** + * Provides [UnfoldTransitionProgressProvider]. The [Optional] is empty when the transition + * animation is disabled. + * + * This component is meant to be used for places that don't use dagger. By providing those + * parameters to the factory, all dagger objects are correctly instantiated. See + * [createUnfoldTransitionProgressProvider] for an example. + */ +@Singleton +@Component(modules = [UnfoldSharedModule::class]) +internal interface UnfoldSharedComponent { + + @Component.Factory + interface Factory { + fun create( + @BindsInstance context: Context, + @BindsInstance config: UnfoldTransitionConfig, + @BindsInstance screenStatusProvider: ScreenStatusProvider, + @BindsInstance deviceStateManager: DeviceStateManager, + @BindsInstance sensorManager: SensorManager, + @BindsInstance @Main handler: Handler, + @BindsInstance @Main executor: Executor, + @BindsInstance @UnfoldTransitionATracePrefix tracingTagPrefix: String, + @BindsInstance contentResolver: ContentResolver = context.contentResolver + ): UnfoldSharedComponent + } + + val unfoldTransitionProvider: Optional +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt new file mode 100644 index 0000000000000..23e4c97fc2713 --- /dev/null +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldSharedModule.kt @@ -0,0 +1,77 @@ +/* + * 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 + +import android.hardware.SensorManager +import com.android.systemui.unfold.config.UnfoldTransitionConfig +import com.android.systemui.unfold.progress.FixedTimingTransitionProgressProvider +import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider +import com.android.systemui.unfold.updates.DeviceFoldStateProvider +import com.android.systemui.unfold.updates.FoldStateProvider +import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider +import com.android.systemui.unfold.updates.hinge.HingeAngleProvider +import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider +import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener +import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider +import dagger.Module +import dagger.Provides +import java.util.Optional +import javax.inject.Singleton + +@Module +class UnfoldSharedModule { + @Provides + @Singleton + fun unfoldTransitionProgressProvider( + config: UnfoldTransitionConfig, + scaleAwareProviderFactory: ScaleAwareTransitionProgressProvider.Factory, + tracingListener: ATraceLoggerTransitionProgressListener, + foldStateProvider: FoldStateProvider + ): Optional = + if (!config.isEnabled) { + Optional.empty() + } else { + val baseProgressProvider = + if (config.isHingeAngleEnabled) { + PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider) + } else { + FixedTimingTransitionProgressProvider(foldStateProvider) + } + Optional.of( + scaleAwareProviderFactory.wrap(baseProgressProvider).apply { + // Always present callback that logs animation beginning and end. + addCallback(tracingListener) + }) + } + + @Provides + @Singleton + fun provideFoldStateProvider( + deviceFoldStateProvider: DeviceFoldStateProvider + ): FoldStateProvider = deviceFoldStateProvider + + @Provides + fun hingeAngleProvider( + config: UnfoldTransitionConfig, + sensorManager: SensorManager + ): HingeAngleProvider = + if (config.isHingeAngleEnabled) { + HingeSensorAngleProvider(sensorManager) + } else { + EmptyHingeAngleProvider + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt index 953b0e0183069..d5d636208747c 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt @@ -23,22 +23,16 @@ 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.progress.FixedTimingTransitionProgressProvider -import com.android.systemui.unfold.progress.PhysicsBasedUnfoldTransitionProgressProvider -import com.android.systemui.unfold.updates.DeviceFoldStateProvider -import com.android.systemui.unfold.updates.FoldStateProvider -import com.android.systemui.unfold.updates.hinge.EmptyHingeAngleProvider -import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider import com.android.systemui.unfold.updates.screen.ScreenStatusProvider -import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener -import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider import java.util.concurrent.Executor /** * Factory for [UnfoldTransitionProgressProvider]. * - * This is needed as Launcher has to create the object manually. Sysui create it using dagger (see - * [UnfoldTransitionModule]). + * This is needed as Launcher has to create the object manually. If dagger is available, this object + * is provided in [UnfoldSharedModule]. + * + * This should **never** be called from sysui, as the object is already provided in that process. */ fun createUnfoldTransitionProgressProvider( context: Context, @@ -49,62 +43,21 @@ fun createUnfoldTransitionProgressProvider( mainHandler: Handler, mainExecutor: Executor, tracingTagPrefix: String -): UnfoldTransitionProgressProvider { - - if (!config.isEnabled) { - throw IllegalStateException( - "Trying to create " + - "UnfoldTransitionProgressProvider when the transition is disabled") - } - - val foldStateProvider = - createFoldStateProvider( +): UnfoldTransitionProgressProvider = + DaggerUnfoldSharedComponent.factory() + .create( context, config, screenStatusProvider, deviceStateManager, sensorManager, mainHandler, - mainExecutor) - - val unfoldTransitionProgressProvider = - if (config.isHingeAngleEnabled) { - PhysicsBasedUnfoldTransitionProgressProvider(foldStateProvider) - } else { - FixedTimingTransitionProgressProvider(foldStateProvider) - } - - return ScaleAwareTransitionProgressProvider( - unfoldTransitionProgressProvider, context.contentResolver) - .apply { - // Always present callback that logs animation beginning and end. - addCallback(ATraceLoggerTransitionProgressListener(tracingTagPrefix)) - } -} - -fun createFoldStateProvider( - context: Context, - config: UnfoldTransitionConfig, - screenStatusProvider: ScreenStatusProvider, - deviceStateManager: DeviceStateManager, - sensorManager: SensorManager, - mainHandler: Handler, - mainExecutor: Executor -): FoldStateProvider { - val hingeAngleProvider = - if (config.isHingeAngleEnabled) { - HingeSensorAngleProvider(sensorManager) - } else { - EmptyHingeAngleProvider() - } - - return DeviceFoldStateProvider( - context, - hingeAngleProvider, - screenStatusProvider, - deviceStateManager, - mainExecutor, - mainHandler) -} + mainExecutor, + tracingTagPrefix) + .unfoldTransitionProvider + .orElse(null) + ?: 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/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt index cd1ea215ccdd5..204ae09b48525 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt @@ -22,6 +22,7 @@ import android.os.Handler import android.util.Log import androidx.annotation.VisibleForTesting import androidx.core.util.Consumer +import com.android.systemui.dagger.qualifiers.Main 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 @@ -29,14 +30,17 @@ 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 java.util.concurrent.Executor +import javax.inject.Inject -class DeviceFoldStateProvider( +class DeviceFoldStateProvider +@Inject +constructor( context: Context, private val hingeAngleProvider: HingeAngleProvider, private val screenStatusProvider: ScreenStatusProvider, private val deviceStateManager: DeviceStateManager, - private val mainExecutor: Executor, - private val handler: Handler + @Main private val mainExecutor: Executor, + @Main private val handler: Handler ) : FoldStateProvider { private val outputListeners: MutableList = mutableListOf() 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 index 9b58b1fcad467..4ca1a531fc259 100644 --- 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 @@ -2,7 +2,7 @@ package com.android.systemui.unfold.updates.hinge import androidx.core.util.Consumer -internal class EmptyHingeAngleProvider : HingeAngleProvider { +internal object EmptyHingeAngleProvider : HingeAngleProvider { override fun start() { } diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt similarity index 76% rename from packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressProvider.kt rename to packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt index f3eeb3210ece7..1574c8d37ab11 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ATraceLoggerTransitionProgressListener.kt @@ -2,6 +2,8 @@ package com.android.systemui.unfold.util import android.os.Trace import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import javax.inject.Inject +import javax.inject.Qualifier /** * Listener that logs start and end of the fold-unfold transition. @@ -9,7 +11,10 @@ import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionPr * [tracePrefix] arg helps in differentiating those. Currently, this is expected to be logged twice * for each fold/unfold: in (1) systemui and (2) launcher process. */ -class ATraceLoggerTransitionProgressListener(tracePrefix: String) : TransitionProgressListener { +class ATraceLoggerTransitionProgressListener +@Inject +internal constructor(@UnfoldTransitionATracePrefix tracePrefix: String) : + TransitionProgressListener { private val traceName = "$tracePrefix#$UNFOLD_TRANSITION_TRACE_NAME" @@ -27,3 +32,5 @@ class ATraceLoggerTransitionProgressListener(tracePrefix: String) : TransitionPr } private const val UNFOLD_TRANSITION_TRACE_NAME = "FoldUnfoldTransitionInProgress" + +@Qualifier annotation class UnfoldTransitionATracePrefix diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt index df9078a15520e..ee79b8761059a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt @@ -6,15 +6,20 @@ import android.database.ContentObserver import android.provider.Settings import com.android.systemui.unfold.UnfoldTransitionProgressProvider import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject /** Wraps [UnfoldTransitionProgressProvider] to disable transitions when animations are disabled. */ -class ScaleAwareTransitionProgressProvider( - unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider, +class ScaleAwareTransitionProgressProvider +@AssistedInject +constructor( + @Assisted progressProviderToWrap: UnfoldTransitionProgressProvider, private val contentResolver: ContentResolver ) : UnfoldTransitionProgressProvider { private val scopedUnfoldTransitionProgressProvider = - ScopedUnfoldTransitionProgressProvider(unfoldTransitionProgressProvider) + ScopedUnfoldTransitionProgressProvider(progressProviderToWrap) private val animatorDurationScaleObserver = object : ContentObserver(null) { override fun onChange(selfChange: Boolean) { @@ -47,4 +52,11 @@ class ScaleAwareTransitionProgressProvider( contentResolver.unregisterContentObserver(animatorDurationScaleObserver) scopedUnfoldTransitionProgressProvider.destroy() } + + @AssistedFactory + interface Factory { + fun wrap( + progressProvider: UnfoldTransitionProgressProvider + ): ScaleAwareTransitionProgressProvider + } } diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt index f2c156108ac6f..61cf530b95cb5 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt @@ -17,87 +17,38 @@ package com.android.systemui.unfold import android.content.Context -import android.hardware.SensorManager -import android.hardware.devicestate.DeviceStateManager -import android.os.Handler import android.view.IWindowManager -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.LifecycleScreenStatusProvider import com.android.systemui.unfold.config.UnfoldTransitionConfig import com.android.systemui.unfold.updates.FoldStateProvider +import com.android.systemui.unfold.updates.screen.ScreenStatusProvider import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider +import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix import com.android.systemui.util.time.SystemClockImpl import com.android.wm.shell.unfold.ShellUnfoldProgressProvider import dagger.Lazy import dagger.Module import dagger.Provides import java.util.Optional -import java.util.concurrent.Executor import javax.inject.Named import javax.inject.Singleton -@Module +@Module(includes = [UnfoldSharedModule::class]) class UnfoldTransitionModule { - @Provides - @Singleton - fun provideUnfoldTransitionProgressProvider( - context: Context, - config: UnfoldTransitionConfig, - screenStatusProvider: Lazy, - deviceStateManager: DeviceStateManager, - sensorManager: SensorManager, - @Main executor: Executor, - @Main handler: Handler - ): Optional = - if (config.isEnabled) { - Optional.of( - createUnfoldTransitionProgressProvider( - context, - config, - screenStatusProvider.get(), - deviceStateManager, - sensorManager, - handler, - executor, - tracingTagPrefix = "systemui")) - } else { - Optional.empty() - } - - @Provides - @Singleton - fun provideFoldStateProvider( - context: Context, - config: UnfoldTransitionConfig, - screenStatusProvider: Lazy, - deviceStateManager: DeviceStateManager, - sensorManager: SensorManager, - @Main executor: Executor, - @Main handler: Handler - ): Optional = - if (!config.isHingeAngleEnabled) { - Optional.empty() - } else { - Optional.of( - createFoldStateProvider( - context, - config, - screenStatusProvider.get(), - deviceStateManager, - sensorManager, - handler, - executor)) - } + @Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui" @Provides @Singleton fun providesFoldStateLoggingProvider( - optionalFoldStateProvider: Optional + config: UnfoldTransitionConfig, + foldStateProvider: Lazy ): Optional = - optionalFoldStateProvider.map { foldStateProvider -> - FoldStateLoggingProviderImpl(foldStateProvider, SystemClockImpl()) + if (config.isHingeAngleEnabled) { + Optional.of(FoldStateLoggingProviderImpl(foldStateProvider.get(), SystemClockImpl())) + } else { + Optional.empty() } @Provides @@ -135,6 +86,9 @@ class UnfoldTransitionModule { } else { ShellUnfoldProgressProvider.NO_PROVIDER } + + @Provides + fun screenStatusProvider(impl: LifecycleScreenStatusProvider): ScreenStatusProvider = impl } const val UNFOLD_STATUS_BAR = "unfold_status_bar"