1 package com.android.launcher3.taskbar.navbutton 2 3 import android.content.res.Configuration 4 import android.content.res.Resources 5 import android.view.Surface 6 import android.view.Surface.ROTATION_270 7 import android.view.Surface.Rotation 8 import android.view.View 9 import android.view.ViewGroup 10 import android.widget.ImageView 11 import android.widget.LinearLayout 12 import android.widget.Space 13 import androidx.test.runner.AndroidJUnit4 14 import com.android.launcher3.DeviceProfile 15 import com.android.launcher3.R 16 import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION 17 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_CONTEXTUAL_BUTTONS 18 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_NAV_BUTTONS 19 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_START_CONTEXTUAL_BUTTONS 20 import org.junit.Assume.assumeTrue 21 import org.junit.Before 22 import org.junit.Test 23 import org.junit.runner.RunWith 24 import org.mockito.kotlin.mock 25 import org.mockito.kotlin.whenever 26 27 @RunWith(AndroidJUnit4::class) 28 class NavButtonLayoutFactoryTest { 29 30 private val mockDeviceProfile: DeviceProfile = mock() 31 private val mockParentButtonContainer: NearestTouchFrame = mock() 32 private val mockNavLayout: LinearLayout = mock() 33 private val mockStartContextualLayout: ViewGroup = mock() 34 private val mockEndContextualLayout: ViewGroup = mock() 35 private val mockResources: Resources = mock() 36 private val mockBackButton: ImageView = mock() 37 private val mockRecentsButton: ImageView = mock() 38 private val mockHomeButton: ImageView = mock() 39 private val mockImeSwitcher: ImageView = mock() 40 private val mockA11yButton: ImageView = mock() 41 private val mockSpace: Space = mock() 42 private val mockConfiguration: Configuration = mock() 43 44 private var surfaceRotation = Surface.ROTATION_0 45 46 @Before setupnull47 fun setup() { 48 // Init end nav buttons 49 whenever(mockNavLayout.childCount).thenReturn(3) 50 whenever(mockNavLayout.findViewById<View>(R.id.back)).thenReturn(mockBackButton) 51 whenever(mockNavLayout.findViewById<View>(R.id.home)).thenReturn(mockHomeButton) 52 whenever(mockNavLayout.findViewById<View>(R.id.recent_apps)).thenReturn(mockRecentsButton) 53 54 // Init top level layout 55 whenever(mockParentButtonContainer.requireViewById<LinearLayout>(ID_END_NAV_BUTTONS)) 56 .thenReturn(mockNavLayout) 57 whenever(mockParentButtonContainer.requireViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)) 58 .thenReturn(mockEndContextualLayout) 59 whenever(mockParentButtonContainer.requireViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)) 60 .thenReturn(mockStartContextualLayout) 61 whenever(mockBackButton.resources).thenReturn(mockResources) 62 whenever(mockResources.configuration).thenReturn(mockConfiguration) 63 whenever(mockConfiguration.layoutDirection).thenReturn(0) 64 } 65 66 @Test getKidsLayoutternull67 fun getKidsLayoutter() { 68 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 69 mockDeviceProfile.isTaskbarPresent = true 70 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 71 getLayoutter( 72 isKidsMode = true, 73 isInSetup = false, 74 isThreeButtonNav = false, 75 phoneMode = false, 76 surfaceRotation = surfaceRotation 77 ) 78 assert(layoutter is KidsNavLayoutter) 79 } 80 81 @Test getSetupLayoutternull82 fun getSetupLayoutter() { 83 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 84 mockDeviceProfile.isTaskbarPresent = true 85 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 86 getLayoutter( 87 isKidsMode = false, 88 isInSetup = true, 89 isThreeButtonNav = false, 90 phoneMode = false, 91 surfaceRotation = surfaceRotation 92 ) 93 assert(layoutter is SetupNavLayoutter) 94 } 95 96 @Test getTaskbarNavLayoutternull97 fun getTaskbarNavLayoutter() { 98 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 99 mockDeviceProfile.isTaskbarPresent = true 100 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 101 getLayoutter( 102 isKidsMode = false, 103 isInSetup = false, 104 isThreeButtonNav = false, 105 phoneMode = false, 106 surfaceRotation = surfaceRotation 107 ) 108 assert(layoutter is TaskbarNavLayoutter) 109 } 110 111 @Test(expected = IllegalStateException::class) noValidLayoutForLargeScreenTaskbarNotPresentnull112 fun noValidLayoutForLargeScreenTaskbarNotPresent() { 113 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 114 mockDeviceProfile.isTaskbarPresent = false 115 getLayoutter( 116 isKidsMode = false, 117 isInSetup = false, 118 isThreeButtonNav = false, 119 phoneMode = false, 120 surfaceRotation = surfaceRotation 121 ) 122 } 123 124 @Test getTaskbarPortraitLayoutternull125 fun getTaskbarPortraitLayoutter() { 126 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 127 mockDeviceProfile.isTaskbarPresent = false 128 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 129 getLayoutter( 130 isKidsMode = false, 131 isInSetup = false, 132 isThreeButtonNav = true, 133 phoneMode = true, 134 surfaceRotation = surfaceRotation 135 ) 136 assert(layoutter is PhonePortraitNavLayoutter) 137 } 138 139 @Test getTaskbarLandscapeLayoutternull140 fun getTaskbarLandscapeLayoutter() { 141 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 142 mockDeviceProfile.isTaskbarPresent = false 143 setDeviceProfileLandscape() 144 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 145 getLayoutter( 146 isKidsMode = false, 147 isInSetup = false, 148 isThreeButtonNav = true, 149 phoneMode = true, 150 surfaceRotation = surfaceRotation 151 ) 152 assert(layoutter is PhoneLandscapeNavLayoutter) 153 } 154 155 @Test getTaskbarSeascapeLayoutternull156 fun getTaskbarSeascapeLayoutter() { 157 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 158 mockDeviceProfile.isTaskbarPresent = false 159 setDeviceProfileLandscape() 160 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 161 getLayoutter( 162 isKidsMode = false, 163 isInSetup = false, 164 isThreeButtonNav = true, 165 phoneMode = true, 166 surfaceRotation = ROTATION_270 167 ) 168 assert(layoutter is PhoneSeascapeNavLayoutter) 169 } 170 171 @Test getTaskbarPhoneGestureNavLayoutternull172 fun getTaskbarPhoneGestureNavLayoutter() { 173 assumeTrue(ENABLE_TASKBAR_NAVBAR_UNIFICATION) 174 mockDeviceProfile.isTaskbarPresent = false 175 val layoutter: NavButtonLayoutFactory.NavButtonLayoutter = 176 getLayoutter( 177 isKidsMode = false, 178 isInSetup = false, 179 isThreeButtonNav = false, 180 phoneMode = true, 181 surfaceRotation = surfaceRotation 182 ) 183 assert(layoutter is PhoneGestureLayoutter) 184 } 185 setDeviceProfileLandscapenull186 private fun setDeviceProfileLandscape() { 187 // Use reflection to modify landscape field 188 val landscapeField = mockDeviceProfile.javaClass.getDeclaredField("isLandscape") 189 landscapeField.isAccessible = true 190 landscapeField.set(mockDeviceProfile, true) 191 } 192 getLayoutternull193 private fun getLayoutter( 194 isKidsMode: Boolean, 195 isInSetup: Boolean, 196 isThreeButtonNav: Boolean, 197 phoneMode: Boolean, 198 @Rotation surfaceRotation: Int 199 ): NavButtonLayoutFactory.NavButtonLayoutter { 200 return NavButtonLayoutFactory.getUiLayoutter( 201 deviceProfile = mockDeviceProfile, 202 navButtonsView = mockParentButtonContainer, 203 resources = mockResources, 204 isKidsMode = isKidsMode, 205 isInSetup = isInSetup, 206 isThreeButtonNav = isThreeButtonNav, 207 phoneMode = phoneMode, 208 surfaceRotation = surfaceRotation, 209 imeSwitcher = mockImeSwitcher, 210 a11yButton = mockA11yButton, 211 space = mockSpace, 212 ) 213 } 214 } 215