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

Commit 4670ff6e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Moving install queue updates to worker thread." into ub-launcher3-master

parents 6750836b 91498abf
Loading
Loading
Loading
Loading
+87 −100
Original line number Diff line number Diff line
@@ -27,7 +27,9 @@ import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
@@ -61,6 +63,9 @@ import java.util.Set;

public class InstallShortcutReceiver extends BroadcastReceiver {

    private static final int MSG_ADD_TO_QUEUE = 1;
    private static final int MSG_FLUSH_QUEUE = 2;

    public static final int FLAG_ACTIVITY_PAUSED = 1;
    public static final int FLAG_LOADER_RUNNING = 2;
    public static final int FLAG_DRAG_AND_DROP = 4;
@@ -93,28 +98,74 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
    public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
    public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;

    private static final Object sLock = new Object();
    private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) {

    private static void addToInstallQueue(
            SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) {
        synchronized(sLock) {
            String encoded = info.encodeToString();
            if (encoded != null) {
                Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ADD_TO_QUEUE: {
                    Pair<Context, PendingInstallShortcutInfo> pair =
                            (Pair<Context, PendingInstallShortcutInfo>) msg.obj;
                    String encoded = pair.second.encodeToString();
                    SharedPreferences prefs = Utilities.getPrefs(pair.first);
                    Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
                    strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
                    strings.add(encoded);
                sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
                    prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
                    return;
                }
                case MSG_FLUSH_QUEUE: {
                    Context context = (Context) msg.obj;
                    LauncherModel model = LauncherAppState.getInstance(context).getModel();
                    if (model.getCallback() == null) {
                        // Launcher not loaded
                        return;
                    }

                    ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
                    SharedPreferences prefs = Utilities.getPrefs(context);
                    Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
                    if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
                    if (strings == null) {
                        return;
                    }

                    LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
                    for (String encoded : strings) {
                        PendingInstallShortcutInfo info = decode(encoded, context);
                        if (info == null) {
                            continue;
                        }

                        String pkg = getIntentPackage(info.launchIntent);
                        if (!TextUtils.isEmpty(pkg)
                                && !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
                            if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
                                    + info.launchIntent);
                            continue;
                        }

                        // Generate a shortcut info to add into the model
                        installQueue.add(info.getItemInfo());
                    }
                    prefs.edit().remove(APPS_PENDING_INSTALL).apply();
                    if (!installQueue.isEmpty()) {
                        model.addAndBindAddedWorkspaceItems(installQueue);
                    }
                    return;
                }
            }
        }
    };

    public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
            UserHandle user) {
        if (packageNames.isEmpty()) {
            return;
        }
        Preconditions.assertWorkerThread();

        SharedPreferences sp = Utilities.getPrefs(context);
        synchronized(sLock) {
        Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
        if (DBG) {
            Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
@@ -140,27 +191,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
        }
        sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
    }
    }

    private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue(Context context) {
        SharedPreferences sharedPrefs = Utilities.getPrefs(context);
        synchronized(sLock) {
            ArrayList<PendingInstallShortcutInfo> infos = new ArrayList<>();
            Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
            if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
            if (strings == null) {
                return infos;
            }
            for (String encoded : strings) {
                PendingInstallShortcutInfo info = decode(encoded, context);
                if (info != null) {
                    infos.add(info);
                }
            }
            sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).apply();
            return infos;
        }
    }

    public void onReceive(Context context, Intent data) {
        if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
@@ -256,7 +286,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {

    private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
        // Queue the item up for adding if launcher has not loaded properly yet
        addToInstallQueue(Utilities.getPrefs(context), info);
        Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget();
        flushInstallQueue(context);
    }

@@ -269,17 +299,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
    }

    static void flushInstallQueue(Context context) {
        LauncherModel model = LauncherAppState.getInstance(context).getModel();
        boolean launcherNotLoaded = model.getCallback() == null;
        if (sInstallQueueDisabledFlags != 0 || launcherNotLoaded) {
        if (sInstallQueueDisabledFlags != 0) {
            return;
        }

        ArrayList<PendingInstallShortcutInfo> items = getAndClearInstallQueue(context);
        if (!items.isEmpty()) {
            model.addAndBindAddedWorkspaceItems(
                    new LazyShortcutsProvider(context.getApplicationContext(), items));
        }
        Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget();
    }

    /**
@@ -601,42 +624,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
        return new PendingInstallShortcutInfo(info, original.mContext);
    }

    private static class LazyShortcutsProvider extends Provider<List<Pair<ItemInfo, Object>>> {

        private final Context mContext;
        private final ArrayList<PendingInstallShortcutInfo> mPendingItems;

        public LazyShortcutsProvider(Context context, ArrayList<PendingInstallShortcutInfo> items) {
            mContext = context;
            mPendingItems = items;
        }

        /**
         * This must be called on the background thread as this requires multiple calls to
         * packageManager and icon cache.
         */
        @Override
        public ArrayList<Pair<ItemInfo, Object>> get() {
            Preconditions.assertNonUiThread();
            ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
            LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
            for (PendingInstallShortcutInfo pendingInfo : mPendingItems) {
                // If the intent specifies a package, make sure the package exists
                String packageName = getIntentPackage(pendingInfo.launchIntent);
                if (!TextUtils.isEmpty(packageName) && !launcherApps.isPackageEnabledForProfile(
                        packageName, pendingInfo.user)) {
                    if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
                            + pendingInfo.launchIntent);
                    continue;
                }

                // Generate a shortcut info to add into the model
                installQueue.add(pendingInfo.getItemInfo());
            }
            return installQueue;
        }
    }

    private static ShortcutInfo createShortcutInfo(Intent data, LauncherAppState app) {
        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
+2 −3
Original line number Diff line number Diff line
@@ -192,9 +192,8 @@ public class LauncherModel extends BroadcastReceiver
    /**
     * Adds the provided items to the workspace.
     */
    public void addAndBindAddedWorkspaceItems(
            Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
        enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
    public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
        enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
    }

    public ModelWriter getWriter(boolean hasVerticalHotseat) {
+6 −8
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@ import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ManagedProfileHeuristic.UserFolderInfo;
import com.android.launcher3.util.Provider;
import java.util.ArrayList;
import java.util.List;

@@ -47,19 +46,18 @@ import java.util.List;
 */
public class AddWorkspaceItemsTask extends BaseModelUpdateTask {

    private final Provider<List<Pair<ItemInfo, Object>>> mAppsProvider;
    private final List<Pair<ItemInfo, Object>> mItemList;

    /**
     * @param appsProvider items to add on the workspace
     * @param itemList items to add on the workspace
     */
    public AddWorkspaceItemsTask(Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
        mAppsProvider = appsProvider;
    public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {
        mItemList = itemList;
    }

    @Override
    public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
        List<Pair<ItemInfo, Object>> workspaceApps = mAppsProvider.get();
        if (workspaceApps.isEmpty()) {
        if (mItemList.isEmpty()) {
            return;
        }
        Context context = app.getContext();
@@ -75,7 +73,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
        synchronized(dataModel) {

            List<ItemInfo> filteredItems = new ArrayList<>();
            for (Pair<ItemInfo, Object> entry : workspaceApps) {
            for (Pair<ItemInfo, Object> entry : mItemList) {
                ItemInfo item = entry.first;
                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
                        item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase {
        for (ItemInfo item : items) {
            list.add(Pair.create(item, null));
        }
        return new AddWorkspaceItemsTask(Provider.of(list)) {
        return new AddWorkspaceItemsTask(list) {

            @Override
            protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) { }