• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.celllayout;
17 
18 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
19 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
20 
21 import static com.android.launcher3.ui.TestViewHelpers.findWidgetProvider;
22 import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
23 
24 import android.content.ComponentName;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.graphics.Rect;
28 import android.os.Process;
29 import android.os.UserHandle;
30 import android.util.Log;
31 
32 import com.android.launcher3.InvariantDeviceProfile;
33 import com.android.launcher3.LauncherSettings;
34 import com.android.launcher3.model.data.AppInfo;
35 import com.android.launcher3.model.data.FolderInfo;
36 import com.android.launcher3.model.data.ItemInfo;
37 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
38 import com.android.launcher3.model.data.WorkspaceItemInfo;
39 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
40 
41 import java.util.function.Supplier;
42 import java.util.stream.IntStream;
43 
44 public class TestWorkspaceBuilder {
45 
46     private static final String TAG = "CellLayoutBoardBuilder";
47     private static final String TEST_ACTIVITY_PACKAGE_PREFIX = "com.android.launcher3.tests.";
48     private ComponentName mAppComponentName = new ComponentName(
49             "com.google.android.calculator", "com.android.calculator2.Calculator");
50     private UserHandle mMyUser;
51 
52     private Context mContext;
53     private ContentResolver mResolver;
54 
TestWorkspaceBuilder(Context context)55     public TestWorkspaceBuilder(Context context) {
56         mMyUser = Process.myUserHandle();
57         mContext = context;
58         mResolver = mContext.getContentResolver();
59     }
60 
61     /**
62      * Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
63      */
fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect, FavoriteItemsTransaction transaction, int screenId)64     private FavoriteItemsTransaction fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect,
65             FavoriteItemsTransaction transaction, int screenId) {
66         int initX = widgetRect.getCellX();
67         int initY = widgetRect.getCellY();
68         for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
69             for (int y = initY; y < initY + widgetRect.getSpanY(); y++) {
70                 try {
71                     // this widgets are filling, we don't care if we can't place them
72                     transaction.addItem(createWidgetInCell(
73                             new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
74                                     new Rect(x, y, x, y)), screenId));
75                 } catch (Exception e) {
76                     Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
77                 }
78             }
79         }
80         return transaction;
81     }
82 
getApp()83     private AppInfo getApp() {
84         return new AppInfo(mAppComponentName, "test icon", mMyUser,
85                 AppInfo.makeLaunchIntent(mAppComponentName));
86     }
87 
88     /**
89      * Helper to set the app to use for the test workspace,
90      *  using activity-alias from AndroidManifest-common.
91      * @param testAppName the android:name field of the test app activity-alias to use
92      */
setTestAppActivityAlias(String testAppName)93     public void setTestAppActivityAlias(String testAppName) {
94         this.mAppComponentName = new ComponentName(
95             getInstrumentation().getContext().getPackageName(),
96         TEST_ACTIVITY_PACKAGE_PREFIX + testAppName
97         );
98     }
99 
addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect, FavoriteItemsTransaction transaction, int screenId)100     private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
101             FavoriteItemsTransaction transaction, int screenId) {
102         if (widgetRect.mType == 'x') {
103             fillWithWidgets(widgetRect, transaction, screenId);
104         } else {
105             transaction.addItem(createWidgetInCell(widgetRect, screenId));
106         }
107     }
108 
109     /**
110      * Builds the given board into the transaction
111      */
buildFromBoard(CellLayoutBoard board, FavoriteItemsTransaction transaction, final int screenId)112     public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board,
113             FavoriteItemsTransaction transaction, final int screenId) {
114         board.getWidgets().forEach(
115                 (widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId));
116         board.getIcons().forEach((iconPoint) ->
117                 transaction.addItem(() -> createIconInCell(iconPoint, screenId))
118         );
119         board.getFolders().forEach((folderPoint) ->
120                 transaction.addItem(() -> createFolderInCell(folderPoint, screenId))
121         );
122         return transaction;
123     }
124 
125     /**
126      * Fills the hotseat row with apps instead of suggestions, for this to work the workspace should
127      * be clean otherwise this doesn't overrides the existing icons.
128      */
fillHotseatIcons(FavoriteItemsTransaction transaction)129     public FavoriteItemsTransaction fillHotseatIcons(FavoriteItemsTransaction transaction) {
130         IntStream.range(0, InvariantDeviceProfile.INSTANCE.get(mContext).numDatabaseHotseatIcons)
131                 .forEach(i -> transaction.addItem(() -> getHotseatValues(i)));
132         return transaction;
133     }
134 
createWidgetInCell( CellLayoutBoard.WidgetRect widgetRect, int screenId)135     private Supplier<ItemInfo> createWidgetInCell(
136             CellLayoutBoard.WidgetRect widgetRect, int screenId) {
137         // Create the widget lazily since the appWidgetId can get lost during setup
138         return () -> {
139             LauncherAppWidgetProviderInfo info = findWidgetProvider(false);
140             LauncherAppWidgetInfo item = createWidgetInfo(info, getApplicationContext(), true);
141             item.cellX = widgetRect.getCellX();
142             item.cellY = widgetRect.getCellY();
143             item.spanX = widgetRect.getSpanX();
144             item.spanY = widgetRect.getSpanY();
145             item.screenId = screenId;
146             return item;
147         };
148     }
149 
createFolderInCell(CellLayoutBoard.FolderPoint folderPoint, int screenId)150     public FolderInfo createFolderInCell(CellLayoutBoard.FolderPoint folderPoint, int screenId) {
151         FolderInfo folderInfo = new FolderInfo();
152         folderInfo.screenId = screenId;
153         folderInfo.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
154         folderInfo.cellX = folderPoint.coord.x;
155         folderInfo.cellY = folderPoint.coord.y;
156         folderInfo.minSpanY = folderInfo.minSpanX = folderInfo.spanX = folderInfo.spanY = 1;
157         folderInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null);
158 
159         for (int i = 0; i < folderPoint.getNumberIconsInside(); i++) {
160             folderInfo.add(getDefaultWorkspaceItem(screenId), false);
161         }
162 
163         return folderInfo;
164     }
165 
getDefaultWorkspaceItem(int screenId)166     private WorkspaceItemInfo getDefaultWorkspaceItem(int screenId) {
167         WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
168         item.screenId = screenId;
169         item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
170         item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
171         return item;
172     }
173 
createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId)174     private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) {
175         WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
176         item.screenId = screenId;
177         item.cellX = iconPoint.getCoord().x;
178         item.cellY = iconPoint.getCoord().y;
179         item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
180         item.container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
181         return item;
182     }
183 
getHotseatValues(int x)184     private ItemInfo getHotseatValues(int x) {
185         WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
186         item.cellX = x;
187         item.cellY = 0;
188         item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;
189         item.rank = x;
190         item.screenId = x;
191         item.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
192         return item;
193     }
194 }
195