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.content.ComponentName
20 import android.os.UserHandle
21 import com.android.systemui.mediaprojection.appselector.data.RecentTask
22 import com.android.systemui.mediaprojection.appselector.data.RecentTaskListProvider
23 import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver
24 import javax.inject.Inject
25 import kotlinx.coroutines.CoroutineScope
26 import kotlinx.coroutines.cancel
27 import kotlinx.coroutines.launch
28 
29 @MediaProjectionAppSelectorScope
30 class MediaProjectionAppSelectorController
31 @Inject
32 constructor(
33     private val recentTaskListProvider: RecentTaskListProvider,
34     private val view: MediaProjectionAppSelectorView,
35     private val devicePolicyResolver: ScreenCaptureDevicePolicyResolver,
36     @HostUserHandle private val hostUserHandle: UserHandle,
37     @MediaProjectionAppSelector private val scope: CoroutineScope,
38     @MediaProjectionAppSelector private val appSelectorComponentName: ComponentName,
39     @MediaProjectionAppSelector private val callerPackageName: String?
40 ) {
41 
42     fun init() {
43         scope.launch {
44             val recentTasks = recentTaskListProvider.loadRecentTasks()
45 
46             val tasks =
47                 recentTasks.filterDevicePolicyRestrictedTasks().filterAppSelector().sortedTasks()
48 
49             view.bind(tasks)
50         }
51     }
52 
53     fun destroy() {
54         scope.cancel()
55     }
56 
57     /** Removes all recent tasks that should be blocked according to the policy */
58     private fun List<RecentTask>.filterDevicePolicyRestrictedTasks(): List<RecentTask> = filter {
59         devicePolicyResolver.isScreenCaptureAllowed(
60             targetAppUserHandle = UserHandle.of(it.userId),
61             hostAppUserHandle = hostUserHandle
62         )
63     }
64 
65     private fun List<RecentTask>.filterAppSelector(): List<RecentTask> = filter {
66         // Only take tasks that is not the app selector
67         it.topActivityComponent != appSelectorComponentName
68     }
69 
70     private fun List<RecentTask>.sortedTasks(): List<RecentTask> = sortedBy {
71         // Show normal tasks first and only then tasks with opened app selector
72         it.topActivityComponent?.packageName == callerPackageName
73     }
74 }
75