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