Merge "Enhance dagger usage in UnfoldSharedModule"

This commit is contained in:
Nicolò Mazzucato
2022-01-14 09:28:52 +00:00
committed by Android (Google) Code Review
10 changed files with 200 additions and 128 deletions

View File

@@ -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 {

View File

@@ -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<UnfoldTransitionProgressProvider>
}

View File

@@ -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<UnfoldTransitionProgressProvider> =
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
}
}

View File

@@ -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)

View File

@@ -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<FoldUpdatesListener> = mutableListOf()

View File

@@ -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() {
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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<LifecycleScreenStatusProvider>,
deviceStateManager: DeviceStateManager,
sensorManager: SensorManager,
@Main executor: Executor,
@Main handler: Handler
): Optional<UnfoldTransitionProgressProvider> =
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<LifecycleScreenStatusProvider>,
deviceStateManager: DeviceStateManager,
sensorManager: SensorManager,
@Main executor: Executor,
@Main handler: Handler
): Optional<FoldStateProvider> =
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<FoldStateProvider>
config: UnfoldTransitionConfig,
foldStateProvider: Lazy<FoldStateProvider>
): Optional<FoldStateLoggingProvider> =
optionalFoldStateProvider.map { foldStateProvider ->
FoldStateLoggingProviderImpl(foldStateProvider, SystemClockImpl())
if (config.isHingeAngleEnabled) {
Optional.of(FoldStateLoggingProviderImpl(foldStateProvider.get(), SystemClockImpl()))
} else {
Optional.empty()
}
@Provides
@@ -144,6 +95,9 @@ class UnfoldTransitionModule {
} else {
ShellUnfoldProgressProvider.NO_PROVIDER
}
@Provides
fun screenStatusProvider(impl: LifecycleScreenStatusProvider): ScreenStatusProvider = impl
}
const val UNFOLD_STATUS_BAR = "unfold_status_bar"