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 
18 package com.android.systemui.user.legacyhelper.data
19 
20 import android.content.Context
21 import android.content.pm.UserInfo
22 import android.graphics.Bitmap
23 import android.os.UserManager
24 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
25 import com.android.settingslib.RestrictedLockUtilsInternal
26 import com.android.systemui.R
27 import com.android.systemui.user.data.source.UserRecord
28 import com.android.systemui.user.shared.model.UserActionModel
29 
30 /**
31  * Defines utility functions for helping with legacy data code for users.
32  *
33  * We need these to avoid code duplication between logic inside the UserSwitcherController and in
34  * modern architecture classes such as repositories, interactors, and view-models. If we ever
35  * simplify UserSwitcherController (or delete it), the code here could be moved into its call-sites.
36  */
37 object LegacyUserDataHelper {
38 
39     @JvmStatic
40     fun createRecord(
41         context: Context,
42         manager: UserManager,
43         picture: Bitmap?,
44         userInfo: UserInfo,
45         isCurrent: Boolean,
46         canSwitchUsers: Boolean,
47     ): UserRecord {
48         val isGuest = userInfo.isGuest
49         return UserRecord(
50             info = userInfo,
51             picture =
52                 getPicture(
53                     manager = manager,
54                     context = context,
55                     userInfo = userInfo,
56                     picture = picture,
57                 ),
58             isGuest = isGuest,
59             isCurrent = isCurrent,
60             isSwitchToEnabled = canSwitchUsers || (isCurrent && !isGuest),
61         )
62     }
63 
64     @JvmStatic
65     fun createRecord(
66         context: Context,
67         selectedUserId: Int,
68         actionType: UserActionModel,
69         isRestricted: Boolean,
70         isSwitchToEnabled: Boolean,
71     ): UserRecord {
72         return UserRecord(
73             isGuest = actionType == UserActionModel.ENTER_GUEST_MODE,
74             isAddUser = actionType == UserActionModel.ADD_USER,
75             isAddSupervisedUser = actionType == UserActionModel.ADD_SUPERVISED_USER,
76             isRestricted = isRestricted,
77             isSwitchToEnabled = isSwitchToEnabled,
78             enforcedAdmin =
79                 getEnforcedAdmin(
80                     context = context,
81                     selectedUserId = selectedUserId,
82                 ),
83             isManageUsers = actionType == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT,
84         )
85     }
86 
87     fun toUserActionModel(record: UserRecord): UserActionModel {
88         check(!isUser(record))
89 
90         return when {
91             record.isAddUser -> UserActionModel.ADD_USER
92             record.isAddSupervisedUser -> UserActionModel.ADD_SUPERVISED_USER
93             record.isGuest -> UserActionModel.ENTER_GUEST_MODE
94             record.isManageUsers -> UserActionModel.NAVIGATE_TO_USER_MANAGEMENT
95             else -> error("Not a known action: $record")
96         }
97     }
98 
99     fun isUser(record: UserRecord): Boolean {
100         return record.info != null
101     }
102 
103     private fun getEnforcedAdmin(
104         context: Context,
105         selectedUserId: Int,
106     ): EnforcedAdmin? {
107         val admin =
108             RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
109                 context,
110                 UserManager.DISALLOW_ADD_USER,
111                 selectedUserId,
112             )
113                 ?: return null
114 
115         return if (
116             !RestrictedLockUtilsInternal.hasBaseUserRestriction(
117                 context,
118                 UserManager.DISALLOW_ADD_USER,
119                 selectedUserId,
120             )
121         ) {
122             admin
123         } else {
124             null
125         }
126     }
127 
128     private fun getPicture(
129         context: Context,
130         manager: UserManager,
131         userInfo: UserInfo,
132         picture: Bitmap?,
133     ): Bitmap? {
134         if (userInfo.isGuest) {
135             return null
136         }
137 
138         if (picture != null) {
139             return picture
140         }
141 
142         val unscaledOrNull = manager.getUserIcon(userInfo.id) ?: return null
143 
144         val avatarSize = context.resources.getDimensionPixelSize(R.dimen.max_avatar_size)
145         return Bitmap.createScaledBitmap(
146             unscaledOrNull,
147             avatarSize,
148             avatarSize,
149             /* filter= */ true,
150         )
151     }
152 }
153