Simplifying add to workspace by not going through the worker thread
Change-Id: I3260786bee257aea93ade49e6fa18008232addbe
This commit is contained in:
@@ -3294,4 +3294,8 @@ public class CellLayout extends ViewGroup {
|
||||
public boolean lastDownOnOccupiedCell() {
|
||||
return mLastDownOnOccupiedCell;
|
||||
}
|
||||
|
||||
public boolean findVacantCell(int spanX, int spanY, int[] outXY) {
|
||||
return Utilities.findVacantCell(outXY, spanX, spanY, mCountX, mCountY, mOccupied);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3702,19 +3702,6 @@ public class Launcher extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindAddPendingItem(final PendingAddItemInfo info, final long container,
|
||||
final long screenId, final int[] cell, final int spanX, final int spanY) {
|
||||
showWorkspace(true, new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mWorkspace.snapToPage(mWorkspace.getPageIndexForScreenId(screenId));
|
||||
addPendingItem(info, container, screenId, cell, spanX, spanY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean shouldShowWeightWatcher() {
|
||||
String spKey = LauncherAppState.getSharedPreferencesKey();
|
||||
SharedPreferences sp = getSharedPreferences(spKey, Context.MODE_PRIVATE);
|
||||
|
||||
@@ -5,13 +5,13 @@ import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.View.AccessibilityDelegate;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
|
||||
import com.android.launcher3.LauncherModel.ScreenPosProvider;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -19,11 +19,13 @@ import java.util.ArrayList;
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
|
||||
public static final int REMOVE = R.id.action_remove;
|
||||
public static final int INFO = R.id.action_info;
|
||||
public static final int UNINSTALL = R.id.action_uninstall;
|
||||
public static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
||||
public static final int MOVE = R.id.action_move;
|
||||
private static final String TAG = "LauncherAccessibilityDelegate";
|
||||
|
||||
private static final int REMOVE = R.id.action_remove;
|
||||
private static final int INFO = R.id.action_info;
|
||||
private static final int UNINSTALL = R.id.action_uninstall;
|
||||
private static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
||||
private static final int MOVE = R.id.action_move;
|
||||
|
||||
enum DragType {
|
||||
ICON,
|
||||
@@ -39,8 +41,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
|
||||
private DragInfo mDragInfo = null;
|
||||
|
||||
private final SparseArray<AccessibilityAction> mActions =
|
||||
new SparseArray<AccessibilityAction>();
|
||||
private final SparseArray<AccessibilityAction> mActions = new SparseArray<>();
|
||||
@Thunk final Launcher mLauncher;
|
||||
|
||||
public LauncherAccessibilityDelegate(Launcher launcher) {
|
||||
@@ -56,7 +57,6 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
launcher.getText(R.string.action_add_to_workspace)));
|
||||
mActions.put(MOVE, new AccessibilityAction(MOVE,
|
||||
launcher.getText(R.string.action_move)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,7 +93,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
return super.performAccessibilityAction(host, action, args);
|
||||
}
|
||||
|
||||
public boolean performAction(View host, ItemInfo item, int action) {
|
||||
public boolean performAction(View host, final ItemInfo item, int action) {
|
||||
if (action == REMOVE) {
|
||||
if (DeleteDropTarget.removeWorkspaceOrFolderItem(mLauncher, item, host)) {
|
||||
announceConfirmation(R.string.item_removed);
|
||||
@@ -108,32 +108,32 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
} else if (action == MOVE) {
|
||||
beginAccessibleDrag(host, item);
|
||||
} else if (action == ADD_TO_WORKSPACE) {
|
||||
final int preferredPage = mLauncher.getWorkspace().getCurrentPage();
|
||||
final ScreenPosProvider screenProvider = new ScreenPosProvider() {
|
||||
final int[] coordinates = new int[2];
|
||||
final long screenId = findSpaceOnWorkspace(item, coordinates);
|
||||
mLauncher.showWorkspace(true, new Runnable() {
|
||||
|
||||
@Override
|
||||
public int getScreenIndex(ArrayList<Long> screenIDs) {
|
||||
return preferredPage;
|
||||
}
|
||||
};
|
||||
if (item instanceof AppInfo) {
|
||||
final ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
|
||||
addShortcuts.add(((AppInfo) item).makeShortcut());
|
||||
mLauncher.showWorkspace(true, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLauncher.getModel().addAndBindAddedWorkspaceItems(
|
||||
mLauncher, addShortcuts, screenProvider, 0, true);
|
||||
announceConfirmation(R.string.item_added_to_workspace);
|
||||
public void run() {
|
||||
if (item instanceof AppInfo) {
|
||||
ShortcutInfo info = ((AppInfo) item).makeShortcut();
|
||||
LauncherModel.addItemToDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
screenId, coordinates[0], coordinates[1]);
|
||||
|
||||
ArrayList<ItemInfo> itemList = new ArrayList<>();
|
||||
itemList.add(info);
|
||||
mLauncher.bindItems(itemList, 0, itemList.size(), true);
|
||||
} else if (item instanceof PendingAddItemInfo) {
|
||||
PendingAddItemInfo info = (PendingAddItemInfo) item;
|
||||
Workspace workspace = mLauncher.getWorkspace();
|
||||
workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
|
||||
mLauncher.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
screenId, coordinates, info.spanX, info.spanY);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} else if (item instanceof PendingAddItemInfo) {
|
||||
mLauncher.getModel().addAndBindPendingItem(
|
||||
mLauncher, (PendingAddItemInfo) item, screenProvider, 0);
|
||||
announceConfirmation(R.string.item_added_to_workspace);
|
||||
return true;
|
||||
}
|
||||
announceConfirmation(R.string.item_added_to_workspace);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -220,4 +220,41 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
||||
mDragInfo = null;
|
||||
mLauncher.getWorkspace().enableAccessibleDrag(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find empty space on the workspace and returns the screenId.
|
||||
*/
|
||||
private long findSpaceOnWorkspace(ItemInfo info, int[] outCoordinates) {
|
||||
Workspace workspace = mLauncher.getWorkspace();
|
||||
ArrayList<Long> workspaceScreens = workspace.getScreenOrder();
|
||||
long screenId;
|
||||
|
||||
// First check if there is space on the current screen.
|
||||
int screenIndex = workspace.getCurrentPage();
|
||||
screenId = workspaceScreens.get(screenIndex);
|
||||
CellLayout layout = (CellLayout) workspace.getPageAt(screenIndex);
|
||||
|
||||
boolean found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
|
||||
screenIndex = workspace.hasCustomContent() ? 1 : 0;
|
||||
while (!found && screenIndex < workspaceScreens.size()) {
|
||||
screenId = workspaceScreens.get(screenIndex);
|
||||
layout = (CellLayout) workspace.getPageAt(screenIndex);
|
||||
found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
|
||||
screenIndex++;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
return screenId;
|
||||
}
|
||||
|
||||
workspace.addExtraEmptyScreen();
|
||||
screenId = workspace.commitExtraEmptyScreen();
|
||||
layout = workspace.getScreenWithId(screenId);
|
||||
found = layout.findCellForSpan(outCoordinates, info.spanX, info.spanY);
|
||||
|
||||
if (!found) {
|
||||
Log.wtf(TAG, "Not enough space on an empty screen");
|
||||
}
|
||||
return screenId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
@@ -203,18 +202,12 @@ public class LauncherModel extends BroadcastReceiver
|
||||
public boolean isAllAppsButtonRank(int rank);
|
||||
public void onPageBoundSynchronously(int page);
|
||||
public void dumpLogsToLocalData();
|
||||
public void bindAddPendingItem(PendingAddItemInfo info, long container, long screenId,
|
||||
int[] cell, int spanX, int spanY);
|
||||
}
|
||||
|
||||
public interface ItemInfoFilter {
|
||||
public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);
|
||||
}
|
||||
|
||||
public interface ScreenPosProvider {
|
||||
int getScreenIndex(ArrayList<Long> screenIDs);
|
||||
}
|
||||
|
||||
LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
|
||||
Context context = app.getContext();
|
||||
|
||||
@@ -406,19 +399,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
runOnWorkerThread(r);
|
||||
}
|
||||
|
||||
public void addAndBindAddedWorkspaceItems(final Context context,
|
||||
final ArrayList<ItemInfo> workspaceApps) {
|
||||
addAndBindAddedWorkspaceItems(context, workspaceApps,
|
||||
new ScreenPosProvider() {
|
||||
|
||||
@Override
|
||||
public int getScreenIndex(ArrayList<Long> screenIDs) {
|
||||
return screenIDs.isEmpty() ? 0 : 1;
|
||||
}
|
||||
}, 1, false);
|
||||
}
|
||||
|
||||
private static boolean findNextAvailableIconSpaceInScreen(ArrayList<Rect> occupiedPos,
|
||||
private static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> occupiedPos,
|
||||
int[] xy, int spanX, int spanY) {
|
||||
LauncherAppState app = LauncherAppState.getInstance();
|
||||
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
|
||||
@@ -426,9 +407,11 @@ public class LauncherModel extends BroadcastReceiver
|
||||
final int yCount = (int) grid.numRows;
|
||||
boolean[][] occupied = new boolean[xCount][yCount];
|
||||
if (occupiedPos != null) {
|
||||
for (Rect r : occupiedPos) {
|
||||
for (int x = r.left; 0 <= x && x < r.right && x < xCount; x++) {
|
||||
for (int y = r.top; 0 <= y && y < r.bottom && y < yCount; y++) {
|
||||
for (ItemInfo r : occupiedPos) {
|
||||
int right = r.cellX + r.spanX;
|
||||
int bottom = r.cellY + r.spanY;
|
||||
for (int x = r.cellX; 0 <= x && x < right && x < xCount; x++) {
|
||||
for (int y = r.cellY; 0 <= y && y < bottom && y < yCount; y++) {
|
||||
occupied[x][y] = true;
|
||||
}
|
||||
}
|
||||
@@ -443,53 +426,24 @@ public class LauncherModel extends BroadcastReceiver
|
||||
*/
|
||||
@Thunk static Pair<Long, int[]> findSpaceForItem(
|
||||
Context context,
|
||||
ScreenPosProvider preferredScreen,
|
||||
int fallbackStartScreen,
|
||||
ArrayList<Long> workspaceScreens,
|
||||
ArrayList<Long> addedWorkspaceScreensFinal,
|
||||
int spanX, int spanY) {
|
||||
// Load position of items which are on the desktop. We can't use sBgItemsIdMap because
|
||||
// loadWorkspace() may not have been called.
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
|
||||
new String[] {
|
||||
LauncherSettings.Favorites.SCREEN,
|
||||
LauncherSettings.Favorites.CELLX,
|
||||
LauncherSettings.Favorites.CELLY,
|
||||
LauncherSettings.Favorites.SPANX,
|
||||
LauncherSettings.Favorites.SPANY,
|
||||
LauncherSettings.Favorites.CONTAINER
|
||||
},
|
||||
"container=?",
|
||||
new String[] { Integer.toString(LauncherSettings.Favorites.CONTAINER_DESKTOP) },
|
||||
null);
|
||||
LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
|
||||
|
||||
final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
|
||||
final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
|
||||
final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
|
||||
final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
|
||||
final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
|
||||
LongSparseArray<ArrayList<Rect>> screenItems = new LongSparseArray<ArrayList<Rect>>();
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
Rect rect = new Rect();
|
||||
rect.left = c.getInt(cellXIndex);
|
||||
rect.top = c.getInt(cellYIndex);
|
||||
rect.right = rect.left + Math.max(1, c.getInt(spanXIndex));
|
||||
rect.bottom = rect.top + Math.max(1, c.getInt(spanYIndex));
|
||||
|
||||
long screenId = c.getInt(screenIndex);
|
||||
ArrayList<Rect> items = screenItems.get(screenId);
|
||||
if (items == null) {
|
||||
items = new ArrayList<Rect>();
|
||||
screenItems.put(screenId, items);
|
||||
// Use sBgItemsIdMap as all the items are already loaded.
|
||||
// TODO: Throw exception is above condition is not met.
|
||||
synchronized (sBgLock) {
|
||||
for (ItemInfo info : sBgItemsIdMap) {
|
||||
if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
|
||||
ArrayList<ItemInfo> items = screenItems.get(info.screenId);
|
||||
if (items == null) {
|
||||
items = new ArrayList<>();
|
||||
screenItems.put(info.screenId, items);
|
||||
}
|
||||
items.add(info);
|
||||
}
|
||||
items.add(rect);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
screenItems.clear();
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
|
||||
// Find appropriate space for the item.
|
||||
@@ -499,7 +453,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
|
||||
int screenCount = workspaceScreens.size();
|
||||
// First check the preferred screen.
|
||||
int preferredScreenIndex = preferredScreen.getScreenIndex(workspaceScreens);
|
||||
int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;
|
||||
if (preferredScreenIndex < screenCount) {
|
||||
screenId = workspaceScreens.get(preferredScreenIndex);
|
||||
found = findNextAvailableIconSpaceInScreen(
|
||||
@@ -507,8 +461,8 @@ public class LauncherModel extends BroadcastReceiver
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Search on any of the screens.
|
||||
for (int screen = fallbackStartScreen; screen < screenCount; screen++) {
|
||||
// Search on any of the screens starting from the first screen.
|
||||
for (int screen = 1; screen < screenCount; screen++) {
|
||||
screenId = workspaceScreens.get(screen);
|
||||
if (findNextAvailableIconSpaceInScreen(
|
||||
screenItems.get(screenId), cordinates, spanX, spanY)) {
|
||||
@@ -538,59 +492,9 @@ public class LauncherModel extends BroadcastReceiver
|
||||
|
||||
/**
|
||||
* Adds the provided items to the workspace.
|
||||
* @param preferredScreen the screen where we should try to add the app first
|
||||
* @param fallbackStartScreen the screen to start search for empty space if
|
||||
* preferredScreen is not available.
|
||||
*/
|
||||
public void addAndBindPendingItem(
|
||||
final Context context,
|
||||
final PendingAddItemInfo addInfo,
|
||||
final ScreenPosProvider preferredScreen,
|
||||
final int fallbackStartScreen) {
|
||||
final Callbacks callbacks = getCallback();
|
||||
// Process the newly added applications and add them to the database first
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
|
||||
ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
|
||||
|
||||
// Find appropriate space for the item.
|
||||
Pair<Long, int[]> coords = findSpaceForItem(context, preferredScreen,
|
||||
fallbackStartScreen, workspaceScreens, addedWorkspaceScreensFinal,
|
||||
addInfo.spanX,
|
||||
addInfo.spanY);
|
||||
final long screenId = coords.first;
|
||||
final int[] cordinates = coords.second;
|
||||
|
||||
// Update the workspace screens
|
||||
updateWorkspaceScreenOrder(context, workspaceScreens);
|
||||
runOnMainThread(new Runnable() {
|
||||
public void run() {
|
||||
Callbacks cb = getCallback();
|
||||
if (callbacks == cb && cb != null) {
|
||||
cb.bindAddScreens(addedWorkspaceScreensFinal);
|
||||
cb.bindAddPendingItem(addInfo,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||
screenId, cordinates, addInfo.spanX, addInfo.spanY);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
runOnWorkerThread(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided items to the workspace.
|
||||
* @param preferredScreen the screen where we should try to add the app first
|
||||
* @param fallbackStartScreen the screen to start search for empty space if
|
||||
* preferredScreen is not available.
|
||||
*/
|
||||
public void addAndBindAddedWorkspaceItems(final Context context,
|
||||
final ArrayList<ItemInfo> workspaceApps,
|
||||
final ScreenPosProvider preferredScreen,
|
||||
final int fallbackStartScreen,
|
||||
final boolean allowDuplicate) {
|
||||
final ArrayList<ItemInfo> workspaceApps) {
|
||||
final Callbacks callbacks = getCallback();
|
||||
if (workspaceApps.isEmpty()) {
|
||||
return;
|
||||
@@ -607,7 +511,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
|
||||
synchronized(sBgLock) {
|
||||
for (ItemInfo item : workspaceApps) {
|
||||
if (!allowDuplicate && item instanceof ShortcutInfo) {
|
||||
if (item instanceof ShortcutInfo) {
|
||||
// Short-circuit this logic if the icon exists somewhere on the workspace
|
||||
if (shortcutExists(context, item.getIntent(), item.user)) {
|
||||
continue;
|
||||
@@ -615,8 +519,8 @@ public class LauncherModel extends BroadcastReceiver
|
||||
}
|
||||
|
||||
// Find appropriate space for the item.
|
||||
Pair<Long, int[]> coords = findSpaceForItem(context, preferredScreen,
|
||||
fallbackStartScreen, workspaceScreens, addedWorkspaceScreensFinal,
|
||||
Pair<Long, int[]> coords = findSpaceForItem(context,
|
||||
workspaceScreens, addedWorkspaceScreensFinal,
|
||||
1, 1);
|
||||
long screenId = coords.first;
|
||||
int[] cordinates = coords.second;
|
||||
|
||||
Reference in New Issue
Block a user