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 static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER;
19 
20 import android.content.Context;
21 import android.content.pm.ShortcutInfo;
22 import android.os.UserHandle;
23 
24 import com.android.launcher3.LauncherAppState;
25 import com.android.launcher3.LauncherSettings;
26 import com.android.launcher3.model.data.WorkspaceItemInfo;
27 import com.android.launcher3.shortcuts.ShortcutKey;
28 import com.android.launcher3.shortcuts.ShortcutRequest;
29 import com.android.launcher3.shortcuts.ShortcutRequest.QueryResult;
30 import com.android.launcher3.util.ComponentKey;
31 import com.android.launcher3.util.ItemInfoMatcher;
32 
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.Iterator;
37 
38 /**
39  * Task to handle changing of lock state of the user
40  */
41 public class UserLockStateChangedTask extends BaseModelUpdateTask {
42 
43     private final UserHandle mUser;
44     private boolean mIsUserUnlocked;
45 
UserLockStateChangedTask(UserHandle user, boolean isUserUnlocked)46     public UserLockStateChangedTask(UserHandle user, boolean isUserUnlocked) {
47         mUser = user;
48         mIsUserUnlocked = isUserUnlocked;
49     }
50 
51     @Override
execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps)52     public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
53         Context context = app.getContext();
54 
55         HashMap<ShortcutKey, ShortcutInfo> pinnedShortcuts = new HashMap<>();
56         if (mIsUserUnlocked) {
57             QueryResult shortcuts = new ShortcutRequest(context, mUser)
58                     .query(ShortcutRequest.PINNED);
59             if (shortcuts.wasSuccess()) {
60                 for (ShortcutInfo shortcut : shortcuts) {
61                     pinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut);
62                 }
63             } else {
64                 // Shortcut manager can fail due to some race condition when the lock state
65                 // changes too frequently. For the purpose of the update,
66                 // consider it as still locked.
67                 mIsUserUnlocked = false;
68             }
69         }
70 
71         // Update the workspace to reflect the changes to updated shortcuts residing on it.
72         ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
73         HashSet<ShortcutKey> removedKeys = new HashSet<>();
74 
75         synchronized (dataModel) {
76             dataModel.forAllWorkspaceItemInfos(mUser, si -> {
77                 if (si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
78                     if (mIsUserUnlocked) {
79                         ShortcutKey key = ShortcutKey.fromItemInfo(si);
80                         ShortcutInfo shortcut = pinnedShortcuts.get(key);
81                         // We couldn't verify the shortcut during loader. If its no longer available
82                         // (probably due to clear data), delete the workspace item as well
83                         if (shortcut == null) {
84                             removedKeys.add(key);
85                             return;
86                         }
87                         si.runtimeStatusFlags &= ~FLAG_DISABLED_LOCKED_USER;
88                         si.updateFromDeepShortcutInfo(shortcut, context);
89                         app.getIconCache().getShortcutIcon(si, shortcut);
90                     } else {
91                         si.runtimeStatusFlags |= FLAG_DISABLED_LOCKED_USER;
92                     }
93                     updatedWorkspaceItemInfos.add(si);
94                 }
95             });
96         }
97         bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
98         if (!removedKeys.isEmpty()) {
99             deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys));
100         }
101 
102         // Remove shortcut id map for that user
103         Iterator<ComponentKey> keysIter = dataModel.deepShortcutMap.keySet().iterator();
104         while (keysIter.hasNext()) {
105             if (keysIter.next().user.equals(mUser)) {
106                 keysIter.remove();
107             }
108         }
109 
110         if (mIsUserUnlocked) {
111             dataModel.updateDeepShortcutCounts(
112                     null, mUser,
113                     new ShortcutRequest(context, mUser).query(ShortcutRequest.ALL));
114         }
115         bindDeepShortcuts(dataModel);
116     }
117 }
118