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