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 package com.android.launcher3.widget;
17 
18 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
19 
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import static org.mockito.ArgumentMatchers.any;
23 import static org.mockito.Mockito.doAnswer;
24 
25 import android.appwidget.AppWidgetHostView;
26 import android.content.Context;
27 import android.graphics.Point;
28 import android.graphics.Rect;
29 
30 import androidx.test.ext.junit.runners.AndroidJUnit4;
31 import androidx.test.filters.SmallTest;
32 
33 import com.android.launcher3.DeviceProfile;
34 import com.android.launcher3.InvariantDeviceProfile;
35 
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.mockito.Mockito;
40 
41 import java.util.ArrayList;
42 import java.util.Collections;
43 import java.util.List;
44 
45 @SmallTest
46 @RunWith(AndroidJUnit4.class)
47 public final class LauncherAppWidgetProviderInfoTest {
48 
49     private static final int SPACE_SIZE = 10;
50     private static final int CELL_SIZE = 50;
51     private static final int NUM_OF_COLS = 4;
52     private static final int NUM_OF_ROWS = 5;
53 
54     private Context mContext;
55 
56     @Before
setUp()57     public void setUp() {
58         mContext = getApplicationContext();
59     }
60 
61     @Test
initSpans_minWidthSmallerThanCellWidth_shouldInitializeSpansToOne()62     public void initSpans_minWidthSmallerThanCellWidth_shouldInitializeSpansToOne() {
63         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
64         info.minWidth = 20;
65         info.minHeight = 20;
66         InvariantDeviceProfile idp = createIDP();
67 
68         info.initSpans(mContext, idp);
69 
70         assertThat(info.spanX).isEqualTo(1);
71         assertThat(info.spanY).isEqualTo(1);
72     }
73 
74     @Test
initSpans_minWidthLargerThanCellWidth_shouldInitializeSpans()75     public void initSpans_minWidthLargerThanCellWidth_shouldInitializeSpans() {
76         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
77         info.minWidth = 80;
78         info.minHeight = 80;
79         InvariantDeviceProfile idp = createIDP();
80 
81         info.initSpans(mContext, idp);
82 
83         assertThat(info.spanX).isEqualTo(2);
84         assertThat(info.spanY).isEqualTo(2);
85     }
86 
87     @Test
88     public void
initSpans_minWidthLargerThanGridColumns_shouldInitializeSpansToAtMostTheGridColumns()89             initSpans_minWidthLargerThanGridColumns_shouldInitializeSpansToAtMostTheGridColumns() {
90         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
91         info.minWidth = CELL_SIZE * (NUM_OF_COLS + 1);
92         info.minHeight = 20;
93         InvariantDeviceProfile idp = createIDP();
94 
95         info.initSpans(mContext, idp);
96 
97         assertThat(info.spanX).isEqualTo(NUM_OF_COLS);
98         assertThat(info.spanY).isEqualTo(1);
99     }
100 
101     @Test
initSpans_minHeightLargerThanGridRows_shouldInitializeSpansToAtMostTheGridRows()102     public void initSpans_minHeightLargerThanGridRows_shouldInitializeSpansToAtMostTheGridRows() {
103         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
104         info.minWidth = 20;
105         info.minHeight = 50 * (NUM_OF_ROWS + 1);
106         InvariantDeviceProfile idp = createIDP();
107 
108         info.initSpans(mContext, idp);
109 
110         assertThat(info.spanX).isEqualTo(1);
111         assertThat(info.spanY).isEqualTo(NUM_OF_ROWS);
112     }
113 
114     @Test
initSpans_minResizeWidthUnspecified_shouldInitializeMinSpansToOne()115     public void initSpans_minResizeWidthUnspecified_shouldInitializeMinSpansToOne() {
116         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
117         InvariantDeviceProfile idp = createIDP();
118 
119         info.initSpans(mContext, idp);
120 
121         assertThat(info.minSpanX).isEqualTo(1);
122         assertThat(info.minSpanY).isEqualTo(1);
123     }
124 
125     @Test
initSpans_minResizeWidthSmallerThanCellWidth_shouldInitializeMinSpansToOne()126     public void initSpans_minResizeWidthSmallerThanCellWidth_shouldInitializeMinSpansToOne() {
127         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
128         info.minWidth = 100;
129         info.minHeight = 100;
130         info.minResizeWidth = 20;
131         info.minResizeHeight = 20;
132         InvariantDeviceProfile idp = createIDP();
133 
134         info.initSpans(mContext, idp);
135 
136         assertThat(info.minSpanX).isEqualTo(1);
137         assertThat(info.minSpanY).isEqualTo(1);
138     }
139 
140     @Test
initSpans_minResizeWidthLargerThanCellWidth_shouldInitializeMinSpans()141     public void initSpans_minResizeWidthLargerThanCellWidth_shouldInitializeMinSpans() {
142         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
143         info.minWidth = 100;
144         info.minHeight = 100;
145         info.minResizeWidth = 80;
146         info.minResizeHeight = 80;
147         InvariantDeviceProfile idp = createIDP();
148 
149         info.initSpans(mContext, idp);
150 
151         assertThat(info.minSpanX).isEqualTo(2);
152         assertThat(info.minSpanY).isEqualTo(2);
153     }
154 
155     @Test
initSpans_minResizeWidthWithCellSpacingAndWidgetInset_shouldInitializeMinSpans()156     public void initSpans_minResizeWidthWithCellSpacingAndWidgetInset_shouldInitializeMinSpans() {
157         InvariantDeviceProfile idp = createIDP();
158         DeviceProfile dp = idp.supportedProfiles.get(0);
159         Rect padding = new Rect();
160         AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding);
161         int maxPadding = Math.max(Math.max(padding.left, padding.right),
162                 Math.max(padding.top, padding.bottom));
163         dp.cellLayoutBorderSpacePx.x = dp.cellLayoutBorderSpacePx.y = maxPadding + 1;
164         Mockito.when(dp.shouldInsetWidgets()).thenReturn(true);
165 
166         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
167         info.minWidth = CELL_SIZE * 3;
168         info.minHeight = CELL_SIZE * 3;
169         info.minResizeWidth = CELL_SIZE * 2 + maxPadding;
170         info.minResizeHeight = CELL_SIZE * 2 + maxPadding;
171 
172         info.initSpans(mContext, idp);
173 
174         assertThat(info.minSpanX).isEqualTo(2);
175         assertThat(info.minSpanY).isEqualTo(2);
176     }
177 
178     @Test
initSpans_minResizeWidthWithCellSpacingAndNoWidgetInset_shouldInitializeMinSpans()179     public void initSpans_minResizeWidthWithCellSpacingAndNoWidgetInset_shouldInitializeMinSpans() {
180         InvariantDeviceProfile idp = createIDP();
181         DeviceProfile dp = idp.supportedProfiles.get(0);
182         Rect padding = new Rect();
183         AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding);
184         int maxPadding = Math.max(Math.max(padding.left, padding.right),
185                 Math.max(padding.top, padding.bottom));
186         dp.cellLayoutBorderSpacePx.x = dp.cellLayoutBorderSpacePx.y = maxPadding - 1;
187         Mockito.when(dp.shouldInsetWidgets()).thenReturn(false);
188         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
189         info.minWidth = CELL_SIZE * 3;
190         info.minHeight = CELL_SIZE * 3;
191         info.minResizeWidth = CELL_SIZE * 2 + maxPadding;
192         info.minResizeHeight = CELL_SIZE * 2 + maxPadding;
193 
194         info.initSpans(mContext, idp);
195 
196         assertThat(info.minSpanX).isEqualTo(3);
197         assertThat(info.minSpanY).isEqualTo(3);
198     }
199 
200     @Test
201     public void
initSpans_minResizeWidthHeightLargerThanMinWidth_shouldUseMinWidthHeightAsMinSpans()202             initSpans_minResizeWidthHeightLargerThanMinWidth_shouldUseMinWidthHeightAsMinSpans() {
203         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
204         info.minWidth = 20;
205         info.minHeight = 20;
206         info.minResizeWidth = 80;
207         info.minResizeHeight = 80;
208         InvariantDeviceProfile idp = createIDP();
209 
210         info.initSpans(mContext, idp);
211 
212         assertThat(info.minSpanX).isEqualTo(1);
213         assertThat(info.minSpanY).isEqualTo(1);
214     }
215 
216     @Test
isMinSizeFulfilled_minWidthAndHeightWithinGridSize_shouldReturnTrue()217     public void isMinSizeFulfilled_minWidthAndHeightWithinGridSize_shouldReturnTrue() {
218         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
219         info.minWidth = 80;
220         info.minHeight = 80;
221         info.minResizeWidth = 50;
222         info.minResizeHeight = 50;
223         InvariantDeviceProfile idp = createIDP();
224 
225         info.initSpans(mContext, idp);
226 
227         assertThat(info.isMinSizeFulfilled()).isTrue();
228     }
229 
230     @Test
231     public void
isMinSizeFulfilled_minWidthAndMinResizeWidthExceededGridColumns_shouldReturnFalse()232             isMinSizeFulfilled_minWidthAndMinResizeWidthExceededGridColumns_shouldReturnFalse() {
233         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
234         info.minWidth = CELL_SIZE * (NUM_OF_COLS + 2);
235         info.minHeight = 80;
236         info.minResizeWidth = CELL_SIZE * (NUM_OF_COLS + 1);
237         info.minResizeHeight = 50;
238         InvariantDeviceProfile idp = createIDP();
239 
240         info.initSpans(mContext, idp);
241 
242         assertThat(info.isMinSizeFulfilled()).isFalse();
243     }
244 
245     @Test
isMinSizeFulfilled_minHeightAndMinResizeHeightExceededGridRows_shouldReturnFalse()246     public void isMinSizeFulfilled_minHeightAndMinResizeHeightExceededGridRows_shouldReturnFalse() {
247         LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo();
248         info.minWidth = 80;
249         info.minHeight = CELL_SIZE * (NUM_OF_ROWS + 2);
250         info.minResizeWidth = 50;
251         info.minResizeHeight = CELL_SIZE * (NUM_OF_ROWS + 1);
252         InvariantDeviceProfile idp = createIDP();
253 
254         info.initSpans(mContext, idp);
255 
256         assertThat(info.isMinSizeFulfilled()).isFalse();
257     }
258 
createIDP()259     private InvariantDeviceProfile createIDP() {
260         DeviceProfile profile = Mockito.mock(DeviceProfile.class);
261         doAnswer(i -> {
262             ((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
263             return null;
264         }).when(profile).getCellSize(any(Point.class));
265         Mockito.when(profile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
266         profile.cellLayoutBorderSpacePx = new Point(SPACE_SIZE, SPACE_SIZE);
267         Mockito.when(profile.shouldInsetWidgets()).thenReturn(true);
268 
269         InvariantDeviceProfile idp = new InvariantDeviceProfile();
270         List<DeviceProfile> supportedProfiles = new ArrayList<>(idp.supportedProfiles);
271         supportedProfiles.add(profile);
272         idp.supportedProfiles = Collections.unmodifiableList(supportedProfiles);
273         idp.numColumns = NUM_OF_COLS;
274         idp.numRows = NUM_OF_ROWS;
275         return idp;
276     }
277 }
278