1 /* 2 * Copyright (C) 2022 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.mediaprojection.appselector 18 19 import android.app.Activity 20 import android.content.ComponentName 21 import android.content.Context 22 import android.os.UserHandle 23 import androidx.lifecycle.DefaultLifecycleObserver 24 import com.android.launcher3.icons.IconFactory 25 import com.android.systemui.coroutines.newTracingContext 26 import com.android.systemui.dagger.qualifiers.Application 27 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerLabelLoader 28 import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader 29 import com.android.systemui.mediaprojection.appselector.data.BasicAppIconLoader 30 import com.android.systemui.mediaprojection.appselector.data.BasicPackageManagerAppIconLoader 31 import com.android.systemui.mediaprojection.appselector.data.RecentTaskLabelLoader 32 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider 33 import com.android.systemui.mediaprojection.appselector.data.RecentTaskThumbnailLoader 34 import com.android.systemui.mediaprojection.appselector.data.ShellRecentTaskListProvider 35 import com.android.systemui.mediaprojection.appselector.view.MediaProjectionRecentsViewController 36 import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider 37 import com.android.systemui.mediaprojection.appselector.view.WindowMetricsProvider 38 import com.android.systemui.mediaprojection.appselector.view.WindowMetricsProviderImpl 39 import com.android.systemui.mediaprojection.devicepolicy.MediaProjectionDevicePolicyModule 40 import com.android.systemui.mediaprojection.devicepolicy.PersonalProfile 41 import com.android.systemui.mediaprojection.permission.MediaProjectionPermissionActivity 42 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl 43 import com.android.systemui.statusbar.policy.ConfigurationController 44 import dagger.Binds 45 import dagger.BindsInstance 46 import dagger.Module 47 import dagger.Provides 48 import dagger.Subcomponent 49 import dagger.multibindings.ClassKey 50 import dagger.multibindings.IntoMap 51 import dagger.multibindings.IntoSet 52 import javax.inject.Qualifier 53 import javax.inject.Scope 54 import kotlinx.coroutines.CoroutineScope 55 import kotlinx.coroutines.SupervisorJob 56 57 @Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector 58 59 @Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUserHandle 60 61 @Qualifier @Retention(AnnotationRetention.BINARY) annotation class HostUid 62 63 @Retention(AnnotationRetention.RUNTIME) @Scope annotation class MediaProjectionAppSelectorScope 64 65 @Module( 66 subcomponents = [MediaProjectionAppSelectorComponent::class], 67 includes = [MediaProjectionDevicePolicyModule::class] 68 ) 69 interface MediaProjectionActivitiesModule { 70 @Binds 71 @IntoMap 72 @ClassKey(MediaProjectionAppSelectorActivity::class) provideMediaProjectionAppSelectorActivitynull73 fun provideMediaProjectionAppSelectorActivity( 74 activity: MediaProjectionAppSelectorActivity 75 ): Activity 76 77 @Binds 78 @IntoMap 79 @ClassKey(MediaProjectionPermissionActivity::class) 80 fun bindsMediaProjectionPermissionActivity(impl: MediaProjectionPermissionActivity): Activity 81 } 82 83 /** 84 * Scoped values for [MediaProjectionAppSelectorComponent]. We create a scope for the activity so 85 * certain dependencies like [TaskPreviewSizeProvider] could be reused. 86 */ 87 @Module 88 interface MediaProjectionAppSelectorModule { 89 90 @Binds 91 @MediaProjectionAppSelectorScope 92 fun bindRecentTaskThumbnailLoader( 93 impl: ActivityTaskManagerThumbnailLoader 94 ): RecentTaskThumbnailLoader 95 96 @Binds 97 @MediaProjectionAppSelectorScope 98 fun bindRecentTaskLabelLoader(impl: ActivityTaskManagerLabelLoader): RecentTaskLabelLoader 99 100 @Binds 101 @MediaProjectionAppSelectorScope 102 fun bindRecentTaskListProvider(impl: ShellRecentTaskListProvider): RecentTaskListProvider 103 104 @Binds 105 @MediaProjectionAppSelectorScope 106 fun bindAppIconLoader(impl: BasicPackageManagerAppIconLoader): BasicAppIconLoader 107 108 @Binds 109 @IntoSet 110 fun taskPreviewSizeProviderAsLifecycleObserver( 111 impl: TaskPreviewSizeProvider 112 ): DefaultLifecycleObserver 113 114 @Binds fun windowMetricsProvider(impl: WindowMetricsProviderImpl): WindowMetricsProvider 115 116 companion object { 117 @Provides 118 @MediaProjectionAppSelector 119 @MediaProjectionAppSelectorScope 120 fun provideAppSelectorComponentName(context: Context): ComponentName = 121 ComponentName(context, MediaProjectionAppSelectorActivity::class.java) 122 123 @Provides 124 @MediaProjectionAppSelector 125 @MediaProjectionAppSelectorScope 126 fun bindConfigurationController( 127 context: Context, 128 configurationControlleFactory: ConfigurationControllerImpl.Factory 129 ): ConfigurationController = configurationControlleFactory.create(context) 130 131 @Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context) 132 133 @Provides 134 @MediaProjectionAppSelector 135 @MediaProjectionAppSelectorScope 136 fun provideCoroutineScope(@Application applicationScope: CoroutineScope): CoroutineScope = 137 CoroutineScope( 138 applicationScope.coroutineContext + 139 SupervisorJob() + 140 newTracingContext("MediaProjectionAppSelectorScope") 141 ) 142 } 143 } 144 145 @Subcomponent(modules = [MediaProjectionAppSelectorModule::class]) 146 @MediaProjectionAppSelectorScope 147 interface MediaProjectionAppSelectorComponent { 148 149 /** Generates [MediaProjectionAppSelectorComponent]. */ 150 @Subcomponent.Factory 151 interface Factory { 152 /** Create a factory to inject the activity into the graph */ createnull153 fun create( 154 @BindsInstance @HostUserHandle hostUserHandle: UserHandle, 155 @BindsInstance @HostUid hostUid: Int, 156 @BindsInstance @MediaProjectionAppSelector callingPackage: String?, 157 @BindsInstance view: MediaProjectionAppSelectorView, 158 @BindsInstance resultHandler: MediaProjectionAppSelectorResultHandler, 159 // Whether the app selector is starting for the first time. False when it is re-starting 160 // due to a config change. 161 @BindsInstance @MediaProjectionAppSelector isFirstStart: Boolean, 162 ): MediaProjectionAppSelectorComponent 163 } 164 165 val controller: MediaProjectionAppSelectorController 166 val recentsViewController: MediaProjectionRecentsViewController 167 val emptyStateProvider: MediaProjectionBlockerEmptyStateProvider 168 @get:HostUserHandle val hostUserHandle: UserHandle 169 @get:PersonalProfile val personalProfileUserHandle: UserHandle 170 171 @MediaProjectionAppSelector val configurationController: ConfigurationController 172 val lifecycleObservers: Set<DefaultLifecycleObserver> 173 } 174