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 package com.android.wallpaper.util
17 
18 import android.content.Context
19 import android.content.res.Configuration
20 import android.graphics.Point
21 import com.android.wallpaper.module.InjectorProvider
22 import com.android.wallpaper.testing.FakeDisplaysProvider
23 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.FOLDABLE_FOLDED
24 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.FOLDABLE_UNFOLDED_LAND
25 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.FOLDABLE_UNFOLDED_PORT
26 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.HANDHELD
27 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.TABLET_LAND
28 import com.android.wallpaper.testing.FakeDisplaysProvider.Companion.TABLET_PORT
29 import com.android.wallpaper.testing.TestInjector
30 import com.google.common.truth.Truth.assertThat
31 import dagger.hilt.android.qualifiers.ApplicationContext
32 import dagger.hilt.android.testing.HiltAndroidRule
33 import dagger.hilt.android.testing.HiltAndroidTest
34 import javax.inject.Inject
35 import org.junit.Before
36 import org.junit.Rule
37 import org.junit.Test
38 import org.junit.runner.RunWith
39 import org.robolectric.RobolectricTestRunner
40 import org.robolectric.annotation.Config
41 import org.robolectric.shadows.ShadowDisplayManager
42 
43 @HiltAndroidTest
44 @RunWith(RobolectricTestRunner::class)
45 @Config(shadows = [ShadowDisplayManager::class])
46 class DisplayUtilsTest {
47     @get:Rule var hiltRule = HiltAndroidRule(this)
48 
49     @Inject @ApplicationContext lateinit var appContext: Context
50     @Inject lateinit var displaysProvider: FakeDisplaysProvider
51     @Inject lateinit var displayUtils: DisplayUtils
52     @Inject lateinit var testInjector: TestInjector
53 
54     @Before
setUpnull55     fun setUp() {
56         hiltRule.inject()
57         InjectorProvider.setInjector(testInjector)
58     }
59 
60     @Test
hasMultiInternalDisplays_oneDisplay_returnsFalsenull61     fun hasMultiInternalDisplays_oneDisplay_returnsFalse() {
62         val displays = listOf(HANDHELD)
63         displaysProvider.setDisplays(displays)
64 
65         assertThat(displayUtils.hasMultiInternalDisplays()).isFalse()
66     }
67 
68     @Test
hasMultiInternalDisplays_twoDisplays_returnsTruenull69     fun hasMultiInternalDisplays_twoDisplays_returnsTrue() {
70         val displays = listOf(FOLDABLE_FOLDED, FOLDABLE_UNFOLDED_LAND)
71         displaysProvider.setDisplays(displays)
72 
73         assertThat(displayUtils.hasMultiInternalDisplays()).isTrue()
74     }
75 
76     @Test
getWallpaperDisplay_oneDisplay_returnsDefaultDisplaynull77     fun getWallpaperDisplay_oneDisplay_returnsDefaultDisplay() {
78         val displays = listOf(HANDHELD)
79         displaysProvider.setDisplays(displays)
80 
81         assertThat(displayUtils.getWallpaperDisplay())
82             .isEqualTo(displaysProvider.getInternalDisplays()[0])
83     }
84 
85     @Test
getWallpaperDisplay_twoDisplays_returnsLargestDisplaynull86     fun getWallpaperDisplay_twoDisplays_returnsLargestDisplay() {
87         val displays = listOf(FOLDABLE_FOLDED, FOLDABLE_UNFOLDED_LAND)
88         displaysProvider.setDisplays(displays)
89 
90         assertThat(displayUtils.getWallpaperDisplay())
91             .isEqualTo(displaysProvider.getInternalDisplays()[1])
92     }
93 
94     @Test
isUnfoldedHorizontalHinge_handheld_returnsFalsenull95     fun isUnfoldedHorizontalHinge_handheld_returnsFalse() {
96         val displays = listOf(HANDHELD)
97         displaysProvider.setDisplays(displays)
98         val displayContext =
99             appContext.createDisplayContext(displaysProvider.getInternalDisplays()[0])
100 
101         assertThat(displayUtils.isUnfoldedHorizontalHinge(displayContext)).isFalse()
102     }
103 
104     @Test
isUnfoldedHorizontalHinge_foldableFolded_returnsFalsenull105     fun isUnfoldedHorizontalHinge_foldableFolded_returnsFalse() {
106         val displays = listOf(FOLDABLE_FOLDED, FOLDABLE_UNFOLDED_PORT)
107         displaysProvider.setDisplays(displays)
108         val displayContext =
109             appContext.createDisplayContext(displaysProvider.getInternalDisplays()[0])
110 
111         assertThat(displayUtils.isUnfoldedHorizontalHinge(displayContext)).isFalse()
112     }
113 
114     @Test
isUnfoldedHorizontalHinge_foldableUnfoldedLandscape_returnsFalsenull115     fun isUnfoldedHorizontalHinge_foldableUnfoldedLandscape_returnsFalse() {
116         val displays = listOf(FOLDABLE_UNFOLDED_LAND, FOLDABLE_FOLDED)
117         displaysProvider.setDisplays(displays)
118         val displayContext =
119             appContext.createDisplayContext(displaysProvider.getInternalDisplays()[0])
120 
121         assertThat(displayUtils.isUnfoldedHorizontalHinge(displayContext)).isFalse()
122     }
123 
124     @Test
isUnfoldedHorizontalHinge_foldableUnfoldedPortrait_returnsTruenull125     fun isUnfoldedHorizontalHinge_foldableUnfoldedPortrait_returnsTrue() {
126         val displays = listOf(FOLDABLE_UNFOLDED_PORT, FOLDABLE_FOLDED)
127         displaysProvider.setDisplays(displays)
128         val displayContext =
129             appContext.createDisplayContext(displaysProvider.getInternalDisplays()[0])
130 
131         assertThat(displayUtils.isUnfoldedHorizontalHinge(displayContext)).isTrue()
132     }
133 
134     @Test
isUnfoldedHorizontalHinge_tabletPortrait_returnsFalsenull135     fun isUnfoldedHorizontalHinge_tabletPortrait_returnsFalse() {
136         val displays = listOf(TABLET_PORT)
137         displaysProvider.setDisplays(displays)
138         val displayContext =
139             appContext.createDisplayContext(displaysProvider.getInternalDisplays()[0])
140 
141         assertThat(displayUtils.isUnfoldedHorizontalHinge(displayContext)).isFalse()
142     }
143 
144     @Test
getMaxDisplaysDimension_oneDisplay_returnsDisplayDimensionsnull145     fun getMaxDisplaysDimension_oneDisplay_returnsDisplayDimensions() {
146         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
147         val displays = listOf(displayConfig1)
148         displaysProvider.setDisplays(displays)
149 
150         assertThat(displayUtils.getMaxDisplaysDimension()).isEqualTo(Point(250, 500))
151     }
152 
153     @Test
getMaxDisplaysDimension_noRotation_returnsMaxOfEachDimensionnull154     fun getMaxDisplaysDimension_noRotation_returnsMaxOfEachDimension() {
155         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
156         val displayConfig2 = FakeDisplaysProvider.FakeDisplayConfig(Point(300, 400))
157         val displays = listOf(displayConfig1, displayConfig2)
158         displaysProvider.setDisplays(displays)
159 
160         assertThat(displayUtils.getMaxDisplaysDimension()).isEqualTo(Point(300, 500))
161     }
162 
163     @Test
getMaxDisplaysDimension_withRotation_returnsMaxPostRotationnull164     fun getMaxDisplaysDimension_withRotation_returnsMaxPostRotation() {
165         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
166         // Display size of config 2 becomes Point(400, 300) with rotation.
167         val displayConfig2 =
168             FakeDisplaysProvider.FakeDisplayConfig(
169                 displaySize = Point(300, 400),
170                 orientation = Configuration.ORIENTATION_LANDSCAPE,
171             )
172         val displays = listOf(displayConfig1, displayConfig2)
173         displaysProvider.setDisplays(displays)
174 
175         assertThat(displayUtils.getMaxDisplaysDimension()).isEqualTo(Point(400, 500))
176     }
177 
178     @Test
getMaxDisplaysDimension_foldable_returnsMaxOfEachDimensionnull179     fun getMaxDisplaysDimension_foldable_returnsMaxOfEachDimension() {
180         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
181         val displayConfig2 = FakeDisplaysProvider.FakeDisplayConfig(Point(300, 400))
182         val displayConfig3 = FakeDisplaysProvider.FakeDisplayConfig(Point(600, 300))
183         val displays = listOf(displayConfig1, displayConfig2, displayConfig3)
184         displaysProvider.setDisplays(displays)
185 
186         assertThat(displayUtils.getMaxDisplaysDimension()).isEqualTo(Point(600, 500))
187     }
188 
189     @Test
isLargeScreenDevice_handheld_returnsFalsenull190     fun isLargeScreenDevice_handheld_returnsFalse() {
191         val displays = listOf(HANDHELD)
192         displaysProvider.setDisplays(displays)
193 
194         assertThat(displayUtils.isLargeScreenDevice()).isFalse()
195     }
196 
197     @Test
isLargeScreenDevice_foldedFoldable_returnsTruenull198     fun isLargeScreenDevice_foldedFoldable_returnsTrue() {
199         val displays = listOf(FOLDABLE_FOLDED, FOLDABLE_UNFOLDED_LAND)
200         displaysProvider.setDisplays(displays)
201 
202         assertThat(displayUtils.isLargeScreenDevice()).isTrue()
203     }
204 
205     @Test
isLargeScreenDevice_unfoldedFoldable_returnsTruenull206     fun isLargeScreenDevice_unfoldedFoldable_returnsTrue() {
207         val displays = listOf(FOLDABLE_UNFOLDED_LAND, FOLDABLE_FOLDED)
208         displaysProvider.setDisplays(displays)
209 
210         assertThat(displayUtils.isLargeScreenDevice()).isTrue()
211     }
212 
213     @Test
isLargeScreenDevice_tablet_returnsTruenull214     fun isLargeScreenDevice_tablet_returnsTrue() {
215         val displays = listOf(TABLET_LAND)
216         displaysProvider.setDisplays(displays)
217 
218         assertThat(displayUtils.isLargeScreenDevice()).isTrue()
219     }
220 
221     @Test
getSmallerDisplay_oneDisplay_returnsDefaultDisplaynull222     fun getSmallerDisplay_oneDisplay_returnsDefaultDisplay() {
223         val displays = listOf(HANDHELD)
224         displaysProvider.setDisplays(displays)
225 
226         assertThat(displayUtils.getSmallerDisplay())
227             .isEqualTo(displaysProvider.getInternalDisplays()[0])
228     }
229 
230     @Test
getSmallerDisplay_twoDisplays_returnsSmallestDisplaynull231     fun getSmallerDisplay_twoDisplays_returnsSmallestDisplay() {
232         val displays = listOf(FOLDABLE_UNFOLDED_LAND, FOLDABLE_FOLDED)
233         displaysProvider.setDisplays(displays)
234 
235         assertThat(displayUtils.getSmallerDisplay())
236             .isEqualTo(displaysProvider.getInternalDisplays()[1])
237     }
238 
239     @Test
getInternalDisplaySizes_noRotation_returnsSizesAsIsnull240     fun getInternalDisplaySizes_noRotation_returnsSizesAsIs() {
241         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
242         val displayConfig2 = FakeDisplaysProvider.FakeDisplayConfig(Point(300, 400))
243         val displays = listOf(displayConfig1, displayConfig2)
244         displaysProvider.setDisplays(displays)
245 
246         val displaySizes = displayUtils.getInternalDisplaySizes()
247         assertThat(displaySizes.size).isEqualTo(displays.size)
248         assertThat(displaySizes).contains(Point(250, 500))
249         assertThat(displaySizes).contains(Point(300, 400))
250     }
251 
252     @Test
getInternalDisplaySizes_withRotation_returnsSizesPostRotationnull253     fun getInternalDisplaySizes_withRotation_returnsSizesPostRotation() {
254         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
255         // Display size of config 2 becomes Point(400, 300) with rotation.
256         val displayConfig2 =
257             FakeDisplaysProvider.FakeDisplayConfig(
258                 displaySize = Point(300, 400),
259                 orientation = Configuration.ORIENTATION_LANDSCAPE,
260             )
261         val displays = listOf(displayConfig1, displayConfig2)
262         displaysProvider.setDisplays(displays)
263 
264         val displaySizes = displayUtils.getInternalDisplaySizes()
265         assertThat(displaySizes.size).isEqualTo(displays.size)
266         assertThat(displaySizes).contains(Point(250, 500))
267         assertThat(displaySizes).contains(Point(400, 300))
268     }
269 
270     @Test
getInternalDisplaySizes_allDimensions_returnsSizesAndRotatedSizesnull271     fun getInternalDisplaySizes_allDimensions_returnsSizesAndRotatedSizes() {
272         val displayConfig1 = FakeDisplaysProvider.FakeDisplayConfig(Point(250, 500))
273         val displayConfig2 = FakeDisplaysProvider.FakeDisplayConfig(Point(300, 400))
274         val displays = listOf(displayConfig1, displayConfig2)
275         displaysProvider.setDisplays(displays)
276 
277         val displaySizes = displayUtils.getInternalDisplaySizes(true)
278         assertThat(displaySizes.size).isEqualTo(displays.size * 2)
279         assertThat(displaySizes).contains(Point(250, 500))
280         assertThat(displaySizes).contains(Point(300, 400))
281         assertThat(displaySizes).contains(Point(500, 250))
282         assertThat(displaySizes).contains(Point(400, 300))
283     }
284 }
285