1 /*
2  * Copyright (C) 2021 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.statusbar.policy
18 
19 import android.content.Context
20 import android.content.pm.UserInfo
21 import android.graphics.Bitmap
22 import android.testing.AndroidTestingRunner
23 import android.view.LayoutInflater
24 import android.view.View
25 import android.view.ViewGroup
26 import androidx.test.filters.SmallTest
27 import com.android.internal.util.UserIcons
28 import com.android.systemui.R
29 import com.android.systemui.SysuiTestCase
30 import com.android.systemui.qs.tiles.UserDetailItemView
31 import com.android.systemui.user.data.source.UserRecord
32 import com.android.systemui.util.mockito.whenever
33 import org.junit.Assert.assertFalse
34 import org.junit.Assert.assertNotNull
35 import org.junit.Assert.assertTrue
36 import org.junit.Before
37 import org.junit.Test
38 import org.junit.runner.RunWith
39 import org.mockito.ArgumentMatchers.any
40 import org.mockito.ArgumentMatchers.anyBoolean
41 import org.mockito.ArgumentMatchers.anyInt
42 import org.mockito.Mock
43 import org.mockito.Mockito.verify
44 import org.mockito.Mockito.`when`
45 import org.mockito.MockitoAnnotations
46 
47 @RunWith(AndroidTestingRunner::class)
48 @SmallTest
49 class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
50     @Mock
51     private lateinit var userSwitcherController: UserSwitcherController
52     @Mock
53     private lateinit var parent: ViewGroup
54     @Mock
55     private lateinit var keyguardUserDetailItemView: KeyguardUserDetailItemView
56     @Mock
57     private lateinit var otherView: View
58     @Mock
59     private lateinit var inflatedUserDetailItemView: KeyguardUserDetailItemView
60     @Mock
61     private lateinit var layoutInflater: LayoutInflater
62     @Mock
63     private lateinit var keyguardUserSwitcherController: KeyguardUserSwitcherController
64 
65     private lateinit var adapter: KeyguardUserSwitcherController.KeyguardUserAdapter
66     private lateinit var picture: Bitmap
67 
68     @Before
69     fun setUp() {
70         MockitoAnnotations.initMocks(this)
71 
72         whenever(userSwitcherController.isUserSwitcherEnabled).thenReturn(true)
73 
74         mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, layoutInflater)
75         `when`(layoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
76                 .thenReturn(inflatedUserDetailItemView)
77         adapter = KeyguardUserSwitcherController.KeyguardUserAdapter(
78                 mContext,
79                 mContext.resources,
80                 LayoutInflater.from(mContext),
81                 userSwitcherController, keyguardUserSwitcherController)
82         picture = UserIcons.convertToBitmap(mContext.getDrawable(R.drawable.ic_avatar_user))
83     }
84 
85     /**
86      * Uses the KeyguardUserAdapter to create a UserDetailItemView where the convertView has an
87      * incompatible type
88      */
89     private fun createViewFromDifferentType(
90         isCurrentUser: Boolean,
91         isGuestUser: Boolean
92     ): UserDetailItemView? {
93         val user = createUserRecord(isCurrentUser, isGuestUser)
94         return adapter.createUserDetailItemView(otherView, parent, user)
95     }
96 
97     /**
98      * Uses the KeyguardUserAdapter to create a UserDetailItemView where the convertView is an
99      * instance of KeyguardUserDetailItemView
100      */
101     private fun createViewFromSameType(
102         isCurrentUser: Boolean,
103         isGuestUser: Boolean
104     ): UserDetailItemView? {
105         val user = createUserRecord(isCurrentUser, isGuestUser)
106         return adapter.createUserDetailItemView(keyguardUserDetailItemView, parent, user)
107     }
108 
109     @Test
110     fun shouldSetOnClickListener_notCurrentUser_notGuestUser_oldViewIsSameType() {
111         val v: UserDetailItemView? = createViewFromSameType(
112                 isCurrentUser = false, isGuestUser = false)
113         assertNotNull(v)
114         verify(v)!!.setOnClickListener(adapter)
115     }
116 
117     @Test
118     fun shouldSetOnClickListener_notCurrentUser_guestUser_oldViewIsSameType() {
119         val v: UserDetailItemView? = createViewFromSameType(
120                 isCurrentUser = false, isGuestUser = true)
121         assertNotNull(v)
122         verify(v)!!.setOnClickListener(adapter)
123     }
124 
125     @Test
126     fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsSameType() {
127         val v: UserDetailItemView? = createViewFromSameType(
128                 isCurrentUser = true, isGuestUser = false)
129         assertNotNull(v)
130         verify(v)!!.setOnClickListener(adapter)
131     }
132 
133     @Test
134     fun shouldSetOnClickListener_currentUser_guestUser_oldViewIsSameType() {
135         val v: UserDetailItemView? = createViewFromSameType(
136                 isCurrentUser = true, isGuestUser = true)
137         assertNotNull(v)
138         verify(v)!!.setOnClickListener(adapter)
139     }
140 
141     @Test
142     fun shouldSetOnClickListener_notCurrentUser_notGuestUser_oldViewIsDifferentType() {
143         val v: UserDetailItemView? = createViewFromDifferentType(
144                 isCurrentUser = false, isGuestUser = false)
145         assertNotNull(v)
146         verify(v)!!.setOnClickListener(adapter)
147     }
148 
149     @Test
150     fun shouldSetOnClickListener_notCurrentUser_guestUser_oldViewIsDifferentType() {
151         val v: UserDetailItemView? = createViewFromDifferentType(
152                 isCurrentUser = false, isGuestUser = true)
153         assertNotNull(v)
154         verify(v)!!.setOnClickListener(adapter)
155     }
156 
157     @Test
158     fun shouldSetOnOnClickListener_currentUser_notGuestUser_oldViewIsDifferentType() {
159         val v: UserDetailItemView? = createViewFromDifferentType(
160                 isCurrentUser = true, isGuestUser = false)
161         assertNotNull(v)
162         verify(v)!!.setOnClickListener(adapter)
163     }
164 
165     @Test
166     fun shouldSetOnClickListener_currentUser_guestUser_oldViewIsDifferentType() {
167         val v: UserDetailItemView? = createViewFromDifferentType(
168                 isCurrentUser = true, isGuestUser = true)
169         assertNotNull(v)
170         verify(v)!!.setOnClickListener(adapter)
171     }
172 
173     @Test
174     fun testCurrentUserIsAlwaysFirst() {
175         `when`(userSwitcherController.users).thenReturn(arrayListOf(
176                 createUserRecord(isCurrentUser = false, isGuestUser = false),
177                 createUserRecord(isCurrentUser = true, isGuestUser = false),
178                 createUserRecord(isCurrentUser = false, isGuestUser = true),
179                 createUserRecord(isCurrentUser = false, isGuestUser = false)
180         ))
181 
182         adapter.notifyDataSetChanged()
183         assertTrue("Expected current user to be first in list", adapter.getItem(0).isCurrent)
184         assertFalse("Did not expect current user in position 1", adapter.getItem(1).isCurrent)
185         assertFalse("Did not expect current user in position 2", adapter.getItem(2).isCurrent)
186         assertTrue("Expected guest user to remain in position 2", adapter.getItem(2).isGuest)
187         assertFalse("Did not expect current user in position 3", adapter.getItem(3).isCurrent)
188     }
189 
190     private fun createUserRecord(isCurrentUser: Boolean, isGuestUser: Boolean) =
191         UserRecord(
192             UserInfo(0 /* id */, "name", 0 /* flags */),
193             picture,
194             isGuestUser,
195             isCurrentUser,
196             false /* isAddUser */,
197             false /* isRestricted */,
198             true /* isSwitchToEnabled */,
199             false /* isAddSupervisedUser */
200         )
201 }
202