1 /*
2  * 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.intentresolver
18 
19 import android.os.UserHandle
20 import androidx.annotation.MainThread
21 import com.android.intentresolver.annotation.JavaInterop
22 import com.android.intentresolver.domain.interactor.UserInteractor
23 import com.android.intentresolver.inject.IntentResolverFlags
24 import com.android.intentresolver.shared.model.Profile
25 import com.android.intentresolver.shared.model.User
26 import javax.inject.Inject
27 import kotlinx.coroutines.CoroutineDispatcher
28 import kotlinx.coroutines.CoroutineScope
29 import kotlinx.coroutines.flow.first
30 import kotlinx.coroutines.runBlocking
31 
32 @JavaInterop
33 @MainThread
34 class ProfileHelper
35 @Inject
36 constructor(
37     interactor: UserInteractor,
38     private val scope: CoroutineScope,
39     private val background: CoroutineDispatcher,
40     private val flags: IntentResolverFlags,
41 ) {
42     private val launchedByHandle: UserHandle = interactor.launchedAs
43 
<lambda>null44     val launchedAsProfile by lazy {
45         runBlocking(background) { interactor.launchedAsProfile.first() }
46     }
<lambda>null47     val profiles by lazy { runBlocking(background) { interactor.profiles.first() } }
48 
49     // Map UserHandle back to a user within launchedByProfile
50     private val launchedByUser: User =
51         when (launchedByHandle) {
52             launchedAsProfile.primary.handle -> launchedAsProfile.primary
53             launchedAsProfile.clone?.handle -> requireNotNull(launchedAsProfile.clone)
54             else -> error("launchedByUser must be a member of launchedByProfile")
55         }
56     val launchedAsProfileType: Profile.Type = launchedAsProfile.type
57 
<lambda>null58     val personalProfile = profiles.single { it.type == Profile.Type.PERSONAL }
<lambda>null59     val workProfile = profiles.singleOrNull { it.type == Profile.Type.WORK }
<lambda>null60     val privateProfile = profiles.singleOrNull { it.type == Profile.Type.PRIVATE }
61 
62     val personalHandle = personalProfile.primary.handle
63     val workHandle = workProfile?.primary?.handle
64     val privateHandle = privateProfile?.primary?.handle
65     val cloneHandle = personalProfile.clone?.handle
66 
67     val isLaunchedAsCloneProfile = launchedByUser == launchedAsProfile.clone
68 
69     val cloneUserPresent = personalProfile.clone != null
70     val workProfilePresent = workProfile != null
71     val privateProfilePresent = privateProfile != null
72 
73     // Name retained for ease of review, to be renamed later
74     val tabOwnerUserHandleForLaunch =
75         if (launchedByUser.role == User.Role.CLONE) {
76             // When started by clone user, return the profile owner instead
77             launchedAsProfile.primary.handle
78         } else {
79             // Otherwise the launched user is used
80             launchedByUser.handle
81         }
82 
findProfilenull83     fun findProfile(handle: UserHandle): Profile? {
84         return profiles.firstOrNull { it.primary.handle == handle || it.clone?.handle == handle }
85     }
86 
findProfileTypenull87     fun findProfileType(handle: UserHandle): Profile.Type? = findProfile(handle)?.type
88 
89     // Name retained for ease of review, to be renamed later
90     fun getQueryIntentsHandle(handle: UserHandle): UserHandle? {
91         return if (isLaunchedAsCloneProfile && handle == personalHandle) {
92             cloneHandle
93         } else {
94             handle
95         }
96     }
97 }
98