1 /* <lambda>null2 * 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.internal.foldables.FoldLockSettingAvailabilityProvider 23 import com.android.systemui.CoreStartable 24 import com.android.systemui.Flags 25 import com.android.systemui.dagger.qualifiers.Application 26 import com.android.systemui.dagger.qualifiers.Main 27 import com.android.systemui.keyguard.LifecycleScreenStatusProvider 28 import com.android.systemui.unfold.config.UnfoldTransitionConfig 29 import com.android.systemui.unfold.dagger.UnfoldBgProgressFlag 30 import com.android.systemui.unfold.dagger.UnfoldMain 31 import com.android.systemui.unfold.data.repository.FoldStateRepository 32 import com.android.systemui.unfold.data.repository.FoldStateRepositoryImpl 33 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepository 34 import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImpl 35 import com.android.systemui.unfold.system.SystemUnfoldSharedModule 36 import com.android.systemui.unfold.updates.FoldProvider 37 import com.android.systemui.unfold.updates.FoldStateProvider 38 import com.android.systemui.unfold.updates.RotationChangeProvider 39 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider 40 import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider 41 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider 42 import com.android.systemui.unfold.util.UnfoldOnlyProgressProvider 43 import com.android.systemui.unfold.util.UnfoldTransitionATracePrefix 44 import com.android.systemui.util.time.SystemClockImpl 45 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider 46 import dagger.Binds 47 import dagger.Lazy 48 import dagger.Module 49 import dagger.Provides 50 import dagger.multibindings.ClassKey 51 import dagger.multibindings.IntoMap 52 import java.util.Optional 53 import java.util.concurrent.Executor 54 import javax.inject.Named 55 import javax.inject.Provider 56 import javax.inject.Singleton 57 58 @Module( 59 includes = 60 [ 61 UnfoldSharedModule::class, 62 SystemUnfoldSharedModule::class, 63 UnfoldTransitionModule.Bindings::class 64 ] 65 ) 66 class UnfoldTransitionModule { 67 68 @Provides @UnfoldTransitionATracePrefix fun tracingTagPrefix() = "systemui" 69 70 @Provides 71 @UnfoldBgProgressFlag 72 @Singleton 73 fun unfoldBgProgressFlag() = Flags.unfoldAnimationBackgroundProgress() 74 75 /** A globally available FoldStateListener that allows one to query the fold state. */ 76 @Provides 77 @Singleton 78 fun providesFoldStateListener( 79 deviceStateManager: DeviceStateManager, 80 @Application context: Context, 81 @Main executor: Executor 82 ): DeviceStateManager.FoldStateListener { 83 val listener = DeviceStateManager.FoldStateListener(context) 84 deviceStateManager.registerCallback(executor, listener) 85 86 return listener 87 } 88 89 @Provides 90 @Singleton 91 fun providesFoldStateLoggingProvider( 92 config: UnfoldTransitionConfig, 93 foldStateProvider: Lazy<FoldStateProvider> 94 ): Optional<FoldStateLoggingProvider> = 95 if (config.isHingeAngleEnabled) { 96 Optional.of(FoldStateLoggingProviderImpl(foldStateProvider.get(), SystemClockImpl())) 97 } else { 98 Optional.empty() 99 } 100 101 @Provides 102 @Singleton 103 fun providesFoldStateLogger( 104 optionalFoldStateLoggingProvider: Optional<FoldStateLoggingProvider> 105 ): Optional<FoldStateLogger> = 106 optionalFoldStateLoggingProvider.map { FoldStateLoggingProvider -> 107 FoldStateLogger(FoldStateLoggingProvider) 108 } 109 110 @Provides 111 @Singleton 112 fun provideNaturalRotationProgressProvider( 113 context: Context, 114 @UnfoldMain rotationChangeProvider: RotationChangeProvider, 115 unfoldTransitionProgressProvider: Optional<UnfoldTransitionProgressProvider> 116 ): Optional<NaturalRotationUnfoldProgressProvider> = 117 unfoldTransitionProgressProvider.map { provider -> 118 NaturalRotationUnfoldProgressProvider(context, rotationChangeProvider, provider) 119 } 120 121 @Provides 122 @Singleton 123 @Named(UNFOLD_ONLY_PROVIDER) 124 fun provideUnfoldOnlyProvider( 125 foldProvider: FoldProvider, 126 @Main executor: Executor, 127 sourceProvider: Optional<UnfoldTransitionProgressProvider> 128 ): Optional<UnfoldTransitionProgressProvider> = 129 sourceProvider.map { provider -> 130 UnfoldOnlyProgressProvider(foldProvider, executor, provider) 131 } 132 133 @Provides 134 @Named(UNFOLD_STATUS_BAR) 135 @Singleton 136 fun provideStatusBarScopedTransitionProvider( 137 source: Optional<NaturalRotationUnfoldProgressProvider> 138 ): Optional<ScopedUnfoldTransitionProgressProvider> = 139 source.map { provider -> ScopedUnfoldTransitionProgressProvider(provider) } 140 141 @Provides 142 @Singleton 143 fun provideShellProgressProvider( 144 config: UnfoldTransitionConfig, 145 foldProvider: FoldProvider, 146 provider: Provider<Optional<UnfoldTransitionProgressProvider>>, 147 @Named(UNFOLD_ONLY_PROVIDER) 148 unfoldOnlyProvider: Provider<Optional<UnfoldTransitionProgressProvider>> 149 ): ShellUnfoldProgressProvider { 150 val resultingProvider = 151 if (config.isEnabled) { 152 // Return unfold only provider to the shell if we don't want to animate tasks during 153 // folding. Shell provider listeners are responsible for animating task bounds. 154 if (ENABLE_FOLD_TASK_ANIMATIONS) { 155 provider 156 } else { 157 unfoldOnlyProvider 158 } 159 } else { 160 null 161 } 162 163 return resultingProvider?.get()?.orElse(null)?.let { unfoldProgressProvider -> 164 UnfoldProgressProvider(unfoldProgressProvider, foldProvider) 165 } 166 ?: ShellUnfoldProgressProvider.NO_PROVIDER 167 } 168 169 @Provides 170 fun screenStatusProvider(impl: LifecycleScreenStatusProvider): ScreenStatusProvider = impl 171 172 @Provides 173 @Singleton 174 fun provideDisplaySwitchLatencyLogger(): DisplaySwitchLatencyLogger = 175 DisplaySwitchLatencyLogger() 176 177 @Provides 178 @Singleton 179 fun provideFoldLockSettingAvailabilityProvider( 180 context: Context 181 ): FoldLockSettingAvailabilityProvider = FoldLockSettingAvailabilityProvider(context.resources) 182 183 @Module 184 interface Bindings { 185 @Binds fun bindRepository(impl: UnfoldTransitionRepositoryImpl): UnfoldTransitionRepository 186 187 @Binds fun bindFoldStateRepository(impl: FoldStateRepositoryImpl): FoldStateRepository 188 } 189 190 @Module 191 interface Startables { 192 @Binds 193 @IntoMap 194 @ClassKey(UnfoldTraceLogger::class) 195 fun bindUnfoldTraceLogger(impl: UnfoldTraceLogger): CoreStartable 196 } 197 } 198 199 const val UNFOLD_STATUS_BAR = "unfold_status_bar" 200 const val UNFOLD_ONLY_PROVIDER = "unfold_only_provider" 201 202 // TODO: b/265764985 - tracking bug to clean-up the flag 203 // FeatureFlags are not accessible here because it's a global submodule (see GlobalModule.java) 204 private val ENABLE_FOLD_TASK_ANIMATIONS = 205 SystemProperties.getBoolean("persist.unfold.enable_fold_tasks_animation", false) 206