Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a911672f authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Simplifying add to workspace by not going through the worker thread

Change-Id: I3260786bee257aea93ade49e6fa18008232addbe
parent 9b032054
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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);
    }
}
+0 −13
Original line number Diff line number Diff line
@@ -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);
+70 −33
Original line number Diff line number Diff line
@@ -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() {

                @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());
            final int[] coordinates = new int[2];
            final long screenId = findSpaceOnWorkspace(item, coordinates);
            mLauncher.showWorkspace(true, new Runnable() {

                @Override
                public void run() {
                        mLauncher.getModel().addAndBindAddedWorkspaceItems(
                                mLauncher, addShortcuts, screenProvider, 0, true);
                    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);
                    }
                    announceConfirmation(R.string.item_added_to_workspace);
                }
            });
            return true;
            } else if (item instanceof PendingAddItemInfo) {
                mLauncher.getModel().addAndBindPendingItem(
                        mLauncher, (PendingAddItemInfo) item, screenProvider, 0);
                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;
    }
}
+28 −124
Original line number Diff line number Diff line
@@ -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);
        // 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<Rect>();
                    screenItems.put(screenId, items);
                        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;