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

Commit 6fb25a66 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

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
parent 8fe59ba8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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 {
+62 −0
Original line number Diff line number Diff line
/*
 * 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>
}
+77 −0
Original line number Diff line number Diff line
/*
 * 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
        }
}
+14 −61
Original line number Diff line number Diff line
@@ -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)
}
            tracingTagPrefix)
        .unfoldTransitionProvider
        .orElse(null)
        ?: throw IllegalStateException(
            "Trying to create " +
                "UnfoldTransitionProgressProvider when the transition is disabled")

fun createConfig(context: Context): UnfoldTransitionConfig = ResourceUnfoldTransitionConfig(context)
Loading