1 /*
<lambda>null2  * Copyright (C) 2024 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.screenshot.policy
18 
19 import android.os.UserHandle
20 import com.android.systemui.screenshot.data.model.DisplayContentModel
21 import com.android.systemui.screenshot.data.model.ProfileType
22 import com.android.systemui.screenshot.data.repository.ProfileTypeRepository
23 import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult
24 import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.Matched
25 import com.android.systemui.screenshot.policy.CapturePolicy.PolicyResult.NotMatched
26 import com.android.systemui.screenshot.policy.CaptureType.FullScreen
27 import javax.inject.Inject
28 
29 /**
30  * Condition: When any visible task belongs to a private user.
31  *
32  * Parameters: Capture the whole screen, owned by the private user.
33  */
34 class PrivateProfilePolicy
35 @Inject
36 constructor(
37     private val profileTypes: ProfileTypeRepository,
38 ) : CapturePolicy {
39     override suspend fun check(content: DisplayContentModel): PolicyResult {
40         // The systemUI notification shade isn't a private profile app, skip.
41         if (content.systemUiState.shadeExpanded) {
42             return NotMatched(policy = NAME, reason = SHADE_EXPANDED)
43         }
44 
45         // Find the first visible rootTaskInfo with a child task owned by a private user
46         val childTask =
47             content.rootTasks
48                 .filter { it.isVisible }
49                 .firstNotNullOfOrNull { root ->
50                     root
51                         .childTasksTopDown()
52                         .firstOrNull {
53                             profileTypes.getProfileType(it.userId) == ProfileType.PRIVATE
54                         }
55                 }
56                 ?: return NotMatched(policy = NAME, reason = NO_VISIBLE_TASKS)
57 
58         // If matched, return parameters needed to modify the request.
59         return Matched(
60             policy = NAME,
61             reason = PRIVATE_TASK_VISIBLE,
62             CaptureParameters(
63                 type = FullScreen(content.displayId),
64                 component = content.rootTasks.first { it.isVisible }.topActivity,
65                 owner = UserHandle.of(childTask.userId),
66             )
67         )
68     }
69     companion object {
70         const val NAME = "PrivateProfile"
71         const val SHADE_EXPANDED = "Notification shade is expanded"
72         const val NO_VISIBLE_TASKS = "No private profile tasks are visible"
73         const val PRIVATE_TASK_VISIBLE = "At least one private profile task is visible"
74     }
75 }
76