• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.launcher3.model;
2 
3 import android.content.ContentValues;
4 import android.content.Intent;
5 import android.database.Cursor;
6 import android.graphics.Point;
7 import android.test.ProviderTestCase2;
8 
9 import com.android.launcher3.InvariantDeviceProfile;
10 import com.android.launcher3.LauncherAppState;
11 import com.android.launcher3.LauncherModel;
12 import com.android.launcher3.LauncherSettings;
13 import com.android.launcher3.config.ProviderConfig;
14 import com.android.launcher3.util.TestLauncherProvider;
15 
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 
20 /**
21  * Unit tests for {@link GridSizeMigrationTask}
22  */
23 public class GridSizeMigrationTaskTest extends ProviderTestCase2<TestLauncherProvider> {
24 
25     private static final long DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
26     private static final long HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
27 
28     private static final int APPLICATION = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
29     private static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
30 
31     private static final String TEST_PACKAGE = "com.android.launcher3.validpackage";
32     private static final String VALID_INTENT =
33             new Intent(Intent.ACTION_MAIN).setPackage(TEST_PACKAGE).toUri(0);
34 
35     private HashSet<String> mValidPackages;
36     private InvariantDeviceProfile mIdp;
37 
GridSizeMigrationTaskTest()38     public GridSizeMigrationTaskTest() {
39         super(TestLauncherProvider.class, ProviderConfig.AUTHORITY);
40     }
41 
42     @Override
setUp()43     protected void setUp() throws Exception {
44         super.setUp();
45         mValidPackages = new HashSet<>();
46         mValidPackages.add(TEST_PACKAGE);
47 
48         mIdp = new InvariantDeviceProfile();
49     }
50 
testHotseatMigration_apps_dropped()51     public void testHotseatMigration_apps_dropped() throws Exception {
52         long[] hotseatItems = {
53                 addItem(APPLICATION, 0, HOTSEAT, 0, 0),
54                 addItem(SHORTCUT, 1, HOTSEAT, 0, 0),
55                 -1,
56                 addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
57                 addItem(APPLICATION, 4, HOTSEAT, 0, 0),
58         };
59 
60         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 2, 3, 1)
61                 .migrateHotseat();
62         // First & last items are dropped as they have the least weight.
63         verifyHotseat(hotseatItems[1], -1, hotseatItems[3]);
64     }
65 
testHotseatMigration_shortcuts_dropped()66     public void testHotseatMigration_shortcuts_dropped() throws Exception {
67         long[] hotseatItems = {
68                 addItem(APPLICATION, 0, HOTSEAT, 0, 0),
69                 addItem(30, 1, HOTSEAT, 0, 0),
70                 -1,
71                 addItem(SHORTCUT, 3, HOTSEAT, 0, 0),
72                 addItem(10, 4, HOTSEAT, 0, 0),
73         };
74 
75         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, 5, 2, 3, 1)
76                 .migrateHotseat();
77         // First & third items are dropped as they have the least weight.
78         verifyHotseat(hotseatItems[1], -1, hotseatItems[4]);
79     }
80 
verifyHotseat(long... sortedIds)81     private void verifyHotseat(long... sortedIds) {
82         int screenId = 0;
83         int total = 0;
84 
85         for (long id : sortedIds) {
86             Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
87                     new String[]{LauncherSettings.Favorites._ID},
88                     "container=-101 and screen=" + screenId, null, null, null);
89 
90             if (id == -1) {
91                 assertEquals(0, c.getCount());
92             } else {
93                 assertEquals(1, c.getCount());
94                 c.moveToNext();
95                 assertEquals(id, c.getLong(0));
96                 total ++;
97             }
98             c.close();
99 
100             screenId++;
101         }
102 
103         // Verify that not other entry exist in the DB.
104         Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
105                 new String[]{LauncherSettings.Favorites._ID},
106                 "container=-101", null, null, null);
107         assertEquals(total, c.getCount());
108         c.close();
109     }
110 
testWorkspace_empty_row_column_removed()111     public void testWorkspace_empty_row_column_removed() throws Exception {
112         long[][][] ids = createGrid(new int[][][]{{
113                 {  0,  0, -1,  1},
114                 {  3,  1, -1,  4},
115                 { -1, -1, -1, -1},
116                 {  5,  2, -1,  6},
117         }});
118 
119         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
120                 new Point(4, 4), new Point(3, 3)).migrateWorkspace();
121 
122         // Column 2 and row 2 got removed.
123         verifyWorkspace(new long[][][] {{
124                 {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
125                 {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
126                 {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
127         }});
128     }
129 
testWorkspace_new_screen_created()130     public void testWorkspace_new_screen_created() throws Exception {
131         long[][][] ids = createGrid(new int[][][]{{
132                 {  0,  0,  0,  1},
133                 {  3,  1,  0,  4},
134                 { -1, -1, -1, -1},
135                 {  5,  2, -1,  6},
136         }});
137 
138         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
139                 new Point(4, 4), new Point(3, 3)).migrateWorkspace();
140 
141         // Items in the second column get moved to new screen
142         verifyWorkspace(new long[][][] {{
143                 {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
144                 {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
145                 {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
146         }, {
147                 {ids[0][0][2], ids[0][1][2], -1},
148         }});
149     }
150 
testWorkspace_items_merged_in_next_screen()151     public void testWorkspace_items_merged_in_next_screen() throws Exception {
152         long[][][] ids = createGrid(new int[][][]{{
153                 {  0,  0,  0,  1},
154                 {  3,  1,  0,  4},
155                 { -1, -1, -1, -1},
156                 {  5,  2, -1,  6},
157         },{
158                 {  0,  0, -1,  1},
159                 {  3,  1, -1,  4},
160         }});
161 
162         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
163                 new Point(4, 4), new Point(3, 3)).migrateWorkspace();
164 
165         // Items in the second column of the first screen should get placed on the 3rd
166         // row of the second screen
167         verifyWorkspace(new long[][][] {{
168                 {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
169                 {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
170                 {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
171         }, {
172                 {ids[1][0][0], ids[1][0][1], ids[1][0][3]},
173                 {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
174                 {ids[0][0][2], ids[0][1][2], -1},
175         }});
176     }
177 
testWorkspace_items_not_merged_in_next_screen()178     public void testWorkspace_items_not_merged_in_next_screen() throws Exception {
179         // First screen has 2 items that need to be moved, but second screen has only one
180         // empty space after migration (top-left corner)
181         long[][][] ids = createGrid(new int[][][]{{
182                 {  0,  0,  0,  1},
183                 {  3,  1,  0,  4},
184                 { -1, -1, -1, -1},
185                 {  5,  2, -1,  6},
186         },{
187                 { -1,  0, -1,  1},
188                 {  3,  1, -1,  4},
189                 { -1, -1, -1, -1},
190                 {  5,  2, -1,  6},
191         }});
192 
193         new GridSizeMigrationTask(getMockContext(), mIdp, mValidPackages, new HashMap<String, Point>(),
194                 new Point(4, 4), new Point(3, 3)).migrateWorkspace();
195 
196         // Items in the second column of the first screen should get placed on a new screen.
197         verifyWorkspace(new long[][][] {{
198                 {ids[0][0][0], ids[0][0][1], ids[0][0][3]},
199                 {ids[0][1][0], ids[0][1][1], ids[0][1][3]},
200                 {ids[0][3][0], ids[0][3][1], ids[0][3][3]},
201         }, {
202                 {          -1, ids[1][0][1], ids[1][0][3]},
203                 {ids[1][1][0], ids[1][1][1], ids[1][1][3]},
204                 {ids[1][3][0], ids[1][3][1], ids[1][3][3]},
205         }, {
206                 {ids[0][0][2], ids[0][1][2], -1},
207         }});
208     }
209 
210     /**
211      * Initializes the DB with dummy elements to represent the provided grid structure.
212      * @param typeArray A 3d array of item types. {@see #addItem(int, long, long, int, int)} for
213      *                  type definitions. The first dimension represents the screens and the next
214      *                  two represent the workspace grid.
215      * @return the same grid representation where each entry is the corresponding item id.
216      */
createGrid(int[][][] typeArray)217     private long[][][] createGrid(int[][][] typeArray) throws Exception {
218         long[][][] ids = new long[typeArray.length][][];
219 
220         for (int i = 0; i < typeArray.length; i++) {
221             // Add screen to DB
222             long screenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
223             ContentValues v = new ContentValues();
224             v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
225             v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
226             getMockContentResolver().insert(LauncherSettings.WorkspaceScreens.CONTENT_URI, v);
227 
228             ids[i] = new long[typeArray[i].length][];
229             for (int y = 0; y < typeArray[i].length; y++) {
230                 ids[i][y] = new long[typeArray[i][y].length];
231                 for (int x = 0; x < typeArray[i][y].length; x++) {
232                     if (typeArray[i][y][x] < 0) {
233                         // Empty cell
234                         ids[i][y][x] = -1;
235                     } else {
236                         ids[i][y][x] = addItem(typeArray[i][y][x], screenId, DESKTOP, x, y);
237                     }
238                 }
239             }
240         }
241         return ids;
242     }
243 
244     /**
245      * Verifies that the workspace items are arranged in the provided order.
246      * @param ids A 3d array where the first dimension represents the screen, and the rest two
247      *            represent the workspace grid.
248      */
verifyWorkspace(long[][][] ids)249     private void verifyWorkspace(long[][][] ids) {
250         ArrayList<Long> allScreens = LauncherModel.loadWorkspaceScreensDb(getMockContext());
251         assertEquals(ids.length, allScreens.size());
252         int total = 0;
253 
254         for (int i = 0; i < ids.length; i++) {
255             long screenId = allScreens.get(i);
256             for (int y = 0; y < ids[i].length; y++) {
257                 for (int x = 0; x < ids[i][y].length; x++) {
258                     long id = ids[i][y][x];
259 
260                     Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
261                             new String[]{LauncherSettings.Favorites._ID},
262                             "container=-100 and screen=" + screenId +
263                                     " and cellX=" + x + " and cellY=" + y, null, null, null);
264                     if (id == -1) {
265                         assertEquals(0, c.getCount());
266                     } else {
267                         assertEquals(1, c.getCount());
268                         c.moveToNext();
269                         assertEquals(id, c.getLong(0));
270                         total++;
271                     }
272                     c.close();
273                 }
274             }
275         }
276 
277         // Verify that not other entry exist in the DB.
278         Cursor c = getMockContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
279                 new String[]{LauncherSettings.Favorites._ID},
280                 "container=-100", null, null, null);
281         assertEquals(total, c.getCount());
282         c.close();
283     }
284 
285     /**
286      * Adds a dummy item in the DB.
287      * @param type {@link #APPLICATION} or {@link #SHORTCUT} or >= 2 for
288      *             folder (where the type represents the number of items in the folder).
289      */
addItem(int type, long screen, long container, int x, int y)290     private long addItem(int type, long screen, long container, int x, int y) throws Exception {
291         long id = LauncherAppState.getLauncherProvider().generateNewItemId();
292 
293         ContentValues values = new ContentValues();
294         values.put(LauncherSettings.Favorites._ID, id);
295         values.put(LauncherSettings.Favorites.CONTAINER, container);
296         values.put(LauncherSettings.Favorites.SCREEN, screen);
297         values.put(LauncherSettings.Favorites.CELLX, x);
298         values.put(LauncherSettings.Favorites.CELLY, y);
299         values.put(LauncherSettings.Favorites.SPANX, 1);
300         values.put(LauncherSettings.Favorites.SPANY, 1);
301 
302         if (type == APPLICATION || type == SHORTCUT) {
303             values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
304             values.put(LauncherSettings.Favorites.INTENT, VALID_INTENT);
305         } else {
306             values.put(LauncherSettings.Favorites.ITEM_TYPE,
307                     LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
308             // Add folder items.
309             for (int i = 0; i < type; i++) {
310                 addItem(APPLICATION, 0, id, 0, 0);
311             }
312         }
313 
314         getMockContentResolver().insert(LauncherSettings.Favorites.CONTENT_URI, values);
315         return id;
316     }
317 }
318