1f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal/*
2f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * Copyright (C) 2016 The Android Open Source Project
3f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal *
4f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * Licensed under the Apache License, Version 2.0 (the "License");
5f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * you may not use this file except in compliance with the License.
6f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * You may obtain a copy of the License at
7f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal *
8f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal *      http://www.apache.org/licenses/LICENSE-2.0
9f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal *
10f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * Unless required by applicable law or agreed to in writing, software
11f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * distributed under the License is distributed on an "AS IS" BASIS,
12f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * See the License for the specific language governing permissions and
14f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * limitations under the License.
15f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal */
16f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalpackage com.android.launcher3.model;
17f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
18f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport android.content.Context;
197c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyalimport android.os.UserHandle;
20f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
21f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.AllAppsList;
22f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.ItemInfo;
23f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.LauncherAppState;
24f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.LauncherModel;
25f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.LauncherSettings;
26f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.ShortcutInfo;
271b0726359b5157db8d3d96c52a37f05fce065618Sunny Goyalimport com.android.launcher3.graphics.LauncherIcons;
28f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.shortcuts.DeepShortcutManager;
29f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.shortcuts.ShortcutInfoCompat;
30f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport com.android.launcher3.util.MultiHashMap;
31f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
32f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport java.util.ArrayList;
33f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalimport java.util.List;
34f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
35f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal/**
36f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal * Handles changes due to shortcut manager updates (deep shortcut changes)
37f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal */
38f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyalpublic class ShortcutsChangedTask extends ExtendedModelTask {
39f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
40f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    private final String mPackageName;
41f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    private final List<ShortcutInfoCompat> mShortcuts;
427c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal    private final UserHandle mUser;
43f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    private final boolean mUpdateIdMap;
44f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
45f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    public ShortcutsChangedTask(String packageName, List<ShortcutInfoCompat> shortcuts,
467c74e4ae641e76f73d74348e293c244a157f6585Sunny Goyal            UserHandle user, boolean updateIdMap) {
47f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        mPackageName = packageName;
48f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        mShortcuts = shortcuts;
49f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        mUser = user;
50f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        mUpdateIdMap = updateIdMap;
51f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    }
52f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
53f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    @Override
54f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
55dde4fd971e825749686e7aa77379c65e410eea54Sunny Goyal        final Context context = app.getContext();
56dde4fd971e825749686e7aa77379c65e410eea54Sunny Goyal        DeepShortcutManager deepShortcutManager = DeepShortcutManager.getInstance(context);
57f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        deepShortcutManager.onShortcutsChanged(mShortcuts);
58f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
59f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        // Find ShortcutInfo's that have changed on the workspace.
60f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        final ArrayList<ShortcutInfo> removedShortcutInfos = new ArrayList<>();
61f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        MultiHashMap<String, ShortcutInfo> idsToWorkspaceShortcutInfos = new MultiHashMap<>();
62f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        for (ItemInfo itemInfo : dataModel.itemsIdMap) {
63f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
64f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                ShortcutInfo si = (ShortcutInfo) itemInfo;
653fe4a146cf774261ab3552dd8ab392439c771e54Sunny Goyal                if (si.getIntent().getPackage().equals(mPackageName)
66f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                        && si.user.equals(mUser)) {
67f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    idsToWorkspaceShortcutInfos.addToList(si.getDeepShortcutId(), si);
68f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                }
69f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            }
70f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        }
71f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
72f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        final ArrayList<ShortcutInfo> updatedShortcutInfos = new ArrayList<>();
73f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        if (!idsToWorkspaceShortcutInfos.isEmpty()) {
74f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            // Update the workspace to reflect the changes to updated shortcuts residing on it.
75f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            List<ShortcutInfoCompat> shortcuts = deepShortcutManager.queryForFullDetails(
76f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    mPackageName, new ArrayList<>(idsToWorkspaceShortcutInfos.keySet()), mUser);
77f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            for (ShortcutInfoCompat fullDetails : shortcuts) {
78f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                List<ShortcutInfo> shortcutInfos = idsToWorkspaceShortcutInfos
79f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                        .remove(fullDetails.getId());
80f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                if (!fullDetails.isPinned()) {
81f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    // The shortcut was previously pinned but is no longer, so remove it from
82f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    // the workspace and our pinned shortcut counts.
83f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    // Note that we put this check here, after querying for full details,
84f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    // because there's a possible race condition between pinning and
85f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    // receiving this callback.
86f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    removedShortcutInfos.addAll(shortcutInfos);
87f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    continue;
88f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                }
89f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                for (ShortcutInfo shortcutInfo : shortcutInfos) {
90f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context);
911b0726359b5157db8d3d96c52a37f05fce065618Sunny Goyal                    shortcutInfo.iconBitmap =
921b0726359b5157db8d3d96c52a37f05fce065618Sunny Goyal                            LauncherIcons.createShortcutIcon(fullDetails, context);
93f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                    updatedShortcutInfos.add(shortcutInfo);
94f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal                }
95f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            }
96f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        }
97f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
98f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        // If there are still entries in idsToWorkspaceShortcutInfos, that means that
99f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        // the corresponding shortcuts weren't passed in onShortcutsChanged(). This
100f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        // means they were cleared, so we remove and unpin them now.
101f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        for (String id : idsToWorkspaceShortcutInfos.keySet()) {
102f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            removedShortcutInfos.addAll(idsToWorkspaceShortcutInfos.get(id));
103f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        }
104f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
105f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        bindUpdatedShortcuts(updatedShortcutInfos, removedShortcutInfos, mUser);
106f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        if (!removedShortcutInfos.isEmpty()) {
10743bf11d9c95f76c2dfeb625b23cb458df81252b3Sunny Goyal            getModelWriter().deleteItemsFromDatabase(removedShortcutInfos);
108f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        }
109f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal
110f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        if (mUpdateIdMap) {
111f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            // Update the deep shortcut map if the list of ids has changed for an activity.
112f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            dataModel.updateDeepShortcutMap(mPackageName, mUser, mShortcuts);
113f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal            bindDeepShortcuts(dataModel);
114f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal        }
115f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal    }
116f0ba8b7ca1dc8fd53451d3d16e9f4fc306cddcd4Sunny Goyal}
117