1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.unfold 18 19 import android.content.Context 20 import android.hardware.devicestate.DeviceStateManager 21 import android.os.SystemProperties 22 import com.android.systemui.dagger.qualifiers.Application 23 import com.android.systemui.dagger.qualifiers.Main 24 import com.android.systemui.keyguard.LifecycleScreenStatusProvider 25 import com.android.systemui.unfold.config.UnfoldTransitionConfig 26 import com.android.systemui.unfold.system.SystemUnfoldSharedModule 27 import com.android.systemui.unfold.updates.FoldProvider 28 import com.android.systemui.unfold.updates.FoldStateProvider 29 import com.android.systemui.unfold.updates.RotationChangeProvider 30 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider 31 import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider 32 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider 33 import com.android.systemui.unfold.util.UnfoldOnlyProgressProvider 34 import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix 35 import com.android.systemui.util.time.SystemClockImpl 36 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider 37 import dagger.Lazy 38 import dagger.Module 39 import dagger.Provides 40 import java.util.Optional 41 import java.util.concurrent.Executor 42 import javax.inject.Named 43 import javax.inject.Provider 44 import javax.inject.Singleton 45 46 @Module(includes = [UnfoldSharedModule::class, SystemUnfoldSharedModule::class]) 47 class UnfoldTransitionModule { 48 49 @Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui" 50 51 /** A globally available FoldStateListener that allows one to query the fold state. */ 52 @Provides 53 @Singleton 54 fun providesFoldStateListener( 55 deviceStateManager: DeviceStateManager, 56 @Application context: Context, 57 @Main executor: Executor 58 ): DeviceStateManager.FoldStateListener { 59 val listener = DeviceStateManager.FoldStateListener(context) 60 deviceStateManager.registerCallback(executor, listener) 61 62 return listener 63 } 64 65 @Provides 66 @Singleton 67 fun providesFoldStateLoggingProvider( 68 config: UnfoldTransitionConfig, 69 foldStateProvider: Lazy<FoldStateProvider> 70 ): Optional<FoldStateLoggingProvider> = 71 if (config.isHingeAngleEnabled) { 72 Optional.of(FoldStateLoggingProviderImpl(foldStateProvider.get(), SystemClockImpl())) 73 } else { 74 Optional.empty() 75 } 76 77 @Provides 78 @Singleton 79 fun providesFoldStateLogger( 80 optionalFoldStateLoggingProvider: Optional<FoldStateLoggingProvider> 81 ): Optional<FoldStateLogger> = 82 optionalFoldStateLoggingProvider.map { FoldStateLoggingProvider -> 83 FoldStateLogger(FoldStateLoggingProvider) 84 } 85 86 @Provides 87 @Singleton 88 fun provideNaturalRotationProgressProvider( 89 context: Context, 90 rotationChangeProvider: RotationChangeProvider, 91 unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider> 92 ): Optional<NaturalRotationUnfoldProgressProvider> = 93 unfoldTransitionProgressProvider.map { provider -> 94 NaturalRotationUnfoldProgressProvider(context, rotationChangeProvider, provider) 95 } 96 97 @Provides 98 @Singleton 99 @Named(UNFOLD_ONLY_PROVIDER) 100 fun provideUnfoldOnlyProvider( 101 foldProvider: FoldProvider, 102 @Main executor: Executor, 103 sourceProvider: Optional<UnfoldTransitionProgressProvider> 104 ): Optional<UnfoldTransitionProgressProvider> = 105 sourceProvider.map { provider -> 106 UnfoldOnlyProgressProvider(foldProvider, executor, provider) 107 } 108 109 @Provides 110 @Named(UNFOLD_STATUS_BAR) 111 @Singleton 112 fun provideStatusBarScopedTransitionProvider( 113 source: Optional<NaturalRotationUnfoldProgressProvider> 114 ): Optional<ScopedUnfoldTransitionProgressProvider> = 115 source.map { provider -> ScopedUnfoldTransitionProgressProvider(provider) } 116 117 @Provides 118 @Singleton 119 fun provideShellProgressProvider( 120 config: UnfoldTransitionConfig, 121 foldProvider: FoldProvider, 122 provider: Provider<Optional<UnfoldTransitionProgressProvider>>, 123 @Named(UNFOLD_ONLY_PROVIDER) 124 unfoldOnlyProvider: Provider<Optional<UnfoldTransitionProgressProvider>> 125 ): ShellUnfoldProgressProvider { 126 val resultingProvider = 127 if (config.isEnabled) { 128 // Return unfold only provider to the shell if we don't want to animate tasks during 129 // folding. Shell provider listeners are responsible for animating task bounds. 130 if (ENABLE_FOLD_TASK_ANIMATIONS) { 131 provider 132 } else { 133 unfoldOnlyProvider 134 } 135 } else { 136 null 137 } 138 139 return resultingProvider?.get()?.orElse(null)?.let { 140 unfoldProgressProvider -> UnfoldProgressProvider(unfoldProgressProvider, foldProvider) 141 } ?: ShellUnfoldProgressProvider.NO_PROVIDER 142 } 143 144 @Provides 145 fun screenStatusProvider(impl: LifecycleScreenStatusProvider): ScreenStatusProvider = impl 146 } 147 148 const val UNFOLD_STATUS_BAR = "unfold_status_bar" 149 const val UNFOLD_ONLY_PROVIDER = "unfold_only_provider" 150 151 // TODO: b/265764985 - tracking bug to clean-up the flag 152 // FeatureFlags are not accessible here because it's a global submodule (see GlobalModule.java) 153 private val ENABLE_FOLD_TASK_ANIMATIONS = 154 SystemProperties.getBoolean("persist.unfold.enable_fold_tasks_animation", false) 155