1 /* 2 * Copyright (C) 2016 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.model; 17 18 import android.content.Context; 19 import android.os.UserHandle; 20 21 import com.android.launcher3.AllAppsList; 22 import com.android.launcher3.ItemInfo; 23 import com.android.launcher3.LauncherAppState; 24 import com.android.launcher3.LauncherSettings; 25 import com.android.launcher3.ShortcutInfo; 26 import com.android.launcher3.graphics.LauncherIcons; 27 import com.android.launcher3.shortcuts.DeepShortcutManager; 28 import com.android.launcher3.shortcuts.ShortcutInfoCompat; 29 import com.android.launcher3.shortcuts.ShortcutKey; 30 import com.android.launcher3.util.ItemInfoMatcher; 31 import com.android.launcher3.util.MultiHashMap; 32 import com.android.launcher3.util.Provider; 33 34 import java.util.ArrayList; 35 import java.util.HashSet; 36 import java.util.List; 37 38 /** 39 * Handles changes due to shortcut manager updates (deep shortcut changes) 40 */ 41 public class ShortcutsChangedTask extends BaseModelUpdateTask { 42 43 private final String mPackageName; 44 private final List<ShortcutInfoCompat> mShortcuts; 45 private final UserHandle mUser; 46 private final boolean mUpdateIdMap; 47 48 public ShortcutsChangedTask(String packageName, List<ShortcutInfoCompat> shortcuts, 49 UserHandle user, boolean updateIdMap) { 50 mPackageName = packageName; 51 mShortcuts = shortcuts; 52 mUser = user; 53 mUpdateIdMap = updateIdMap; 54 } 55 56 @Override 57 public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { 58 final Context context = app.getContext(); 59 DeepShortcutManager deepShortcutManager = DeepShortcutManager.getInstance(context); 60 deepShortcutManager.onShortcutsChanged(mShortcuts); 61 62 // Find ShortcutInfo's that have changed on the workspace. 63 HashSet<ShortcutKey> removedKeys = new HashSet<>(); 64 MultiHashMap<ShortcutKey, ShortcutInfo> keyToShortcutInfo = new MultiHashMap<>(); 65 HashSet<String> allIds = new HashSet<>(); 66 67 for (ItemInfo itemInfo : dataModel.itemsIdMap) { 68 if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) { 69 ShortcutInfo si = (ShortcutInfo) itemInfo; 70 if (si.getIntent().getPackage().equals(mPackageName) && si.user.equals(mUser)) { 71 keyToShortcutInfo.addToList(ShortcutKey.fromItemInfo(si), si); 72 allIds.add(si.getDeepShortcutId()); 73 } 74 } 75 } 76 77 final ArrayList<ShortcutInfo> updatedShortcutInfos = new ArrayList<>(); 78 if (!keyToShortcutInfo.isEmpty()) { 79 // Update the workspace to reflect the changes to updated shortcuts residing on it. 80 List<ShortcutInfoCompat> shortcuts = deepShortcutManager.queryForFullDetails( 81 mPackageName, new ArrayList<>(allIds), mUser); 82 for (ShortcutInfoCompat fullDetails : shortcuts) { 83 ShortcutKey key = ShortcutKey.fromInfo(fullDetails); 84 List<ShortcutInfo> shortcutInfos = keyToShortcutInfo.remove(key); 85 if (!fullDetails.isPinned()) { 86 // The shortcut was previously pinned but is no longer, so remove it from 87 // the workspace and our pinned shortcut counts. 88 // Note that we put this check here, after querying for full details, 89 // because there's a possible race condition between pinning and 90 // receiving this callback. 91 removedKeys.add(key); 92 continue; 93 } 94 for (final ShortcutInfo shortcutInfo : shortcutInfos) { 95 shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context); 96 // If the shortcut is pinned but no longer has an icon in the system, 97 // keep the current icon instead of reverting to the default icon. 98 LauncherIcons li = LauncherIcons.obtain(context); 99 li.createShortcutIcon(fullDetails, true, Provider.of(shortcutInfo.iconBitmap)) 100 .applyTo(shortcutInfo); 101 li.recycle(); 102 updatedShortcutInfos.add(shortcutInfo); 103 } 104 } 105 } 106 107 // If there are still entries in keyToShortcutInfo, that means that 108 // the corresponding shortcuts weren't passed in onShortcutsChanged(). This 109 // means they were cleared, so we remove and unpin them now. 110 removedKeys.addAll(keyToShortcutInfo.keySet()); 111 112 bindUpdatedShortcuts(updatedShortcutInfos, mUser); 113 if (!keyToShortcutInfo.isEmpty()) { 114 deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys)); 115 } 116 117 if (mUpdateIdMap) { 118 // Update the deep shortcut map if the list of ids has changed for an activity. 119 dataModel.updateDeepShortcutMap(mPackageName, mUser, mShortcuts); 120 bindDeepShortcuts(dataModel); 121 } 122 } 123 } 124