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