131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/*
231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License.
631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at
731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project *
1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and
1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License.
1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
17325dc23624160689e59fbac708cf6f222b20d025Daniel Sandlerpackage com.android.launcher3;
1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
19629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
20f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.BroadcastReceiver;
21f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ComponentName;
22f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentProviderOperation;
23f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentResolver;
24f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentValues;
25f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.Context;
26f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.Intent;
270589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.content.Intent.ShortcutIconResource;
28f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.IntentFilter;
2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.pm.PackageManager;
3031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.pm.ResolveInfo;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.database.Cursor;
3231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Bitmap;
3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.net.Uri;
343611578579b4bfb25616085dafdb1a45207394f9Joe Onoratoimport android.os.Handler;
353611578579b4bfb25616085dafdb1a45207394f9Joe Onoratoimport android.os.HandlerThread;
36756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyalimport android.os.Looper;
370589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.os.Parcelable;
3831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Process;
399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onoratoimport android.os.SystemClock;
40e26d1008eb587303db25797ca02cc32464e45656Sunny Goyalimport android.os.Trace;
41c3919c0e994309982efc8779af57e2bc78dcac43Chris Wrenimport android.provider.BaseColumns;
42a90303bb6fdad59e4a55855edba68c9902192599Winson Chungimport android.text.TextUtils;
43aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.util.Log;
4471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyalimport android.util.LongSparseArray;
45bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport android.util.MutableInt;
46c916834ad0da535f08325bcd902a60070f2f7e53Winson Chungimport android.util.Pair;
4734c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurka
48ffe83f13319cdb833a25596d47cf1af098cc4c60Sunny Goyalimport com.android.launcher3.compat.AppWidgetManagerCompat;
49ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherActivityInfoCompat;
50ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat;
51349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat;
52e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
53ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserHandleCompat;
54ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserManagerCompat;
55a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyalimport com.android.launcher3.config.FeatureFlags;
566c56c68555dcb3d99b05d5faecd582a1f683cc92Sunny Goyalimport com.android.launcher3.config.ProviderConfig;
57827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickhamimport com.android.launcher3.dynamicui.ExtractionUtils;
58261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.Folder;
59261194387beebaa7927ec4e310274218b651494dSunny Goyalimport com.android.launcher3.folder.FolderIcon;
601acb9e9e29bb06b6266781284ae60e9fd4d0962fSunny Goyalimport com.android.launcher3.logging.FileLog;
61f862a26347b583bd84be22a8ceff4bc13158ec7eSunny Goyalimport com.android.launcher3.model.GridSizeMigrationTask;
622bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Songimport com.android.launcher3.model.WidgetsModel;
63a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyalimport com.android.launcher3.provider.ImportDataTask;
64a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyalimport com.android.launcher3.provider.LauncherDbUtils;
65bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.DeepShortcutManager;
66bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.ShortcutInfoCompat;
67bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.ShortcutKey;
6826ace12135a662ad864678c9fede9817e5c02b67Robin Leeimport com.android.launcher3.util.ComponentKey;
694e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyalimport com.android.launcher3.util.CursorIconInfo;
703bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyalimport com.android.launcher3.util.FlagOp;
71ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyalimport com.android.launcher3.util.GridOccupancy;
72e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyalimport com.android.launcher3.util.LongArrayMap;
7318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.util.ManagedProfileHeuristic;
74d82a39da1c61b19d2749725f9c70c3baf2dab6bfTony Wickhamimport com.android.launcher3.util.MultiHashMap;
75d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyalimport com.android.launcher3.util.PackageManagerHelper;
76aaf7d1d13bd88bdeac5c56a9ab1d293fdaea3c11Sunny Goyalimport com.android.launcher3.util.Preconditions;
77da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyalimport com.android.launcher3.util.StringFilter;
78091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
79527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport com.android.launcher3.util.ViewOnDrawExecutor;
80edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
81c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.lang.ref.WeakReference;
82c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.net.URISyntaxException;
83349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyalimport java.security.InvalidParameterException;
84c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.ArrayList;
85dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohenimport java.util.Arrays;
86c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.Collections;
87c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.Comparator;
88c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.HashMap;
89b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chungimport java.util.HashSet;
902abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chungimport java.util.Iterator;
91c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.List;
92bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport java.util.Map;
93f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport java.util.Map.Entry;
94b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chungimport java.util.Set;
95527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyalimport java.util.concurrent.Executor;
96c2f801e770b4f80354b3edb722ec04222251990cMichael Jurka
9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
9831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Maintains in-memory state of the Launcher. It is expected that there should be only one
9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * LauncherModel object held in a static. Also provide APIs for updating the database state
100bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project * for the Launcher.
10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
102ed13187a745866483139e2878037e1f8427ce567Kenny Guypublic class LauncherModel extends BroadcastReceiver
103c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
104a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato    static final boolean DEBUG_LOADERS = false;
105ee52336a9ed0c98f78831a0e44b21f5a8d8c17d1Chris Wren    private static final boolean DEBUG_RECEIVER = false;
106b358f813c93ac0d6c4f31058947efd16b188cd1eChris Wren
1079c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    static final String TAG = "Launcher.Model";
1089c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
1093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
1107aff399974c756930070d82d7b2df88f125dacd6Derek Prothro    private static final long INVALID_SCREEN_ID = -1L;
111a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung
112091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final LauncherAppState mApp;
113091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final Object mLock = new Object();
114091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DeferredHandler mHandler = new DeferredHandler();
115091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk LoaderTask mLoaderTask;
116091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk boolean mIsLoaderTaskRunning;
117756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk boolean mHasLoaderCompletedOnce;
1189c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
119091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
120700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick    static {
121700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick        sWorkerThread.start();
122700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick    }
123091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());
124700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick
125cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // We start off with everything not loaded.  After that, we assume that
126cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // our monitoring of the package manager provides all updates and we never
127cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // need to do a requery.  These are only ever touched from the loader thread.
128bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private boolean mWorkspaceLoaded;
129bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private boolean mAllAppsLoaded;
130bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private boolean mDeepShortcutsLoaded;
131cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato
132756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    /**
133756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     * Set of runnables to be called on the background thread after the workspace binding
134756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     * is complete.
135756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     */
136756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    static final ArrayList<Runnable> mBindCompleteRunnables = new ArrayList<Runnable>();
137756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
138091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk WeakReference<Callbacks> mCallbacks;
1399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
140a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // < only access in worker thread >
1412e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal    private final AllAppsList mBgAllAppsList;
1429110d485fa12c03df3061278717efb342f1142cfHyunyoung Song    // Entire list of widgets.
1432e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal    private final WidgetsModel mBgWidgetsModel;
144a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
145bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    // Maps all launcher activities to the id's of their shortcuts (if they have any).
146bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private final MultiHashMap<ComponentKey, String> mBgDeepShortcutMap = new MultiHashMap<>();
147bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
14895f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    private boolean mHasShortcutHostPermission;
14995f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    // Runnable to check if the shortcuts permission has changed.
15095f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    private final Runnable mShortcutPermissionCheckRunnable = new Runnable() {
15195f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal        @Override
15295f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal        public void run() {
15395f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal            if (mDeepShortcutsLoaded) {
15495f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                boolean hasShortcutHostPermission = mDeepShortcutManager.hasHostPermission();
15595f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                if (hasShortcutHostPermission != mHasShortcutHostPermission) {
15695f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                    mApp.reloadWorkspace();
15795f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                }
15895f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal            }
15995f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal        }
16095f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    };
16195f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal
162b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // The lock that must be acquired before referencing any static bg data structures.  Unlike
163b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // other locks, this one can generally be held long-term because we never expect any of these
164b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // static data structures to be referenced outside of the worker thread except on the first
165b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // load after configuration change.
1662abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung    static final Object sBgLock = new Object();
167b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
168487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
169a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // LauncherModel to their ids
170e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static final LongArrayMap<ItemInfo> sBgItemsIdMap = new LongArrayMap<>();
171a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
172487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts
173487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    //       created by LauncherModel that are directly on the home screen (however, no widgets or
174487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    //       shortcuts within folders).
175487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();
1760589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
177487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()
178487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =
179a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka        new ArrayList<LauncherAppWidgetInfo>();
180a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
181487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
182e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static final LongArrayMap<FolderInfo> sBgFolders = new LongArrayMap<>();
183b1094bd9630f659cc606853b8a244b6a6b6c6943Winson Chung
184dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    // sBgWorkspaceScreens is the ordered set of workspace screens.
185dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
186dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
187bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    // sBgPinnedShortcutCounts is the ComponentKey representing a pinned shortcut to the number of
188bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    // times it is pinned.
189bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    static final Map<ShortcutKey, MutableInt> sBgPinnedShortcutCounts = new HashMap<>();
190bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
191f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal    // sPendingPackages is a set of packages which could be on sdcard and are not available yet
192513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala    static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =
193513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala            new HashMap<UserHandleCompat, HashSet<String>>();
194f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
195a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // </ only access in worker thread >
196a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
197bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private IconCache mIconCache;
198bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private DeepShortcutManager mDeepShortcutManager;
1999c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
200bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private final LauncherAppsCompat mLauncherApps;
201bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private final UserManagerCompat mUserManager;
202ed13187a745866483139e2878037e1f8427ce567Kenny Guy
2039c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    public interface Callbacks {
204ef2efcff5e70e5900f4f10f9e46c3fa17c03b0ecJoe Onorato        public boolean setLoadOnResume();
2059c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public int getCurrentWorkspaceScreen();
206527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        public void clearPendingBinds();
2079c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public void startBinding();
20864359a53dc827797917a8d9a0697a91996789801Winson Chung        public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,
20964359a53dc827797917a8d9a0697a91996789801Winson Chung                              boolean forceAnimateIcons);
210dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        public void bindScreens(ArrayList<Long> orderedScreenIds);
211b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        public void finishFirstPageBind(ViewOnDrawExecutor executor);
21266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        public void finishBindingItems();
2139c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public void bindAppWidget(LauncherAppWidgetInfo info);
214eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public void bindAllApplications(ArrayList<AppInfo> apps);
215d64d1763c590b1c954b759156683abf39ff22945Winson Chung        public void bindAppsAdded(ArrayList<Long> newScreens,
216d64d1763c590b1c954b759156683abf39ff22945Winson Chung                                  ArrayList<ItemInfo> addNotAnimated,
217c58497ee619416c4949b16eb43486c11618b69e5Winson Chung                                  ArrayList<ItemInfo> addAnimated,
218c58497ee619416c4949b16eb43486c11618b69e5Winson Chung                                  ArrayList<AppInfo> addedApps);
219eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public void bindAppsUpdated(ArrayList<AppInfo> apps);
2204390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal        public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
2214390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                ArrayList<ShortcutInfo> removed, UserHandleCompat user);
2224390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal        public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
223756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
2243bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal        public void bindWorkspaceComponentsRemoved(
2253bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                HashSet<String> packageNames, HashSet<ComponentName> components,
2263bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                UserHandleCompat user);
2273bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal        public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
2282e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal        public void notifyWidgetProvidersChanged();
2292e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal        public void bindWidgetsModel(WidgetsModel model);
2301462de39f01cec0ba785386532719cb0207dd827Adam Cohen        public void onPageBoundSynchronously(int page);
231527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        public void executeOnNextDraw(ViewOnDrawExecutor executor);
232bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        public void bindDeepShortcutMap(MultiHashMap<ComponentKey, String> deepShortcutMap);
2339c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
23431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
23564359a53dc827797917a8d9a0697a91996789801Winson Chung    public interface ItemInfoFilter {
23664359a53dc827797917a8d9a0697a91996789801Winson Chung        public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);
23764359a53dc827797917a8d9a0697a91996789801Winson Chung    }
23864359a53dc827797917a8d9a0697a91996789801Winson Chung
239bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter,
240bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            DeepShortcutManager deepShortcutManager) {
241a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung        Context context = app.getContext();
242e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mApp = app;
2431307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert        mBgAllAppsList = new AllAppsList(iconCache, appFilter);
244eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song        mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter);
2450589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = iconCache;
246bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        mDeepShortcutManager = deepShortcutManager;
2470589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
248ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mLauncherApps = LauncherAppsCompat.getInstance(context);
249ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mUserManager = UserManagerCompat.getInstance(context);
2500589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
2510589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
252b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    /** Runs the specified runnable immediately if called from the main thread, otherwise it is
253b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung     * posted on the main thread handler. */
25480f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham    private void runOnMainThread(Runnable r) {
255b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        if (sWorkerThread.getThreadId() == Process.myTid()) {
256b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // If we are on the worker thread, post onto the main handler
257b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            mHandler.post(r);
258b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        } else {
259b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r.run();
260b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
261b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
262b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
263b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    /** Runs the specified runnable immediately if called from the worker thread, otherwise it is
264b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung     * posted on the worker thread handler. */
26580f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham    private static void runOnWorkerThread(Runnable r) {
266b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        if (sWorkerThread.getThreadId() == Process.myTid()) {
267b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r.run();
268b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        } else {
269b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // If we are not on the worker thread, then post to the worker handler
270b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sWorker.post(r);
271b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
272b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
273b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
274756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    public void setPackageState(final PackageInstallInfo installInfo) {
275756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        Runnable updateRunnable = new Runnable() {
276756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
277756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal            @Override
278aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren            public void run() {
279756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                synchronized (sBgLock) {
280756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    final HashSet<ItemInfo> updates = new HashSet<>();
281756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
282756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
283756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        // Ignore install success events as they are handled by Package add events.
284756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        return;
285756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
286756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
287e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                    for (ItemInfo info : sBgItemsIdMap) {
288756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        if (info instanceof ShortcutInfo) {
289756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            ShortcutInfo si = (ShortcutInfo) info;
290756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            ComponentName cn = si.getTargetComponent();
291756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            if (si.isPromise() && (cn != null)
292756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    && installInfo.packageName.equals(cn.getPackageName())) {
293756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                si.setInstallProgress(installInfo.progress);
294756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
295756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) {
296756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    // Mark this info as broken.
297756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
298756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                }
299756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                updates.add(si);
300756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            }
301756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        }
302756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
303756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
304756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    for (LauncherAppWidgetInfo widget : sBgAppWidgets) {
305756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        if (widget.providerName.getPackageName().equals(installInfo.packageName)) {
306756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            widget.installProgress = installInfo.progress;
307756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            updates.add(widget);
308756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        }
309756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
310756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
311756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    if (!updates.isEmpty()) {
312756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        // Push changes to the callback.
313756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        Runnable r = new Runnable() {
314756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            public void run() {
315756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                Callbacks callbacks = getCallback();
316756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                if (callbacks != null) {
317756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    callbacks.bindRestoreItemsChange(updates);
318756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                }
319756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            }
320756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        };
321756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        mHandler.post(r);
322756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
323aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                }
324aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren            }
325aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren        };
326756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        runOnWorkerThread(updateRunnable);
327aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren    }
328aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren
329756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    /**
330756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * Updates the icons and label of all pending icons for the provided package name.
331756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     */
332756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    public void updateSessionDisplayInfo(final String packageName) {
333756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        Runnable updateRunnable = new Runnable() {
334756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
335756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal            @Override
336a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal            public void run() {
337756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                synchronized (sBgLock) {
338d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    ArrayList<ShortcutInfo> updates = new ArrayList<>();
339d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    UserHandleCompat user = UserHandleCompat.myUserHandle();
340756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
341e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                    for (ItemInfo info : sBgItemsIdMap) {
342756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        if (info instanceof ShortcutInfo) {
343756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            ShortcutInfo si = (ShortcutInfo) info;
344756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            ComponentName cn = si.getTargetComponent();
345756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            if (si.isPromise() && (cn != null)
346756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    && packageName.equals(cn.getPackageName())) {
347756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
348756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    // For auto install apps update the icon as well as label.
349756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    mIconCache.getTitleAndIcon(si,
350756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            si.promisedIntent, user,
351756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            si.shouldUseLowResIcon());
352756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                } else {
353756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    // Only update the icon for restored apps.
354756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.updateIcon(mIconCache);
355756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                }
356756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                updates.add(si);
357756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            }
358756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        }
359756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
360756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
361d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    bindUpdatedShortcuts(updates, user);
362a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal                }
363a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal            }
364a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal        };
365756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        runOnWorkerThread(updateRunnable);
366a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal    }
367a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal
36876a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen    public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
369e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final Callbacks callbacks = getCallback();
37076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
37176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (allAppsApps == null) {
37276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            throw new RuntimeException("allAppsApps must not be null");
37376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        }
37476a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (allAppsApps.isEmpty()) {
37576a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            return;
37676a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        }
37776a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
37876a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        // Process the newly added applications and add them to the database first
37976a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        Runnable r = new Runnable() {
38076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            public void run() {
38176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                runOnMainThread(new Runnable() {
38276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                    public void run() {
383e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
38476a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                        if (callbacks == cb && cb != null) {
3856d0dde01f307051ee1849481c989d9e87774b894Chris Wren                            callbacks.bindAppsAdded(null, null, null, allAppsApps);
38676a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                        }
38776a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                    }
38876a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                });
38976a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            }
39076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        };
39176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        runOnWorkerThread(r);
392997a92348a6d6e061737399321393449c16cd4d8Winson Chung    }
39376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
394a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal    private static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> occupiedPos,
39571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            int[] xy, int spanX, int spanY) {
39671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        LauncherAppState app = LauncherAppState.getInstance();
3972e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
398ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal
399ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal        GridOccupancy occupied = new GridOccupancy(profile.numColumns, profile.numRows);
40071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (occupiedPos != null) {
401a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (ItemInfo r : occupiedPos) {
402ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                occupied.markCells(r, true);
40371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
40471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
405ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal        return occupied.findVacantCell(xy, spanX, spanY);
40671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    }
40771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
40871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    /**
40971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * Find a position on the screen for the given size or adds a new screen.
41071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * @return screenId and the coordinates for the item.
41171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     */
412756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk Pair<Long, int[]> findSpaceForItem(
413c3642d45098eed97ee278f7db370335d7fd407fcSunny Goyal            Context context,
41471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            ArrayList<Long> workspaceScreens,
41571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            ArrayList<Long> addedWorkspaceScreensFinal,
41671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            int spanX, int spanY) {
417a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
418a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal
419a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        // Use sBgItemsIdMap as all the items are already loaded.
420756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        assertWorkspaceLoaded();
421a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        synchronized (sBgLock) {
422a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (ItemInfo info : sBgItemsIdMap) {
423a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
424a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    ArrayList<ItemInfo> items = screenItems.get(info.screenId);
425a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    if (items == null) {
426a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        items = new ArrayList<>();
427a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        screenItems.put(info.screenId, items);
428a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    }
429a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    items.add(info);
43071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                }
43171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
43271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
43371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
43471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        // Find appropriate space for the item.
43571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        long screenId = 0;
43671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        int[] cordinates = new int[2];
43771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        boolean found = false;
43871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
43971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        int screenCount = workspaceScreens.size();
44071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        // First check the preferred screen.
441a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;
44271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (preferredScreenIndex < screenCount) {
44371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            screenId = workspaceScreens.get(preferredScreenIndex);
44471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            found = findNextAvailableIconSpaceInScreen(
44571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    screenItems.get(screenId), cordinates, spanX, spanY);
44671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
44771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
44871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (!found) {
449a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            // Search on any of the screens starting from the first screen.
450a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (int screen = 1; screen < screenCount; screen++) {
45171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                screenId = workspaceScreens.get(screen);
45271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                if (findNextAvailableIconSpaceInScreen(
45371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        screenItems.get(screenId), cordinates, spanX, spanY)) {
45471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    // We found a space for it
45571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    found = true;
45671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    break;
45771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                }
45871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
45971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
46071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
46171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (!found) {
46271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // Still no position found. Add a new screen to the end.
463d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal            screenId = LauncherSettings.Settings.call(context.getContentResolver(),
464d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                    LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
465d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                    .getLong(LauncherSettings.Settings.EXTRA_VALUE);
46671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
46771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // Save the screen id for binding in the workspace
46871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            workspaceScreens.add(screenId);
46971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            addedWorkspaceScreensFinal.add(screenId);
47076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
47171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // If we still can't find an empty space, then God help us all!!!
47271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            if (!findNextAvailableIconSpaceInScreen(
47371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    screenItems.get(screenId), cordinates, spanX, spanY)) {
47471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                throw new RuntimeException("Can't find space to add the item");
47571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
476fe9d96a39651de99819208e95c7ec7d432a402e0Winson Chung        }
47771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        return Pair.create(screenId, cordinates);
47871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    }
47971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
48071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    /**
48171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * Adds the provided items to the workspace.
48271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     */
48318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public void addAndBindAddedWorkspaceItems(final Context context,
484a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal            final ArrayList<? extends ItemInfo> workspaceApps) {
48571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        final Callbacks callbacks = getCallback();
48676a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (workspaceApps.isEmpty()) {
4879e6a0a20d40675ef98c7fdb8892cf34b90152f7aWinson Chung            return;
488997a92348a6d6e061737399321393449c16cd4d8Winson Chung        }
48964359a53dc827797917a8d9a0697a91996789801Winson Chung        // Process the newly added applications and add them to the database first
49064359a53dc827797917a8d9a0697a91996789801Winson Chung        Runnable r = new Runnable() {
49164359a53dc827797917a8d9a0697a91996789801Winson Chung            public void run() {
49264359a53dc827797917a8d9a0697a91996789801Winson Chung                final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
49364359a53dc827797917a8d9a0697a91996789801Winson Chung                final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
49464359a53dc827797917a8d9a0697a91996789801Winson Chung
49576828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // Get the list of workspace screens.  We need to append to this list and
49676828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
49776828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // called.
498c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
49964359a53dc827797917a8d9a0697a91996789801Winson Chung                synchronized(sBgLock) {
50071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    for (ItemInfo item : workspaceApps) {
501a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        if (item instanceof ShortcutInfo) {
50271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                            // Short-circuit this logic if the icon exists somewhere on the workspace
503756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            if (shortcutExists(context, item.getIntent(), item.user)) {
50471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                                continue;
505c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung                            }
50664359a53dc827797917a8d9a0697a91996789801Winson Chung                        }
50764359a53dc827797917a8d9a0697a91996789801Winson Chung
50871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        // Find appropriate space for the item.
509c3642d45098eed97ee278f7db370335d7fd407fcSunny Goyal                        Pair<Long, int[]> coords = findSpaceForItem(context,
5109eba1fd75e9fa6b0dc5cad9a4e817b3b167d2461Sunny Goyal                                workspaceScreens, addedWorkspaceScreensFinal, 1, 1);
51171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        long screenId = coords.first;
51271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        int[] cordinates = coords.second;
51371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
51418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        ItemInfo itemInfo;
51518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        if (item instanceof ShortcutInfo || item instanceof FolderInfo) {
51618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                            itemInfo = item;
51771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        } else if (item instanceof AppInfo) {
51818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                            itemInfo = ((AppInfo) item).makeShortcut();
519997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        } else {
520997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            throw new RuntimeException("Unexpected info type");
521997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        }
52294d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung
52364359a53dc827797917a8d9a0697a91996789801Winson Chung                        // Add the shortcut to the db
52418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        addItemToDatabase(context, itemInfo,
52564359a53dc827797917a8d9a0697a91996789801Winson Chung                                LauncherSettings.Favorites.CONTAINER_DESKTOP,
5261d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                                screenId, cordinates[0], cordinates[1]);
52764359a53dc827797917a8d9a0697a91996789801Winson Chung                        // Save the ShortcutInfo for binding in the workspace
52818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        addedShortcutsFinal.add(itemInfo);
52964359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
53064359a53dc827797917a8d9a0697a91996789801Winson Chung                }
53164359a53dc827797917a8d9a0697a91996789801Winson Chung
53276828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // Update the workspace screens
53376828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                updateWorkspaceScreenOrder(context, workspaceScreens);
53476828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
53576a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                if (!addedShortcutsFinal.isEmpty()) {
536997a92348a6d6e061737399321393449c16cd4d8Winson Chung                    runOnMainThread(new Runnable() {
537997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        public void run() {
538e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Callbacks cb = getCallback();
539997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            if (callbacks == cb && cb != null) {
540997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();
541997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();
54294d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                if (!addedShortcutsFinal.isEmpty()) {
54394d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 1);
54494d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    long lastScreenId = info.screenId;
54594d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    for (ItemInfo i : addedShortcutsFinal) {
54694d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        if (i.screenId == lastScreenId) {
54794d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                            addAnimated.add(i);
54894d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        } else {
54994d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                            addNotAnimated.add(i);
55094d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        }
551997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                    }
552997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                }
553d64d1763c590b1c954b759156683abf39ff22945Winson Chung                                callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
55476a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                                        addNotAnimated, addAnimated, null);
555997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            }
55664359a53dc827797917a8d9a0697a91996789801Winson Chung                        }
557997a92348a6d6e061737399321393449c16cd4d8Winson Chung                    });
558997a92348a6d6e061737399321393449c16cd4d8Winson Chung                }
55964359a53dc827797917a8d9a0697a91996789801Winson Chung            }
56064359a53dc827797917a8d9a0697a91996789801Winson Chung        };
56164359a53dc827797917a8d9a0697a91996789801Winson Chung        runOnWorkerThread(r);
56264359a53dc827797917a8d9a0697a91996789801Winson Chung    }
56364359a53dc827797917a8d9a0697a91996789801Winson Chung
5649c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
5659c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Adds an item to the DB if it was not created previously, or move it to a new
5669c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * <container, screen, cellX, cellY>
5679c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
568f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohen    public static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
569dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long screenId, int cellX, int cellY) {
5709c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        if (item.container == ItemInfo.NO_ID) {
5719c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // From all apps
5721d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal            addItemToDatabase(context, item, container, screenId, cellX, cellY);
5739c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        } else {
5749c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // From somewhere else
575dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            moveItemInDatabase(context, item, container, screenId, cellX, cellY);
5769c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
5779c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
57831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
579b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka    static void checkItemInfoLocked(
580b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {
581b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        ItemInfo modelItem = sBgItemsIdMap.get(itemId);
582b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        if (modelItem != null && item != modelItem) {
583b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // check all the data is consistent
584b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {
585b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;
586b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                ShortcutInfo shortcut = (ShortcutInfo) item;
587b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&
588b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.intent.filterEquals(shortcut.intent) &&
589b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.id == shortcut.id &&
590b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.itemType == shortcut.itemType &&
591b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.container == shortcut.container &&
592dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        modelShortcut.screenId == shortcut.screenId &&
593b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.cellX == shortcut.cellX &&
594b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.cellY == shortcut.cellY &&
595b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.spanX == shortcut.spanX &&
596aa8ef119f18864f4ab41c12f9c2ad6d7f643a0a9Sunny Goyal                        modelShortcut.spanY == shortcut.spanY) {
597b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    // For all intents and purposes, this is the same object
598b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    return;
599b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                }
600b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
601b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka
602b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // the modelItem needs to match up perfectly with item if our model is
603b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // to be consistent with the database-- for now, just require
604b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // modelItem == item or the equality check above
605b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            String msg = "item: " + ((item != null) ? item.toString() : "null") +
606b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    "modelItem: " +
607b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    ((modelItem != null) ? modelItem.toString() : "null") +
608b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    "Error: ItemInfo passed to checkItemInfo doesn't match original";
609b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            RuntimeException e = new RuntimeException(msg);
610b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            if (stackTrace != null) {
611b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                e.setStackTrace(stackTrace);
612b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
613b9ada65af30c61c5b35da9b9efac75ffe6c56fd7Adam Cohen            throw e;
614b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        }
615b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka    }
616b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka
617816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka    static void checkItemInfo(final ItemInfo item) {
618816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
619816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        final long itemId = item.id;
620816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        Runnable r = new Runnable() {
621b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            public void run() {
622b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                synchronized (sBgLock) {
623b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    checkItemInfoLocked(itemId, item, stackTrace);
624816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka                }
625b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
626b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        };
627b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
628816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka    }
629816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka
630c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    static void updateItemInDatabaseHelper(Context context, final ContentValues values,
631c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            final ItemInfo item, final String callingFunction) {
632c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final long itemId = item.id;
6331d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal        final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
634c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ContentResolver cr = context.getContentResolver();
635c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
636487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
637c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
638c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            public void run() {
639c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                cr.update(uri, values, null, null);
640f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                updateItemArrays(item, itemId, stackTrace);
641f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
642f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        };
643f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        runOnWorkerThread(r);
644f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
645c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
646f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,
647f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final ArrayList<ItemInfo> items, final String callingFunction) {
648f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        final ContentResolver cr = context.getContentResolver();
649c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
650f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
651f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        Runnable r = new Runnable() {
652f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            public void run() {
653f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                ArrayList<ContentProviderOperation> ops =
654f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        new ArrayList<ContentProviderOperation>();
655f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                int count = items.size();
656f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                for (int i = 0; i < count; i++) {
657f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ItemInfo item = items.get(i);
658f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    final long itemId = item.id;
6591d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
660f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ContentValues values = valuesList.get(i);
661f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
662f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
663f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    updateItemArrays(item, itemId, stackTrace);
664487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen
665f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
666f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                try {
667f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);
668f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                } catch (Exception e) {
669f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    e.printStackTrace();
670c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                }
671c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            }
672c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
673b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
674c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    }
675bebf042666cffe52039b875a549a582abd78a431Adam Cohen
676f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {
677f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        // Lock on mBgLock *after* the db operation
678f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        synchronized (sBgLock) {
679f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            checkItemInfoLocked(itemId, item, stackTrace);
680f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
681f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
682f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
683f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                // Item is in a folder, make sure this folder exists
684f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                if (!sBgFolders.containsKey(item.container)) {
685f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    // An items container is being set to a that of an item which is not in
686f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    // the list of Folders.
687f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    String msg = "item: " + item + " container being set to: " +
688f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                            item.container + ", not in the list of folders";
689f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    Log.e(TAG, msg);
690f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
691f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
692f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
693f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // Items are added/removed from the corresponding FolderInfo elsewhere, such
694f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // as in Workspace.onDrop. Here, we just add/remove them from the list of items
695f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // that are on the desktop, as appropriate
696f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            ItemInfo modelItem = sBgItemsIdMap.get(itemId);
69733231f587e1a6f716af68e6198df774d2847a8e5Winson Chung            if (modelItem != null &&
69833231f587e1a6f716af68e6198df774d2847a8e5Winson Chung                    (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
69933231f587e1a6f716af68e6198df774d2847a8e5Winson Chung                     modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
700f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                switch (modelItem.itemType) {
701f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
702f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
703bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
704f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
705f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        if (!sBgWorkspaceItems.contains(modelItem)) {
706f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                            sBgWorkspaceItems.add(modelItem);
707f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        }
708f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        break;
709f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    default:
710f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        break;
711f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
712f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            } else {
713f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                sBgWorkspaceItems.remove(modelItem);
714f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
715f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        }
716f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
717f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
7189c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
7199c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Move an item in the DB to a new <container, screen, cellX, cellY>
7209c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
72183a8f042adda926489494dff217c15ab696139b4Sunny Goyal    public static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
722dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final long screenId, final int cellX, final int cellY) {
7239c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.container = container;
7249c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellX = cellX;
7259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellY = cellY;
726c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
7273d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // We store hotseat items in canonical form which is this orientation invariant position
7283d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // in the hotseat
729dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
7303d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
7312fd020860533e18c64a93d14d11cb2d34bc9cbafTony            item.screenId = Launcher.getLauncher(context).getHotseat()
7322fd020860533e18c64a93d14d11cb2d34bc9cbafTony                    .getOrderInHotseat(cellX, cellY);
7333d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        } else {
734dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
7353d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        }
73631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7379c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentValues values = new ContentValues();
7389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
7393d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
7403d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
74108f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal        values.put(LauncherSettings.Favorites.RANK, item.rank);
742dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
743ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
744c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
74531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
74631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
74731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
748f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the
749f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     * cellX, cellY have already been updated on the ItemInfos.
750f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     */
751f9c184a619e4e4b82cf9e0bf318ca6d8deaaaee7Adam Cohen    public static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,
752f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final long container, final int screen) {
753f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
754f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();
755f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        int count = items.size();
756f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
757f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        for (int i = 0; i < count; i++) {
758f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            ItemInfo item = items.get(i);
759f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            item.container = container;
760f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
761f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // We store hotseat items in canonical form which is this orientation invariant position
762f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // in the hotseat
763f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            if (context instanceof Launcher && screen < 0 &&
764f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
7652fd020860533e18c64a93d14d11cb2d34bc9cbafTony                item.screenId = Launcher.getLauncher(context).getHotseat().getOrderInHotseat(item.cellX,
766f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        item.cellY);
767f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            } else {
768dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                item.screenId = screen;
769f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
770f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
771f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final ContentValues values = new ContentValues();
772f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CONTAINER, item.container);
773f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CELLX, item.cellX);
774f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CELLY, item.cellY);
77508f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal            values.put(LauncherSettings.Favorites.RANK, item.rank);
776dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
777f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
778f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            contentValues.add(values);
779f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        }
780f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");
781f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
782f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
783f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    /**
784bebf042666cffe52039b875a549a582abd78a431Adam Cohen     * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>
785d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen     */
786bebf042666cffe52039b875a549a582abd78a431Adam Cohen    static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,
787dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {
7880f84a604563037ea65883b99d30e7ff802d986c2Winson Chung        item.container = container;
789d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        item.cellX = cellX;
790d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        item.cellY = cellY;
791bebf042666cffe52039b875a549a582abd78a431Adam Cohen        item.spanX = spanX;
792bebf042666cffe52039b875a549a582abd78a431Adam Cohen        item.spanY = spanY;
793bebf042666cffe52039b875a549a582abd78a431Adam Cohen
794bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // We store hotseat items in canonical form which is this orientation invariant position
795bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // in the hotseat
796dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
797bebf042666cffe52039b875a549a582abd78a431Adam Cohen                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
7982fd020860533e18c64a93d14d11cb2d34bc9cbafTony            item.screenId = Launcher.getLauncher(context).getHotseat()
7992fd020860533e18c64a93d14d11cb2d34bc9cbafTony                    .getOrderInHotseat(cellX, cellY);
800bebf042666cffe52039b875a549a582abd78a431Adam Cohen        } else {
801dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
802bebf042666cffe52039b875a549a582abd78a431Adam Cohen        }
803d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
804d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        final ContentValues values = new ContentValues();
805d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
806bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
807bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
80808f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal        values.put(LauncherSettings.Favorites.RANK, item.rank);
809bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.SPANX, item.spanX);
810bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.SPANY, item.spanY);
811dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
812d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
813816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");
814bebf042666cffe52039b875a549a582abd78a431Adam Cohen    }
815c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
816c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    /**
817c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * Update an item to the database in a specified container.
818c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     */
81983a8f042adda926489494dff217c15ab696139b4Sunny Goyal    public static void updateItemInDatabase(Context context, final ItemInfo item) {
820c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ContentValues values = new ContentValues();
821ed13187a745866483139e2878037e1f8427ce567Kenny Guy        item.onAddToDatabase(context, values);
822c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
823d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
824d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
825756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    private void assertWorkspaceLoaded() {
8268f531dd9883443265afba8b94db62e78ce02ca57Sunny Goyal        if (ProviderConfig.IS_DOGFOOD_BUILD) {
827639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal            synchronized (mLock) {
828639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                if (!mHasLoaderCompletedOnce ||
829639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        (mLoaderTask != null && mLoaderTask.mIsLoadingAndBindingWorkspace)) {
830639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    throw new RuntimeException("Trying to add shortcut while loader is running");
831639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                }
832639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal            }
833756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        }
834756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    }
835756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
836d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    /**
837756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * Returns true if the shortcuts already exists on the workspace. This must be called after
838756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * the workspace has been loaded. We identify a shortcut by its intent.
839bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project     */
840756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk boolean shortcutExists(Context context, Intent intent, UserHandleCompat user) {
841756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        assertWorkspaceLoaded();
842dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal        final String intentWithPkg, intentWithoutPkg;
8432a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        if (intent.getComponent() != null) {
8442a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            // If component is not null, an intent with null package will produce
8452a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            // the same result and should also be a match.
8464e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            String packageName = intent.getComponent().getPackageName();
8472a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            if (intent.getPackage() != null) {
848dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithPkg = intent.toUri(0);
849dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0);
8502a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            } else {
851dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithPkg = new Intent(intent).setPackage(packageName).toUri(0);
852dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithoutPkg = intent.toUri(0);
8532a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            }
8542a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        } else {
855dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal            intentWithPkg = intent.toUri(0);
856dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal            intentWithoutPkg = intent.toUri(0);
8572a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        }
858756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
859756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        synchronized (sBgLock) {
860e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            for (ItemInfo item : sBgItemsIdMap) {
861756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                if (item instanceof ShortcutInfo) {
862756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    ShortcutInfo info = (ShortcutInfo) item;
8634e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    Intent targetIntent = info.promisedIntent == null
8644e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            ? info.intent : info.promisedIntent;
8654e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    if (targetIntent != null && info.user.equals(user)) {
866cbfe71dba38af1d1cd2d2372b649537d7d94610bSunny Goyal                        Intent copyIntent = new Intent(targetIntent);
867cbfe71dba38af1d1cd2d2372b649537d7d94610bSunny Goyal                        copyIntent.setSourceBounds(intent.getSourceBounds());
868cbfe71dba38af1d1cd2d2372b649537d7d94610bSunny Goyal                        String s = copyIntent.toUri(0);
869dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                        if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) {
870dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                            return true;
871dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                        }
872756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
873756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                }
874756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal            }
8759c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
876756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        return false;
877bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project    }
878bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project
879bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project    /**
8809c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Add an item to the database in a specified container. Sets the container, screen, cellX and
8819c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * cellY fields of the item. Also assigns an ID to the item.
8829c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
88318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public static void addItemToDatabase(Context context, final ItemInfo item, final long container,
8841d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal            final long screenId, final int cellX, final int cellY) {
8859c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.container = container;
8869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellX = cellX;
8879c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellY = cellY;
8883d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // We store hotseat items in canonical form which is this orientation invariant position
8893d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // in the hotseat
890dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
8913d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
8922fd020860533e18c64a93d14d11cb2d34bc9cbafTony            item.screenId = Launcher.getLauncher(context).getHotseat()
8932fd020860533e18c64a93d14d11cb2d34bc9cbafTony                    .getOrderInHotseat(cellX, cellY);
8943d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        } else {
895dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
8963d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        }
897ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
8989c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentValues values = new ContentValues();
8999c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
900ed13187a745866483139e2878037e1f8427ce567Kenny Guy        item.onAddToDatabase(context, values);
901ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
902d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal        item.id = LauncherSettings.Settings.call(cr, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
903d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                .getLong(LauncherSettings.Settings.EXTRA_VALUE);
904d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal
905a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka        values.put(LauncherSettings.Favorites._ID, item.id);
906aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
9078e19cf22a4ab86f982b08e7d10b86ea7be56acccJason Monk        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
908c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
909a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            public void run() {
9101d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.insert(LauncherSettings.Favorites.CONTENT_URI, values);
911ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
912b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
9132abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
9148e19cf22a4ab86f982b08e7d10b86ea7be56acccJason Monk                    checkItemInfoLocked(item.id, item, stackTrace);
915b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgItemsIdMap.put(item.id, item);
916b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    switch (item.itemType) {
917b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
918b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            sBgFolders.put(item.id, (FolderInfo) item);
919b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            // Fall through
920b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
921b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
922bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
923b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
924b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
925b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgWorkspaceItems.add(item);
926b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            } else {
927b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                if (!sBgFolders.containsKey(item.container)) {
928b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // Adding an item to a folder that doesn't exist.
929b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    String msg = "adding item: " + item + " to a folder that " +
930b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            " doesn't exist";
93128b3e10fdea4d719b46d2e0da9a916bacc238fd1Adam Cohen                                    Log.e(TAG, msg);
932b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
933487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen                            }
934bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                            if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
935d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                incrementPinnedShortcutCount(
936fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                                        ShortcutKey.fromShortcutInfo((ShortcutInfo) item),
937fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                                        true /* shouldPin */);
938bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                            }
939b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            break;
940b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
941b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            sBgAppWidgets.add((LauncherAppWidgetInfo) item);
942b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            break;
943b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
944a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka                }
945a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            }
946c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
947b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
94831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
94931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
950349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    private static ArrayList<ItemInfo> getItemsByPackageName(
951349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            final String pn, final UserHandleCompat user) {
952e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        ItemInfoFilter filter  = new ItemInfoFilter() {
953e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            @Override
954e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
955e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                return cn.getPackageName().equals(pn) && info.user.equals(user);
956e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            }
957e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        };
958e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal        return filterItemInfos(sBgItemsIdMap, filter);
959349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    }
960349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
961349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    /**
962349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     * Removes all the items from the database corresponding to the specified package.
963349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     */
964349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    static void deletePackageFromDatabase(Context context, final String pn,
965349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            final UserHandleCompat user) {
966349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));
967e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
968e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
969e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    /**
970c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * Removes the specified item from the database
9719c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
972fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal    public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
973e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
974e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        items.add(item);
975e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        deleteItemsFromDatabase(context, items);
976e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
977e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
978e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    /**
979e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     * Removes the specified items from the database
980e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     */
9814390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal    static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
9829c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
98383df188ce0822f4058406e5f2878d1cf34bf413eMichael Jurka        Runnable r = new Runnable() {
984a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            public void run() {
985e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                for (ItemInfo item : items) {
9861d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    final Uri uri = LauncherSettings.Favorites.getContentUri(item.id);
987e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    cr.delete(uri, null, null);
988b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
989e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    // Lock on mBgLock *after* the db operation
990e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    synchronized (sBgLock) {
991e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        switch (item.itemType) {
992e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
993e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgFolders.remove(item.id);
994e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                                for (ItemInfo info: sBgItemsIdMap) {
995e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                    if (info.container == item.id) {
996e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        // We are deleting a folder which still contains items that
997e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        // think they are contained by that folder.
998e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        String msg = "deleting a folder (" + item + ") which still " +
999e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                                "contains items (" + info + ")";
1000e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        Log.e(TAG, msg);
1001e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                    }
1002b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
1003e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgWorkspaceItems.remove(item);
1004e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1005bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
1006fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                                decrementPinnedShortcutCount(ShortcutKey.fromShortcutInfo(
1007fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                                        (ShortcutInfo) item));
1008bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                // Fall through.
1009e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1010e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1011e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgWorkspaceItems.remove(item);
1012e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1013e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1014e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgAppWidgets.remove((LauncherAppWidgetInfo) item);
1015e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1016e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        }
1017e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        sBgItemsIdMap.remove(item.id);
1018b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
1019a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka                }
1020a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            }
102183df188ce0822f4058406e5f2878d1cf34bf413eMichael Jurka        };
1022b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
102331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
102431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
1026bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     * Decrement the count for the given pinned shortcut, unpinning it if the count becomes 0.
1027bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     */
1028bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private static void decrementPinnedShortcutCount(final ShortcutKey pinnedShortcut) {
1029bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        synchronized (sBgLock) {
1030bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            MutableInt count = sBgPinnedShortcutCounts.get(pinnedShortcut);
1031bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            if (count == null || --count.value == 0) {
1032bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                LauncherAppState.getInstance().getShortcutManager().unpinShortcut(pinnedShortcut);
1033bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
1034bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
1035bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
1036bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
1037bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    /**
1038bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     * Increment the count for the given shortcut, pinning it if the count becomes 1.
1039bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     *
1040bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     * As an optimization, the caller can pass shouldPin == false to avoid
1041bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     * unnecessary RPC's if the shortcut is already pinned.
1042bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     */
1043bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private static void incrementPinnedShortcutCount(ShortcutKey pinnedShortcut, boolean shouldPin) {
1044bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        synchronized (sBgLock) {
1045bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            MutableInt count = sBgPinnedShortcutCounts.get(pinnedShortcut);
1046bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            if (count == null) {
1047bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                count = new MutableInt(1);
1048bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                sBgPinnedShortcutCounts.put(pinnedShortcut, count);
1049bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            } else {
1050bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                count.value++;
1051bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
1052bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            if (shouldPin && count.value == 1) {
1053bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                LauncherAppState.getInstance().getShortcutManager().pinShortcut(pinnedShortcut);
1054bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
1055bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
1056bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
1057bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
1058bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    /**
1059dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     * Update the order of the workspace screens in the database. The array list contains
1060dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     * a list of screen ids in the order that they should appear.
1061dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     */
1062e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal    public void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {
106364359a53dc827797917a8d9a0697a91996789801Winson Chung        final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);
1064dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        final ContentResolver cr = context.getContentResolver();
1065dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
1066dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1067dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        // Remove any negative screen ids -- these aren't persisted
106864359a53dc827797917a8d9a0697a91996789801Winson Chung        Iterator<Long> iter = screensCopy.iterator();
1069dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        while (iter.hasNext()) {
1070dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long id = iter.next();
1071dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            if (id < 0) {
1072dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                iter.remove();
1073dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            }
1074dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        }
1075dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1076dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        Runnable r = new Runnable() {
1077dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            @Override
1078dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            public void run() {
1079085c853a5702c45865e9b017d21fa15cf2b151b9Yura                ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
1080dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                // Clear the table
1081085c853a5702c45865e9b017d21fa15cf2b151b9Yura                ops.add(ContentProviderOperation.newDelete(uri).build());
108276828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                int count = screensCopy.size();
1083dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                for (int i = 0; i < count; i++) {
1084dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    ContentValues v = new ContentValues();
108576828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                    long screenId = screensCopy.get(i);
1086dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
1087dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
1088085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
1089085c853a5702c45865e9b017d21fa15cf2b151b9Yura                }
1090085c853a5702c45865e9b017d21fa15cf2b151b9Yura
1091085c853a5702c45865e9b017d21fa15cf2b151b9Yura                try {
1092085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);
1093085c853a5702c45865e9b017d21fa15cf2b151b9Yura                } catch (Exception ex) {
1094085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    throw new RuntimeException(ex);
1095dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
10969e6a0a20d40675ef98c7fdb8892cf34b90152f7aWinson Chung
1097ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                synchronized (sBgLock) {
1098ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    sBgWorkspaceScreens.clear();
1099ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    sBgWorkspaceScreens.addAll(screensCopy);
11004caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                }
1101dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            }
1102dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        };
1103dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        runOnWorkerThread(r);
1104dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    }
1105dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1106dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    /**
1107c0b52fefbc11531d560359c093484099f9d1298eWinson     * Remove the specified folder and all its contents from the database.
11089c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
1109c0b52fefbc11531d560359c093484099f9d1298eWinson    public static void deleteFolderAndContentsFromDatabase(Context context, final FolderInfo info) {
11109c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
1111f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1112c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
1113c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            public void run() {
11141d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
1115b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
11162abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
1117b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgItemsIdMap.remove(info.id);
1118b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgFolders.remove(info.id);
1119b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgWorkspaceItems.remove(info);
1120b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1121c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
11221d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.delete(LauncherSettings.Favorites.CONTENT_URI,
1123c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                        LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
1124b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
11252abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
1126b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    for (ItemInfo childInfo : info.contents) {
1127b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        sBgItemsIdMap.remove(childInfo.id);
1128b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
1129afb01ee74243cede19088e694ca82cea5983c603Adam Cohen                }
1130c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            }
1131c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
1132b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
11339c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
1134f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
11359c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
11369c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Set this as the current Launcher activity object for the loader.
11379c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
11389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    public void initialize(Callbacks callbacks) {
11399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        synchronized (mLock) {
1140aaf7d1d13bd88bdeac5c56a9ab1d293fdaea3c11Sunny Goyal            Preconditions.assertUIThread();
1141aaf7d1d13bd88bdeac5c56a9ab1d293fdaea3c11Sunny Goyal            // Remove any queued UI runnables
1142aaf7d1d13bd88bdeac5c56a9ab1d293fdaea3c11Sunny Goyal            mHandler.cancelAll();
1143aaf7d1d13bd88bdeac5c56a9ab1d293fdaea3c11Sunny Goyal            mCallbacks = new WeakReference<>(callbacks);
1144f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1145f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1146f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1147ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1148c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageChanged(String packageName, UserHandleCompat user) {
1149ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_UPDATE;
1150bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(new PackageUpdatedTask(op, new String[] { packageName },
1151ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1152ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1153ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1154ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1155c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageRemoved(String packageName, UserHandleCompat user) {
1156ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_REMOVE;
1157bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(new PackageUpdatedTask(op, new String[] { packageName },
1158ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1159ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1160ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1161ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1162c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageAdded(String packageName, UserHandleCompat user) {
1163ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_ADD;
1164bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(new PackageUpdatedTask(op, new String[] { packageName },
1165ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1166ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1167ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1168ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1169c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,
1170ed13187a745866483139e2878037e1f8427ce567Kenny Guy            boolean replacing) {
1171bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(
1172144154d435ac535b28c947cd765c02590a683d3aSunny Goyal                new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, packageNames, user));
1173ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1174ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1175ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1176c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,
1177ed13187a745866483139e2878037e1f8427ce567Kenny Guy            boolean replacing) {
1178ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!replacing) {
1179bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            enqueueItemUpdatedTask(new PackageUpdatedTask(
1180ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    PackageUpdatedTask.OP_UNAVAILABLE, packageNames,
1181ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    user));
1182ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
1183ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1184ed13187a745866483139e2878037e1f8427ce567Kenny Guy
118544cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    @Override
118644cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    public void onPackagesSuspended(String[] packageNames, UserHandleCompat user) {
1187bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(new PackageUpdatedTask(
118844cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                PackageUpdatedTask.OP_SUSPEND, packageNames,
118944cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                user));
119044cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    }
119144cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy
119244cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    @Override
119344cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    public void onPackagesUnsuspended(String[] packageNames, UserHandleCompat user) {
1194bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        enqueueItemUpdatedTask(new PackageUpdatedTask(
119544cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                PackageUpdatedTask.OP_UNSUSPEND, packageNames,
119644cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                user));
119744cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy    }
119844cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy
1199bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    @Override
1200bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    public void onShortcutsChanged(String packageName, List<ShortcutInfoCompat> shortcuts,
1201bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            UserHandleCompat user) {
120250941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        enqueueItemUpdatedTask(new ShortcutsChangedTask(packageName, shortcuts, user, true));
120350941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal    }
120450941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal
120550941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal    public void updatePinnedShortcuts(String packageName, List<ShortcutInfoCompat> shortcuts,
120650941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal            UserHandleCompat user) {
120750941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        enqueueItemUpdatedTask(new ShortcutsChangedTask(packageName, shortcuts, user, false));
1208bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
1209bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
12101d8e7bbe09e130af5e9534cc26a65f623be7a424Joe Onorato    /**
12119c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
12129c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * ACTION_PACKAGE_CHANGED.
12139c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
1214cb1a4778686a46c46d8dc88b6c83674f6fac6592Narayan Kamath    @Override
1215f99f8c1ad265cf7bea7e30476911d730b7d0eaaeJoe Onorato    public void onReceive(Context context, Intent intent) {
1216b358f813c93ac0d6c4f31058947efd16b188cd1eChris Wren        if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
1217aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
12183611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        final String action = intent.getAction();
1219ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
122093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // If we have changed locale we need to clear out the labels in all apps/workspace.
122193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            forceReload();
1222d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
1223d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
1224823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyal            UserManagerCompat.getInstance(context).enableAndResetCache();
1225957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal            forceReload();
1226d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action) ||
1227d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action) ||
1228d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
1229da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal            UserHandleCompat user = UserHandleCompat.fromIntent(intent);
1230da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal            if (user != null) {
1231d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action) ||
1232d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)) {
1233d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    enqueueItemUpdatedTask(new PackageUpdatedTask(
1234d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                            PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE,
1235d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                            new String[0], user));
1236d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                }
1237d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
1238d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                // ACTION_MANAGED_PROFILE_UNAVAILABLE sends the profile back to locked mode, so
1239d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                // we need to run the state change task again.
1240d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                if (Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action) ||
1241d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
1242d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    enqueueItemUpdatedTask(new UserLockStateChangedTask(user));
1243d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                }
1244da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal            }
1245827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham        } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(action)) {
1246827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham            ExtractionUtils.startColorExtractionServiceIfNecessary(context);
1247e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        }
1248e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    }
1249e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato
12506cc806d678c8a44478308119c087ac9adde73b66Amith Yamasani    void forceReload() {
1251f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        resetLoadedState(true, true);
1252f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
1253f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // Do this here because if the launcher activity is running it will be restarted.
1254f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // If it's not running startLoaderFromBackground will merely tell it that it needs
1255f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // to reload.
1256f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        startLoaderFromBackground();
1257f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung    }
1258f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
1259f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung    public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {
126093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        synchronized (mLock) {
126193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // Stop any existing loaders first, so they don't set mAllAppsLoaded or
126293f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // mWorkspaceLoaded to true later
126393f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            stopLoaderLocked();
1264f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung            if (resetAllAppsLoaded) mAllAppsLoaded = false;
1265f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung            if (resetWorkspaceLoaded) mWorkspaceLoaded = false;
1266bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            // Always reset deep shortcuts loaded.
126795f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal            // TODO: why?
1268bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            mDeepShortcutsLoaded = false;
126993f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        }
127093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee    }
127193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee
1272e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    /**
1273e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * When the launcher is in the background, it's possible for it to miss paired
1274e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * configuration changes.  So whenever we trigger the loader from the background
1275e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * tell the launcher that it needs to re-run the loader when it comes back instead
1276e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * of doing it now.
1277e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     */
1278e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    public void startLoaderFromBackground() {
1279e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        Callbacks callbacks = getCallback();
1280e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        if (callbacks != null) {
1281e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            // Only actually run the loader if they're not paused.
1282e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (!callbacks.setLoadOnResume()) {
128393f878c1686f0438f399353b6fa61ac256f89e6dSunny Goyal                startLoader(callbacks.getCurrentWorkspaceScreen());
1284e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato            }
1285e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        }
12863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
1287f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
12882bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    /**
12892bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal     * If there is already a loader task running, tell it to stop.
12902bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal     */
12912bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    private void stopLoaderLocked() {
129293f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        LoaderTask oldTask = mLoaderTask;
129393f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        if (oldTask != null) {
129493f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            oldTask.stopLocked();
129593f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        }
129693f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee    }
129793f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee
12981a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen    public boolean isCurrentCallbacks(Callbacks callbacks) {
12991a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen        return (mCallbacks != null && mCallbacks.get() == callbacks);
13001a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen    }
13011a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen
1302b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    /**
1303b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal     * Starts the loader. Tries to bind {@params synchronousBindPage} synchronously if possible.
1304b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal     * @return true if the page could be bound synchronously.
1305b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal     */
1306b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal    public boolean startLoader(int synchronousBindPage) {
1307756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
1308756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        InstallShortcutReceiver.enableInstallQueue();
13093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        synchronized (mLock) {
13103611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Don't bother to start the thread if we know it's not going to do anything
13113611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (mCallbacks != null && mCallbacks.get() != null) {
1312527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                final Callbacks oldCallbacks = mCallbacks.get();
1313527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                // Clear any pending bind-runnables from the synchronized load process.
1314527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                runOnMainThread(new Runnable() {
1315527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                    public void run() {
1316527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                        oldCallbacks.clearPendingBinds();
1317527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                    }
1318527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                });
1319527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
13203611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // If there is already one running, tell it to stop.
13212bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal                stopLoaderLocked();
1322ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal                mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
132395f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                // TODO: mDeepShortcutsLoaded does not need to be true for synchronous bind.
132480f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE && mAllAppsLoaded
132580f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham                        && mWorkspaceLoaded && mDeepShortcutsLoaded && !mIsLoaderTaskRunning) {
1326b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
1327b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    return true;
1328b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
1329b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
1330b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sWorker.post(mLoaderTask);
1331b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1332b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1333b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
1334b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal        return false;
1335b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
1336b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
13373611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    public void stopLoader() {
13383611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        synchronized (mLock) {
13393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (mLoaderTask != null) {
13403611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mLoaderTask.stopLocked();
13419c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
1342f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
13433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
1344b132a97cb7ee976bc54370fd0d5899876eaaf33aRomain Guy
1345c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal    /**
1346c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal     * Loads the workspace screen ids in an ordered list.
1347c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal     */
1348e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal    public static ArrayList<Long> loadWorkspaceScreensDb(Context context) {
134976828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        final ContentResolver contentResolver = context.getContentResolver();
135076828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
135176828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
1352c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal        // Get screens ordered by rank.
1353a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyal        return LauncherDbUtils.getScreenIdsFromCursor(contentResolver.query(
1354a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyal                screensUri, null, null, null, LauncherSettings.WorkspaceScreens.SCREEN_RANK));
135576828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung    }
135676828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
13573611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    /**
13583611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     * Runnable for the thread that loads the contents of the launcher:
13593611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - workspace icons
13603611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - widgets
13613611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - all apps icons
1362bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham     *   - deep shortcuts within apps
13633611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     */
13643611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private class LoaderTask implements Runnable {
13653611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private Context mContext;
136693f878c1686f0438f399353b6fa61ac256f89e6dSunny Goyal        private int mPageToBindFirst;
136793f878c1686f0438f399353b6fa61ac256f89e6dSunny Goyal
1368091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen        @Thunk boolean mIsLoadingAndBindingWorkspace;
13693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private boolean mStopped;
1370091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen        @Thunk boolean mLoadAndBindStepFinished;
1371b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1372ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal        LoaderTask(Context context, int pageToBindFirst) {
13733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mContext = context;
137493f878c1686f0438f399353b6fa61ac256f89e6dSunny Goyal            mPageToBindFirst = pageToBindFirst;
13753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1376f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
137766cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void loadAndBindWorkspace() {
137836a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung            mIsLoadingAndBindingWorkspace = true;
137936a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung
13803611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Load the workspace
13813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
13823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
13833611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1384288a36b563801a26d00084cb823435a3ba4cb76cMichael Jurka
1385a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            if (!mWorkspaceLoaded) {
138666cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                loadWorkspace();
138793f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                synchronized (LoaderTask.this) {
138893f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    if (mStopped) {
138966cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        return;
139093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    }
139193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    mWorkspaceLoaded = true;
13929c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
13933611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1394cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato
13953611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Bind the workspace
139693f878c1686f0438f399353b6fa61ac256f89e6dSunny Goyal            bindWorkspace(mPageToBindFirst);
13973611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1398f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
13993611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void waitForIdle() {
14003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Wait until the either we're stopped or the other threads are done.
14013611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // This way we don't start loading all apps until the workspace has settled
14023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // down.
14033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (LoaderTask.this) {
14043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
1405843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
14063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.postIdle(new Runnable() {
14073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        public void run() {
14083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            synchronized (LoaderTask.this) {
14093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                mLoadAndBindStepFinished = true;
14103611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                if (DEBUG_LOADERS) {
14113611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                    Log.d(TAG, "done with previous binding step");
14129c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
14133611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                LoaderTask.this.notify();
14149c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                            }
14159c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
14163611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    });
14173611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
141871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                while (!mStopped && !mLoadAndBindStepFinished) {
14193611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    try {
1420c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        // Just in case mFlushingWorkerThread changes but we aren't woken up,
1421c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        // wait no longer than 1sec at a time
1422c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        this.wait(1000);
14233611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    } catch (InterruptedException ex) {
14243611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        // Ignore
14259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
14263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
14273611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (DEBUG_LOADERS) {
14283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Log.d(TAG, "waited "
1429aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                            + (SystemClock.uptimeMillis()-workspaceWaitTime)
14303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            + "ms for previous step to finish binding");
14319c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
1432843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler            }
14333611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1434f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1435b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        void runBindSynchronousPage(int synchronousBindPage) {
14367aff399974c756930070d82d7b2df88f125dacd6Derek Prothro            if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {
1437b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Ensure that we have a valid page index to load synchronously
1438b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                throw new RuntimeException("Should not call runBindSynchronousPage() without " +
1439b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        "valid page index");
1440b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1441b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            if (!mAllAppsLoaded || !mWorkspaceLoaded) {
1442b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Ensure that we don't try and bind a specified page when the pages have not been
1443b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // loaded already (we should load everything asynchronously in that case)
1444b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                throw new RuntimeException("Expecting AllApps and Workspace to be loaded");
1445b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1446b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            synchronized (mLock) {
1447b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (mIsLoaderTaskRunning) {
1448b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // Ensure that we are never running the background loading at this point since
1449b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // we also touch the background collections
1450b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    throw new RuntimeException("Error! Background loading is already running");
1451b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1452b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1453b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1454b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // XXX: Throw an exception if we are already loading (since we touch the worker thread
1455b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      data structures, we can't allow any other thread to touch that data, but because
1456b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      this call is synchronous, we can get away with not locking).
1457b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1458cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            // The LauncherModel is static in the LauncherAppState and mHandler may have queued
1459a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            // operations from the previous activity.  We need to ensure that all queued operations
1460a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            // are executed before any synchronous binding work is done.
1461a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            mHandler.flush();
1462a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen
1463b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Divide the set of loaded items into those that we are binding synchronously, and
1464b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // everything else that is to be bound normally (asynchronously).
146566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal            bindWorkspace(synchronousBindPage);
1466b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // XXX: For now, continue posting the binding of AllApps as there are other issues that
1467b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      arise from that.
1468b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            onlyBindAllApps();
146980f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham
147080f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham            bindDeepShortcuts();
1471b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
1472b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
14733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void run() {
1474b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            synchronized (mLock) {
1475f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                if (mStopped) {
1476f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    return;
1477f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                }
1478b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                mIsLoaderTaskRunning = true;
1479b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
14803611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Optimize for end-user experience: if the Launcher is up and // running with the
14813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
14823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // workspace first (default).
14833611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            keep_running: {
148464359a53dc827797917a8d9a0697a91996789801Winson Chung                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
148566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                loadAndBindWorkspace();
1486843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
14873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mStopped) {
14883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break keep_running;
14893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
14903611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
14913611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                waitForIdle();
1492f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1493843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler                // second step
149464359a53dc827797917a8d9a0697a91996789801Winson Chung                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
149564359a53dc827797917a8d9a0697a91996789801Winson Chung                loadAndBindAllApps();
1496bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
1497bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                waitForIdle();
1498bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
1499bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                // third step
1500bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                if (DEBUG_LOADERS) Log.d(TAG, "step 3: loading deep shortcuts");
1501bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                loadAndBindDeepShortcuts();
15023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1503843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
15043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Clear out this reference, otherwise we end up holding it until all of the
15053611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // callback runnables are done.
15063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mContext = null;
1507f3d5ea926d4dd1a739b9d3816543728af723cc26Joe Onorato
15083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (mLock) {
15093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // If we are still the last one to be scheduled, remove ourselves.
15103611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mLoaderTask == this) {
15113611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    mLoaderTask = null;
1512843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler                }
1513b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                mIsLoaderTaskRunning = false;
1514756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                mHasLoaderCompletedOnce = true;
15153611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
15163611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1517f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15183611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void stopLocked() {
15193611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (LoaderTask.this) {
15203611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mStopped = true;
15213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                this.notify();
1522f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
15233611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1524f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        /**
15263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * Gets the callbacks object.  If we've been stopped, or if the launcher object
15273611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * has somehow been garbage collected, return null instead.  Pass in the Callbacks
15283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * object that was around when the deferred message was scheduled, and if there's
15293611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * a new Callbacks object around then also return null.  This will save us from
15303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * calling onto it with data that will be ignored.
15313611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         */
15323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
15333611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (mLock) {
15343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mStopped) {
15353611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15363611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
1537ac03330c9684f98b4dd067a87ca70d3e0be1cfedJoe Onorato
15383611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mCallbacks == null) {
15393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15403611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
1541f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15423611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final Callbacks callbacks = mCallbacks.get();
15433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (callbacks != oldCallbacks) {
15443611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15453611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
15463611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (callbacks == null) {
15473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Log.w(TAG, "no mCallbacks");
15483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15499c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
15503611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
15513611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return callbacks;
1552f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
15533611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1554f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15553611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        // check & update map of what's occupied; used to discard overlapping/invalid items
1556ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal        private boolean checkItemPlacement(LongArrayMap<GridOccupancy> occupied, ItemInfo item,
155741cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                   ArrayList<Long> workspaceScreens) {
1558892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            LauncherAppState app = LauncherAppState.getInstance();
15592e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
1560892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung
1561dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long containerIndex = item.screenId;
1562f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
1563a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                // Return early if we detect that an item is under the hotseat button
1564bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal                if (!FeatureFlags.NO_ALL_APPS_ICON &&
1565bb011dad4e69bec027be1e00d573a3095b318b43Sunny Goyal                        profile.isAllAppsButtonRank((int) item.screenId)) {
1566295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                    Log.e(TAG, "Error loading shortcut into hotseat " + item
1567295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                            + " into position (" + item.screenId + ":" + item.cellX + ","
1568295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                            + item.cellY + ") occupied by all apps");
1569a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                    return false;
1570a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                }
1571a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung
1572ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                final GridOccupancy hotseatOccupancy =
1573295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                        occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
1574295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler
15752e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                if (item.screenId >= profile.numHotseatIcons) {
1576ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    Log.e(TAG, "Error loading shortcut " + item
1577ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                            + " into hotseat position " + item.screenId
15782e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                            + ", position out of bounds: (0 to " + (profile.numHotseatIcons - 1)
1579ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                            + ")");
1580ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    return false;
1581ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                }
1582ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
1583ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                if (hotseatOccupancy != null) {
1584ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                    if (hotseatOccupancy.cells[(int) item.screenId][0]) {
1585dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        Log.e(TAG, "Error loading shortcut into hotseat " + item
1586dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                + " into position (" + item.screenId + ":" + item.cellX + ","
1587ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                                + item.cellY + ") already occupied");
1588dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                            return false;
1589295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                    } else {
1590ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                        hotseatOccupancy.cells[(int) item.screenId][0] = true;
1591295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                        return true;
1592dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
15936ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                } else {
1594ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                    final GridOccupancy occupancy = new GridOccupancy(profile.numHotseatIcons, 1);
1595ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                    occupancy.cells[(int) item.screenId][0] = true;
1596ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                    occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, occupancy);
15976ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                    return true;
15986ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                }
159941cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            } else if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
160041cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                if (!workspaceScreens.contains((Long) item.screenId)) {
160141cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                    // The item has an invalid screen id.
160241cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                    return false;
160341cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                }
160441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            } else {
1605f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung                // Skip further checking if it is not the hotseat or workspace container
16063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return true;
16073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1608f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung
1609ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            final int countX = profile.numColumns;
1610ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            final int countY = profile.numRows;
1611ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
1612ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    item.cellX < 0 || item.cellY < 0 ||
1613ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
1614ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                Log.e(TAG, "Error loading shortcut " + item
1615ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + " into cell (" + containerIndex + "-" + item.screenId + ":"
1616ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + item.cellX + "," + item.cellY
1617ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + ") out of screen bounds ( " + countX + "x" + countY + ")");
1618ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                return false;
1619ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen            }
1620ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
1621ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            if (!occupied.containsKey(item.screenId)) {
1622da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                GridOccupancy screen = new GridOccupancy(countX + 1, countY + 1);
1623da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                if (item.screenId == Workspace.FIRST_SCREEN_ID) {
1624a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyal                    // Mark the first row as occupied (if the feature is enabled)
1625a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyal                    // in order to account for the QSB.
1626a9e2f5abb3c21d9721939c625ffb0caabb34e8d9Sunny Goyal                    screen.markCells(0, 0, countX + 1, 1, FeatureFlags.QSB_ON_FIRST_SCREEN);
1627da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                }
1628da4fe1a6244457f144e0a331cada3ada17157809Sunny Goyal                occupied.put(item.screenId, screen);
16298802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler            }
1630ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            final GridOccupancy occupancy = occupied.get(item.screenId);
1631f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung
1632ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            // Check if any workspace icons overlap with each other
1633ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            if (occupancy.isRegionVacant(item.cellX, item.cellY, item.spanX, item.spanY)) {
1634ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                occupancy.markCells(item, true);
1635ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                return true;
1636ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            } else {
1637ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                Log.e(TAG, "Error loading shortcut " + item
1638ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                        + " into cell (" + containerIndex + "-" + item.screenId + ":"
1639ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                        + item.cellX + "," + item.cellX + "," + item.spanX + "," + item.spanY
1640ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                        + ") already occupied");
1641ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                return false;
1642ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal            }
16433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
16448802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler
1645ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        /** Clears all the sBg data structures */
1646ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        private void clearSBgDataStructures() {
1647ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung            synchronized (sBgLock) {
1648ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgWorkspaceItems.clear();
1649ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgAppWidgets.clear();
1650ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgFolders.clear();
1651ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgItemsIdMap.clear();
1652ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgWorkspaceScreens.clear();
1653bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                sBgPinnedShortcutCounts.clear();
1654ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung            }
1655ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        }
1656ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung
165766cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void loadWorkspace() {
1658e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal            if (LauncherAppState.PROFILE_STARTUP) {
1659e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal                Trace.beginSection("Loading Workspace");
1660e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal            }
16613611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
1662f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
16633611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Context context = mContext;
16643611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final ContentResolver contentResolver = context.getContentResolver();
16653611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final PackageManager manager = context.getPackageManager();
16663611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final boolean isSafeMode = manager.isSafeMode();
1667f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
166825aba0aea58b2ecbc0fd350c378fa9e45edb81c3Sunny Goyal            final boolean isSdCardReady = Utilities.isBootCompleted();
1669f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1670892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            LauncherAppState app = LauncherAppState.getInstance();
16712e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
167241cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            int countX = profile.numColumns;
167341cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            int countY = profile.numRows;
1674892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung
1675ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal            boolean clearDb = false;
1676a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            try {
1677a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                ImportDataTask.performImportIfPossible(context);
1678a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            } catch (Exception e) {
1679a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                // Migration failed. Clear workspace.
1680a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal                clearDb = true;
1681a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            }
1682a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal
1683a5c8a9eb666da16bc4c9ea4412868e22ace8d1f0Sunny Goyal            if (!clearDb && GridSizeMigrationTask.ENABLED &&
1684f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                    !GridSizeMigrationTask.migrateGridIfNeeded(mContext)) {
1685f076eae0cab10f035f7b187c72a680cd220acf1bSunny Goyal                // Migration failed. Clear workspace.
1686ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal                clearDb = true;
1687e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal            }
1688e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal
1689ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal            if (clearDb) {
1690a13654529cb557abd946da4d4637593565917ecdSunny Goyal                Log.d(TAG, "loadWorkspace: resetting launcher database");
1691d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                LauncherSettings.Settings.call(contentResolver,
1692d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                        LauncherSettings.Settings.METHOD_DELETE_DB);
1693d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            }
1694d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler
1695ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal            Log.d(TAG, "loadWorkspace: loading default favorites");
1696ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal            LauncherSettings.Settings.call(contentResolver,
1697ded0fdba52d94f8c841598a14dbece36a2f1849cSunny Goyal                    LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);
1698e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen
16992abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            synchronized (sBgLock) {
1700ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                clearSBgDataStructures();
1701756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                final HashMap<String, Integer> installingPkgs = PackageInstallerCompat
17029448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                        .getInstance(mContext).updateAndGetActiveSessionCache();
170341cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
1704b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
17052e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                final ArrayList<Long> itemsToRemove = new ArrayList<>();
17062e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                final ArrayList<Long> restoredRows = new ArrayList<>();
1707bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                Map<ShortcutKey, ShortcutInfoCompat> shortcutKeyToPinnedShortcuts = new HashMap<>();
17081d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
1709e523e70f75ff90ca5d613fb8398d37208e6cd32dChris Wren                if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
1710e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen                final Cursor c = contentResolver.query(contentUri, null, null, null, null);
1711b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1712b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // +1 for the hotseat (it can be larger than the workspace)
1713b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Load workspace in reverse order to ensure that latest items are loaded first (and
1714b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // before any earlier duplicates)
1715ff4ba2d99593ed84963b3f71c555b529dd905835Sunny Goyal                final LongArrayMap<GridOccupancy> occupied = new LongArrayMap<>();
17162e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                HashMap<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null;
1717b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1718b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                try {
1719b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
1720b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int intentIndex = c.getColumnIndexOrThrow
1721b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.INTENT);
1722b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int containerIndex = c.getColumnIndexOrThrow(
1723b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.CONTAINER);
1724b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int itemTypeIndex = c.getColumnIndexOrThrow(
1725b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.ITEM_TYPE);
1726b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int appWidgetIdIndex = c.getColumnIndexOrThrow(
1727b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.APPWIDGET_ID);
1728c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                    final int appWidgetProviderIndex = c.getColumnIndexOrThrow(
1729c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                            LauncherSettings.Favorites.APPWIDGET_PROVIDER);
1730b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int screenIndex = c.getColumnIndexOrThrow(
1731b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.SCREEN);
1732b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int cellXIndex = c.getColumnIndexOrThrow
1733b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.CELLX);
1734b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int cellYIndex = c.getColumnIndexOrThrow
1735b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.CELLY);
1736b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int spanXIndex = c.getColumnIndexOrThrow
1737b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.SPANX);
1738b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int spanYIndex = c.getColumnIndexOrThrow(
1739b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.SPANY);
174008f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                    final int rankIndex = c.getColumnIndexOrThrow(
174108f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                            LauncherSettings.Favorites.RANK);
1742f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                    final int restoredIndex = c.getColumnIndexOrThrow(
1743f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                            LauncherSettings.Favorites.RESTORED);
1744ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    final int profileIdIndex = c.getColumnIndexOrThrow(
1745ed13187a745866483139e2878037e1f8427ce567Kenny Guy                            LauncherSettings.Favorites.PROFILE_ID);
17465d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                    final int optionsIndex = c.getColumnIndexOrThrow(
17475d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                            LauncherSettings.Favorites.OPTIONS);
1748d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    final CursorIconInfo cursorIconInfo = new CursorIconInfo(mContext, c);
1749b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
17507f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    final LongSparseArray<UserHandleCompat> allUsers = new LongSparseArray<>();
1751ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                    final LongSparseArray<Boolean> quietMode = new LongSparseArray<>();
1752d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    final LongSparseArray<Boolean> unlockedUsers = new LongSparseArray<>();
17537f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    for (UserHandleCompat user : mUserManager.getUserProfiles()) {
1754ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                        long serialNo = mUserManager.getSerialNumberForUser(user);
1755ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                        allUsers.put(serialNo, user);
1756ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                        quietMode.put(serialNo, mUserManager.isQuietModeEnabled(user));
1757bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
1758d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        boolean userUnlocked = mUserManager.isUserUnlocked(user);
1759d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
1760d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        // We can only query for shortcuts when the user is unlocked.
1761d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        if (userUnlocked) {
176249f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                            List<ShortcutInfoCompat> pinnedShortcuts =
176349f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                    mDeepShortcutManager.queryForPinnedShortcuts(null, user);
176449f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                            if (mDeepShortcutManager.wasLastCallSuccess()) {
176549f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                for (ShortcutInfoCompat shortcut : pinnedShortcuts) {
176649f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                    shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut),
176749f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                            shortcut);
176849f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                }
176949f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                            } else {
177049f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                // Shortcut manager can fail due to some race condition when the
177149f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                // lock state changes too frequently. For the purpose of the loading
177249f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                // shortcuts, consider the user is still locked.
177349f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                                userUnlocked = false;
1774d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                            }
1775bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        }
177649f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                        unlockedUsers.put(serialNo, userUnlocked);
17777f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    }
17787f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal
1779b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    ShortcutInfo info;
1780b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    String intentDescription;
1781b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    LauncherAppWidgetInfo appWidgetInfo;
1782b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    int container;
1783b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    long id;
178426ace12135a662ad864678c9fede9817e5c02b67Robin Lee                    long serialNumber;
1785b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Intent intent;
1786ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    UserHandleCompat user;
1787d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                    String targetPackage;
1788b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1789b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    while (!mStopped && c.moveToNext()) {
1790b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        try {
1791b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            int itemType = c.getInt(itemTypeIndex);
1792f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                            boolean restored = 0 != c.getInt(restoredIndex);
1793f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                            boolean allowMissingTarget = false;
1794b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            container = c.getInt(containerIndex);
1795b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1796b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            switch (itemType) {
1797b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1798b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1799bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
1800ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                id = c.getLong(idIndex);
1801b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                intentDescription = c.getString(intentIndex);
180226ace12135a662ad864678c9fede9817e5c02b67Robin Lee                                serialNumber = c.getInt(profileIdIndex);
18037f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                user = allUsers.get(serialNumber);
1804349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                int promiseType = c.getInt(restoredIndex);
18051a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                int disabledState = 0;
1806bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                boolean itemReplaced = false;
1807d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                targetPackage = null;
1808ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                if (user == null) {
1809ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    // User has been deleted remove the item.
1810ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    itemsToRemove.add(id);
1811ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    continue;
1812ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                }
1813b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                try {
1814b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    intent = Intent.parseUri(intentDescription, 0);
1815ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    ComponentName cn = intent.getComponent();
1816f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                    if (cn != null && cn.getPackageName() != null) {
1817f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        boolean validPkg = launcherApps.isPackageEnabledForProfile(
1818f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                cn.getPackageName(), user);
1819f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        boolean validComponent = validPkg &&
1820f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                launcherApps.isActivityEnabledForProfile(cn, user);
1821d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                        if (validPkg) {
1822d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                            targetPackage = cn.getPackageName();
1823d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                        }
1824f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
1825f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        if (validComponent) {
1826f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            if (restored) {
1827f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                // no special handling necessary for this item
1828f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                restoredRows.add(id);
1829f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                restored = false;
1830f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            }
1831ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                                            if (quietMode.get(serialNumber)) {
1832d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                                disabledState = ShortcutInfo.FLAG_DISABLED_QUIET_USER;
1833ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                                            }
1834f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        } else if (validPkg) {
1835349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            intent = null;
1836349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
1837349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // We allow auto install apps to have their intent
1838349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // updated after an install.
1839349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                intent = manager.getLaunchIntentForPackage(
1840349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                        cn.getPackageName());
1841349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                if (intent != null) {
1842349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                    ContentValues values = new ContentValues();
1843349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                    values.put(LauncherSettings.Favorites.INTENT,
1844349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                            intent.toUri(0));
1845bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    updateItem(id, values);
1846349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                }
1847349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            }
1848349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
1849349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            if (intent == null) {
1850349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // The app is installed but the component is no
1851349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // longer available.
1852713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                                FileLog.d(TAG, "Invalid component removed: " + cn);
1853349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                itemsToRemove.add(id);
1854349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                continue;
1855349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            } else {
1856349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // no special handling necessary for this item
1857349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                restoredRows.add(id);
1858349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                restored = false;
1859349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            }
1860f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        } else if (restored) {
1861f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // Package is not yet available but might be
1862f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // installed later.
1863713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                            FileLog.d(TAG, "package not yet restored: " + cn);
18649448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal
18659448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
18669448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                // Restore has started once.
1867756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            } else if (installingPkgs.containsKey(cn.getPackageName())) {
18689448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                // App restore has started. Update the flag
18699448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;
18709448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                ContentValues values = new ContentValues();
18719448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                values.put(LauncherSettings.Favorites.RESTORED,
18729448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                        promiseType);
1873bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                updateItem(id, values);
1874bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                            } else if ((promiseType & ShortcutInfo.FLAG_RESTORED_APP_TYPE) != 0) {
1875bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                // This is a common app. Try to replace this.
1876bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                int appType = CommonAppTypeParser.decodeItemTypeFromFlag(promiseType);
1877bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                CommonAppTypeParser parser = new CommonAppTypeParser(id, appType, context);
1878bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                if (parser.findDefaultApp()) {
1879bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    // Default app found. Replace it.
1880bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    intent = parser.parsedIntent;
1881bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    cn = intent.getComponent();
1882bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    ContentValues values = parser.parsedValues;
1883bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    values.put(LauncherSettings.Favorites.RESTORED, 0);
1884bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    updateItem(id, values);
1885bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    restored = false;
1886bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    itemReplaced = true;
1887bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal
1888b05a00a441d7e608fd709fae62bde1c661936e2aSunny Goyal                                                } else {
1889713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                                    FileLog.d(TAG, "Unrestored package removed: " + cn);
1890bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    itemsToRemove.add(id);
1891bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    continue;
1892bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                }
1893b05a00a441d7e608fd709fae62bde1c661936e2aSunny Goyal                                            } else {
1894713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                                FileLog.d(TAG, "Unrestored package removed: " + cn);
18959448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                itemsToRemove.add(id);
18969448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                continue;
18979448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            }
1898d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                        } else if (PackageManagerHelper.isAppOnSdcard(
1899d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                                manager, cn.getPackageName())) {
19001a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Package is present but not available.
19011a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            allowMissingTarget = true;
19021a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
19031a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        } else if (!isSdCardReady) {
1904f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // SdCard is not ready yet. Package might get available,
1905f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // once it is ready.
1906a13654529cb557abd946da4d4637593565917ecdSunny Goyal                                            Log.d(TAG, "Invalid package: " + cn + " (check again later)");
1907f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            HashSet<String> pkgs = sPendingPackages.get(user);
1908f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            if (pkgs == null) {
1909513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala                                                pkgs = new HashSet<String>();
1910f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                sPendingPackages.put(user, pkgs);
1911f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                            }
1912f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            pkgs.add(cn.getPackageName());
1913f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            allowMissingTarget = true;
1914f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // Add the icon on the workspace anyway.
19151a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
19161a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        } else {
19171a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Do not wait for external media load anymore.
19181a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Log the invalid package, and remove it
1919713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                            FileLog.d(TAG, "Invalid package removed: " + cn);
19201a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            itemsToRemove.add(id);
19211a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            continue;
1922ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                        }
1923938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                    } else if (cn == null) {
1924938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        // For shortcuts with no component, keep them as they are
1925938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        restoredRows.add(id);
1926938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        restored = false;
1927ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    }
1928b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                } catch (URISyntaxException e) {
1929713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                    FileLog.d(TAG, "Invalid uri: " + intentDescription);
193041cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    itemsToRemove.add(id);
1931b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    continue;
1932b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
1933968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka
193434b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                                boolean useLowResIcon = container >= 0 &&
193534b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                                        c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
193634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
1937bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                if (itemReplaced) {
1938bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    if (user.equals(UserHandleCompat.myUserHandle())) {
1939d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info = getAppShortcutInfo(intent, user, null,
1940d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                                cursorIconInfo, false, useLowResIcon);
1941bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    } else {
1942bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        // Don't replace items for other profiles.
1943bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        itemsToRemove.add(id);
1944bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        continue;
1945bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    }
1946bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                } else if (restored) {
1947ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    if (user.equals(UserHandleCompat.myUserHandle())) {
1948d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info = getRestoredItemInfo(c, intent,
1949d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                                promiseType, itemType, cursorIconInfo);
1950ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        intent = getRestoredItemIntent(c, context, intent);
1951ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    } else {
1952ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        // Don't restore items for other profiles.
1953ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        itemsToRemove.add(id);
1954ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        continue;
1955ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    }
1956f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                } else if (itemType ==
1957f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                        LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
1958d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    info = getAppShortcutInfo(intent, user, c,
1959d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                            cursorIconInfo, allowMissingTarget, useLowResIcon);
1960bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                } else if (itemType ==
1961bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                        LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
1962d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
1963d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    ShortcutKey key = ShortcutKey.fromIntent(intent, user);
1964d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    if (unlockedUsers.get(serialNumber)) {
1965d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        ShortcutInfoCompat pinnedShortcut =
1966d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                                shortcutKeyToPinnedShortcuts.get(key);
1967d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        if (pinnedShortcut == null) {
1968d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                            // The shortcut is no longer valid.
1969d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                            itemsToRemove.add(id);
1970d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                            continue;
1971bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                        }
1972d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info = new ShortcutInfo(pinnedShortcut, context);
1973d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        intent = info.intent;
1974d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    } else {
1975d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        // Create a shortcut info in disabled mode for now.
1976d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info = new ShortcutInfo();
1977d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info.user = user;
1978d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info.itemType = itemType;
1979d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        loadInfoFromCursor(info, c, cursorIconInfo);
1980d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
1981d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                        info.isDisabled |= ShortcutInfo.FLAG_DISABLED_LOCKED_USER;
1982bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                    }
1983d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    incrementPinnedShortcutCount(key, false /* shouldPin */);
1984bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                                } else { // item type == ITEM_TYPE_SHORTCUT
1985d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                    info = getShortcutInfo(c, cursorIconInfo);
1986b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1987d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                    // Shortcuts are only available on the primary profile
1988d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                    if (PackageManagerHelper.isAppSuspended(manager, targetPackage)) {
1989d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                        disabledState |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
1990d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                    }
1991d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal
1992b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // App shortcuts that used to be automatically added to Launcher
1993b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // didn't always have the correct intent flags set, so do that
1994b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // here
1995b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    if (intent.getAction() != null &&
19969ad005639e1698c94674cdfadf3ae342fb56c9b5Michael Jurka                                        intent.getCategories() != null &&
19979ad005639e1698c94674cdfadf3ae342fb56c9b5Michael Jurka                                        intent.getAction().equals(Intent.ACTION_MAIN) &&
1998968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka                                        intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
1999b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        intent.addFlags(
2000b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            Intent.FLAG_ACTIVITY_NEW_TASK |
2001b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
2002b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2003968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka                                }
20043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
2005b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                if (info != null) {
2006ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    info.id = id;
2007b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.intent = intent;
2008b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.container = container;
2009dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                    info.screenId = c.getInt(screenIndex);
2010b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.cellX = c.getInt(cellXIndex);
2011b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.cellY = c.getInt(cellYIndex);
201208f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                                    info.rank = c.getInt(rankIndex);
20135f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                    info.spanX = 1;
20145f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                    info.spanY = 1;
2015ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
20164e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                    if (info.promisedIntent != null) {
20174e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                        info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
20184e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                    }
2019d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                                    info.isDisabled |= disabledState;
20201a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
20211a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
20221a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    }
2023ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
2024b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // check & update map of what's occupied
202541cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    if (!checkItemPlacement(occupied, info, sBgWorkspaceScreens)) {
2026fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                        itemsToRemove.add(id);
2027b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2028b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2029b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2030756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    if (restored) {
2031756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        ComponentName cn = info.getTargetComponent();
2032756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        if (cn != null) {
2033756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            Integer progress = installingPkgs.get(cn.getPackageName());
2034756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            if (progress != null) {
2035756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                info.setInstallProgress(progress);
2036756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            } else {
2037756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
2038756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            }
2039756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        }
2040756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    }
2041756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
2042b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    switch (container) {
2043b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
2044b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
2045b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        sBgWorkspaceItems.add(info);
2046b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2047b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    default:
2048b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        // Item is in a user folder
2049b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        FolderInfo folderInfo =
2050b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                                findOrMakeFolder(sBgFolders, container);
2051c52ba710053e4c6927937dd1a26d1abe06b6fa99Sunny Goyal                                        folderInfo.add(info, false);
2052b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2053b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2054b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgItemsIdMap.put(info.id, info);
20551323b4856a2a822af77293cadeda9910a5d1ba0eWinson Chung                                } else {
20561323b4856a2a822af77293cadeda9910a5d1ba0eWinson Chung                                    throw new RuntimeException("Unexpected null ShortcutInfo");
2057b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
2058b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                break;
2059b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2060b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
2061b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                id = c.getLong(idIndex);
2062b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);
2063b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2064a508e4f804c2bddf9e2cdfa3d0bd4a8202ff2151Sunny Goyal                                // Do not trim the folder label, as is was set by the user.
2065d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                                folderInfo.title = c.getString(cursorIconInfo.titleIndex);
2066b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.id = id;
2067b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.container = container;
2068dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                folderInfo.screenId = c.getInt(screenIndex);
2069b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.cellX = c.getInt(cellXIndex);
2070b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.cellY = c.getInt(cellYIndex);
20715f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                folderInfo.spanX = 1;
20725f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                folderInfo.spanY = 1;
20735d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                                folderInfo.options = c.getInt(optionsIndex);
20745f8afe6280eae34620067696173e71943e1a30a3Winson Chung
20753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                // check & update map of what's occupied
207641cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                if (!checkItemPlacement(occupied, folderInfo, sBgWorkspaceScreens)) {
2077fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                    itemsToRemove.add(id);
20783611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                    break;
20799c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
20805f8afe6280eae34620067696173e71943e1a30a3Winson Chung
20813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                switch (container) {
2082b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
2083b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
2084b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        sBgWorkspaceItems.add(folderInfo);
2085b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
20869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
208717a8922e2ab2ad599df3750d398a095473ccd1b4Joe Onorato
2088f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                if (restored) {
2089f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                    // no special handling required for restored folders
2090f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                    restoredRows.add(id);
2091f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                }
2092f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
2093b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgItemsIdMap.put(folderInfo.id, folderInfo);
2094b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgFolders.put(folderInfo.id, folderInfo);
2095b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                break;
2096b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2097b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
20985940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                            case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
2099b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                // Read all Launcher-specific widget details
21005940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                boolean customWidget = itemType ==
21015940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                    LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
21025940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
2103b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                int appWidgetId = c.getInt(appWidgetIdIndex);
21047f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                serialNumber = c.getLong(profileIdIndex);
2105c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                                String savedProvider = c.getString(appWidgetProviderIndex);
21063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                id = c.getLong(idIndex);
21077f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                user = allUsers.get(serialNumber);
21087f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                if (user == null) {
21097f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                    itemsToRemove.add(id);
21107f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                    continue;
21117f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                }
21127f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal
2113ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final ComponentName component =
2114ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        ComponentName.unflattenFromString(savedProvider);
2115f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
2116651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                final int restoreStatus = c.getInt(restoredIndex);
2117ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean isIdValid = (restoreStatus &
2118ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;
2119ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean wasProviderReady = (restoreStatus &
2120ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
2121ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
21222e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                if (widgetProvidersMap == null) {
21232e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                    widgetProvidersMap = AppWidgetManagerCompat
21242e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                            .getInstance(mContext).getAllProvidersMap();
21252e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                }
21262e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                final AppWidgetProviderInfo provider = widgetProvidersMap.get(
21272e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                        new ComponentKey(
212826ace12135a662ad864678c9fede9817e5c02b67Robin Lee                                                ComponentName.unflattenFromString(savedProvider),
21292e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                                user));
2130ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2131ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean isProviderReady = isValidProvider(provider);
21325940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                if (!isSafeMode && !customWidget &&
21335940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        wasProviderReady && !isProviderReady) {
2134713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                    FileLog.d(TAG, "Deleting widget that isn't installed anymore: "
2135a13654529cb557abd946da4d4637593565917ecdSunny Goyal                                            + provider);
2136b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    itemsToRemove.add(id);
2137b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                } else {
2138ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                    if (isProviderReady) {
2139651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
2140651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                provider.provider);
21415940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
214253f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // The provider is available. So the widget is either
214353f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // available or not available. We do not need to track
214453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // any future restore updates.
214553f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        int status = restoreStatus &
214653f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                                ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
2147ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        if (!wasProviderReady) {
2148ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // If provider was not previously ready, update the
2149ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // status and UI flag.
2150ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2151ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // Id would be valid only if the widget restore broadcast was received.
2152ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            if (isIdValid) {
215386df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                                status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
2154ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            } else {
2155ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                status &= ~LauncherAppWidgetInfo
2156ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                        .FLAG_PROVIDER_NOT_READY;
2157ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            }
2158ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        }
2159ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        appWidgetInfo.restoreStatus = status;
2160651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                    } else {
2161651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        Log.v(TAG, "Widget restore pending id=" + id
2162651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                + " appWidgetId=" + appWidgetId
2163651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                + " status =" + restoreStatus);
2164651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
2165ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                component);
2166651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo.restoreStatus = restoreStatus;
2167756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        Integer installProgress = installingPkgs.get(component.getPackageName());
21689448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal
21699448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                        if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {
21709448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            // Restore has started once.
2171756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        } else if (installProgress != null) {
21729448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            // App restore has started. Update the flag
21739448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            appWidgetInfo.restoreStatus |=
21749448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                    LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
2175b05a00a441d7e608fd709fae62bde1c661936e2aSunny Goyal                                        } else if (!isSafeMode) {
2176713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                                            FileLog.d(TAG, "Unrestored widget removed: " + component);
21779448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            itemsToRemove.add(id);
21789448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            continue;
21799448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                        }
2180756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
2181756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        appWidgetInfo.installProgress =
2182756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                installProgress == null ? 0 : installProgress;
2183651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                    }
218486df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                    if (appWidgetInfo.hasRestoreFlag(
218586df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                            LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {
218686df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                        intentDescription = c.getString(intentIndex);
218786df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                        if (!TextUtils.isEmpty(intentDescription)) {
218886df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                            appWidgetInfo.bindOptions =
218986df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                                    Intent.parseUri(intentDescription, 0);
219086df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                        }
219186df138d9f5b32d947f3497314694a2a7adac70cSunny Goyal                                    }
2192ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2193b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.id = id;
2194dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                    appWidgetInfo.screenId = c.getInt(screenIndex);
2195b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.cellX = c.getInt(cellXIndex);
2196b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.cellY = c.getInt(cellYIndex);
2197b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.spanX = c.getInt(spanXIndex);
2198b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.spanY = c.getInt(spanYIndex);
2199ab7a4fe206b4ca1c18457738d5068df473a01ea5Sunny Goyal                                    appWidgetInfo.user = user;
2200b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2201b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
2202b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
2203b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        Log.e(TAG, "Widget found where container != " +
220441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                                "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
220541cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                        itemsToRemove.add(id);
2206b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        continue;
2207b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2208b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2209b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    appWidgetInfo.container = container;
2210b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // check & update map of what's occupied
221141cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    if (!checkItemPlacement(occupied, appWidgetInfo, sBgWorkspaceScreens)) {
2212fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                        itemsToRemove.add(id);
2213b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2214b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2215651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal
22165940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                    if (!customWidget) {
22175940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        String providerName =
22185940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                appWidgetInfo.providerName.flattenToString();
22195940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        if (!providerName.equals(savedProvider) ||
22205940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                (appWidgetInfo.restoreStatus != restoreStatus)) {
22215940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            ContentValues values = new ContentValues();
22225940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            values.put(
22235940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    LauncherSettings.Favorites.APPWIDGET_PROVIDER,
22245940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    providerName);
22255940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            values.put(LauncherSettings.Favorites.RESTORED,
22265940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    appWidgetInfo.restoreStatus);
2227bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                            updateItem(id, values);
22285940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        }
2229c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                                    }
2230b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
2231b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgAppWidgets.add(appWidgetInfo);
2232b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
22339c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                break;
22343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            }
2235b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        } catch (Exception e) {
2236a13654529cb557abd946da4d4637593565917ecdSunny Goyal                            Log.e(TAG, "Desktop items loading interrupted", e);
2237b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        }
2238b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2239b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } finally {
2240713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal                    Utilities.closeSilently(c);
2241b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
2242ad72e1705c32da463a552f2283ae467dc15a4a34Joe Onorato
2243ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                // Break early if we've stopped loading
2244ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                if (mStopped) {
2245ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    clearSBgDataStructures();
224666cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    return;
2247ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                }
2248ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung
2249b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (itemsToRemove.size() > 0) {
2250b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // Remove dead items
2251b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    contentResolver.delete(LauncherSettings.Favorites.CONTENT_URI,
2252b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            Utilities.createDbSelectionQuery(
2253b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    LauncherSettings.Favorites._ID, itemsToRemove), null);
2254b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    if (DEBUG_LOADERS) {
2255b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        Log.d(TAG, "Removed = " + Utilities.createDbSelectionQuery(
2256b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                LauncherSettings.Favorites._ID, itemsToRemove));
2257b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    }
2258b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal
2259b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    // Remove any empty folder
2260d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                    ArrayList<Long> deletedFolderIds = (ArrayList<Long>) LauncherSettings.Settings
2261d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                            .call(contentResolver,
2262d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                                    LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS)
2263d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                            .getSerializable(LauncherSettings.Settings.EXTRA_VALUE);
2264d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal                    for (long folderId : deletedFolderIds) {
2265b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgWorkspaceItems.remove(sBgFolders.get(folderId));
2266b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgFolders.remove(folderId);
2267b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgItemsIdMap.remove(folderId);
2268b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2269b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
22708802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler
2271bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                // Unpin shortcuts that don't exist on the workspace.
2272bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                for (ShortcutKey key : shortcutKeyToPinnedShortcuts.keySet()) {
2273bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    MutableInt numTimesPinned = sBgPinnedShortcutCounts.get(key);
2274bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    if (numTimesPinned == null || numTimesPinned.value == 0) {
2275bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        // Shortcut is pinned but doesn't exist on the workspace; unpin it.
2276bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        mDeepShortcutManager.unpinShortcut(key);
2277bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    }
2278bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
2279bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
2280317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                // Sort all the folder items and make sure the first 3 items are high resolution.
2281317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                for (FolderInfo folder : sBgFolders) {
2282317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);
2283317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    int pos = 0;
2284317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    for (ShortcutInfo info : folder.contents) {
2285317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        if (info.usingLowResIcon) {
2286317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                            info.updateIcon(mIconCache, false);
2287317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        }
2288317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        pos ++;
2289317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        if (pos >= FolderIcon.NUM_ITEMS_IN_PREVIEW) {
2290317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                            break;
2291317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        }
2292317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    }
2293317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                }
2294317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal
2295f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                if (restoredRows.size() > 0) {
2296f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                    // Update restored items that no longer require special handling
2297b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    ContentValues values = new ContentValues();
2298b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    values.put(LauncherSettings.Favorites.RESTORED, 0);
2299b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, values,
2300b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            Utilities.createDbSelectionQuery(
2301b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    LauncherSettings.Favorites._ID, restoredRows), null);
2302f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                }
2303f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
2304f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                if (!isSdCardReady && !sPendingPackages.isEmpty()) {
2305f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    context.registerReceiver(new AppsAvailabilityCheck(),
230625aba0aea58b2ecbc0fd350c378fa9e45edb81c3Sunny Goyal                            new IntentFilter(Intent.ACTION_BOOT_COMPLETED),
2307f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                            null, sWorker);
2308f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                }
2309f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
231066cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                // Remove any empty screens
231166cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
2312e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                for (ItemInfo item: sBgItemsIdMap) {
231366cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    long screenId = item.screenId;
231466cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
231566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                            unusedScreens.contains(screenId)) {
231666cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        unusedScreens.remove(screenId);
2317dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
231866cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                }
2319dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
232066cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                // If there are any empty screens remove them, and update.
232166cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                if (unusedScreens.size() != 0) {
232266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    sBgWorkspaceScreens.removeAll(unusedScreens);
232366cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
2324dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
2325dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2326b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (DEBUG_LOADERS) {
2327b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
2328b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Log.d(TAG, "workspace layout: ");
2329dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    int nScreens = occupied.size();
2330892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung                    for (int y = 0; y < countY; y++) {
2331b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        String line = "";
2332dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2333e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                        for (int i = 0; i < nScreens; i++) {
2334e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                            long screenId = occupied.keyAt(i);
2335c916834ad0da535f08325bcd902a60070f2f7e53Winson Chung                            if (screenId > 0) {
2336b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                line += " | ";
2337b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            }
23389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
2339b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        Log.d(TAG, "[ " + line + " ]");
23409c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
23419c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
23423611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2343e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal            if (LauncherAppState.PROFILE_STARTUP) {
2344e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal                Trace.endSection();
2345e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal            }
2346e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen        }
2347e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen
2348bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        /**
2349bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal         * Partially updates the item without any notification. Must be called on the worker thread.
2350bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal         */
2351bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        private void updateItem(long itemId, ContentValues update) {
2352bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal            mContext.getContentResolver().update(
23531d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    LauncherSettings.Favorites.CONTENT_URI,
2354bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    update,
2355bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    BaseColumns._ID + "= ?",
2356bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    new String[]{Long.toString(itemId)});
2357bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        }
2358bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal
2359b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Filters the set of items who are directly or indirectly (via another container) on the
2360b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * specified screen. */
23619b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung        private void filterCurrentWorkspaceItems(long currentScreenId,
2362b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> allWorkspaceItems,
2363b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> currentScreenItems,
2364b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> otherScreenItems) {
23652abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            // Purge any null ItemInfos
23662abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            Iterator<ItemInfo> iter = allWorkspaceItems.iterator();
23672abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            while (iter.hasNext()) {
23682abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                ItemInfo i = iter.next();
23692abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                if (i == null) {
23702abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                    iter.remove();
23712abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                }
23722abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            }
23732abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung
2374b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Order the set of items by their containers first, this allows use to walk through the
2375b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // list sequentially, build up a list of containers that are in the specified screen,
2376b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // as well as all items in those containers.
2377b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Set<Long> itemsOnScreen = new HashSet<Long>();
2378b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {
2379b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                @Override
2380b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                public int compare(ItemInfo lhs, ItemInfo rhs) {
238112fb9fc3c3133c3a748deef7a0265e6a11a24cd6Winson                    return Utilities.longCompare(lhs.container, rhs.container);
2382b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
2383b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            });
2384b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (ItemInfo info : allWorkspaceItems) {
2385b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
23869b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                    if (info.screenId == currentScreenId) {
2387b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        currentScreenItems.add(info);
2388b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        itemsOnScreen.add(info.id);
2389b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    } else {
2390b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        otherScreenItems.add(info);
23913611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
2392b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
2393b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentScreenItems.add(info);
2394b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    itemsOnScreen.add(info.id);
2395b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2396b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    if (itemsOnScreen.contains(info.container)) {
2397b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        currentScreenItems.add(info);
2398b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        itemsOnScreen.add(info.id);
2399b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    } else {
2400b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        otherScreenItems.add(info);
24015c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
24025c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                }
24033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2404b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
24055c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy
2406b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Filters the set of widgets which are on the specified screen. */
24079b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung        private void filterCurrentAppWidgets(long currentScreenId,
2408b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> appWidgets,
2409b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,
2410b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {
2411b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2412b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (LauncherAppWidgetInfo widget : appWidgets) {
24132abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                if (widget == null) continue;
2414b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
24159b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                        widget.screenId == currentScreenId) {
2416b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentScreenWidgets.add(widget);
2417b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2418b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherScreenWidgets.add(widget);
2419a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato                }
24209c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
24213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
242231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2423b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to
2424b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * right) */
2425b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
2426892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            final LauncherAppState app = LauncherAppState.getInstance();
24272e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            final InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
2428882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung            final int screenCols = profile.numColumns;
2429882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung            final int screenCellCount = profile.numColumns * profile.numRows;
2430b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
2431db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                @Override
2432db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                public int compare(ItemInfo lhs, ItemInfo rhs) {
2433882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                    if (lhs.container == rhs.container) {
2434882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                        // Within containers, order by their spatial position in that container
2435882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                        switch ((int) lhs.container) {
2436882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                            case LauncherSettings.Favorites.CONTAINER_DESKTOP: {
2437882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                long lr = (lhs.screenId * screenCellCount +
2438882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                        lhs.cellY * screenCols + lhs.cellX);
2439882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                long rr = (rhs.screenId * screenCellCount +
2440882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                        rhs.cellY * screenCols + rhs.cellX);
2441722e85678aa4aabd5e92f492544dbb3015fbd352Winson                                return Utilities.longCompare(lr, rr);
2442882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                            }
2443882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                            case LauncherSettings.Favorites.CONTAINER_HOTSEAT: {
2444882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                // We currently use the screen id as the rank
2445722e85678aa4aabd5e92f492544dbb3015fbd352Winson                                return Utilities.longCompare(lhs.screenId, rhs.screenId);
2446882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                            }
2447882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                            default:
24486c56c68555dcb3d99b05d5faecd582a1f683cc92Sunny Goyal                                if (ProviderConfig.IS_DOGFOOD_BUILD) {
2449882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                    throw new RuntimeException("Unexpected container type when " +
2450882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                            "sorting workspace items.");
2451882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                }
2452882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                                return 0;
2453882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                        }
2454882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                    } else {
2455882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                        // Between containers, order by hotseat, desktop
2456722e85678aa4aabd5e92f492544dbb3015fbd352Winson                        return Utilities.longCompare(lhs.container, rhs.container);
2457882a52eacf9e3bba09aa693f4982c2b8c41d25bbWinson Chung                    }
2458db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                }
2459db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung            });
2460b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
2461db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung
2462dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        private void bindWorkspaceScreens(final Callbacks oldCallbacks,
2463dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                final ArrayList<Long> orderedScreens) {
2464dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final Runnable r = new Runnable() {
2465dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                @Override
2466dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                public void run() {
2467dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2468dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    if (callbacks != null) {
2469dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        callbacks.bindScreens(orderedScreens);
2470dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
2471dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
2472dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            };
2473d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            runOnMainThread(r);
2474dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        }
2475dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2476b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        private void bindWorkspaceItems(final Callbacks oldCallbacks,
2477b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final ArrayList<ItemInfo> workspaceItems,
2478b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final ArrayList<LauncherAppWidgetInfo> appWidgets,
2479527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                final Executor executor) {
2480603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung
2481b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Bind the workspace items
2482db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung            int N = workspaceItems.size();
2483b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (int i = 0; i < N; i += ITEMS_CHUNK) {
24843611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final int start = i;
24853611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
2486b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final Runnable r = new Runnable() {
2487b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    @Override
24889c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    public void run() {
2489c131b74922e6323331c374856bda830010d761c8Joe Onorato                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
24909c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        if (callbacks != null) {
249164359a53dc827797917a8d9a0697a91996789801Winson Chung                            callbacks.bindItems(workspaceItems, start, start+chunkSize,
249264359a53dc827797917a8d9a0697a91996789801Winson Chung                                    false);
24939c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
24949c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
2495b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                };
2496527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                executor.execute(r);
2497b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2498b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2499b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Bind the widgets, one at a time
2500b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            N = appWidgets.size();
2501b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (int i = 0; i < N; i++) {
2502b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final LauncherAppWidgetInfo widget = appWidgets.get(i);
2503b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final Runnable r = new Runnable() {
2504b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    public void run() {
2505b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2506b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        if (callbacks != null) {
2507b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            callbacks.bindAppWidget(widget);
25083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
2509b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2510b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                };
2511527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                executor.execute(r);
25123611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2513b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
2514b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2515b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /**
2516b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * Binds all loaded data to actual views on the main thread.
2517b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         */
251866cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void bindWorkspace(int synchronizeBindPage) {
2519b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            final long t = SystemClock.uptimeMillis();
2520b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Runnable r;
2521b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2522b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Don't use these two variables in any of the callback runnables.
2523b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Otherwise we hold a reference to them.
2524b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            final Callbacks oldCallbacks = mCallbacks.get();
2525b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            if (oldCallbacks == null) {
2526b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // This launcher has exited and nobody bothered to tell us.  Just bail.
2527b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                Log.w(TAG, "LoaderTask running with no launcher");
2528b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                return;
2529b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2530b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
25319b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // Save a copy of all the bg-thread collections
253244c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<ItemInfo> workspaceItems = new ArrayList<>();
253344c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<>();
253444c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<Long> orderedScreenIds = new ArrayList<>();
2535e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal
25362abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            synchronized (sBgLock) {
2537b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                workspaceItems.addAll(sBgWorkspaceItems);
2538b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                appWidgets.addAll(sBgAppWidgets);
2539dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                orderedScreenIds.addAll(sBgWorkspaceScreens);
2540b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2541b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2542b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            final int currentScreen;
2543b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            {
2544b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                int currScreen = synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE
2545b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                        ? synchronizeBindPage : oldCallbacks.getCurrentWorkspaceScreen();
2546b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                if (currScreen >= orderedScreenIds.size()) {
2547b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    // There may be no workspace screens (just hotseat items and an empty page).
2548b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    currScreen = PagedView.INVALID_RESTORE_PAGE;
2549b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                }
2550b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                currentScreen = currScreen;
25519b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            }
2552b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            final boolean validFirstPage = currentScreen >= 0;
2553b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            final long currentScreenId =
2554b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    validFirstPage ? orderedScreenIds.get(currentScreen) : INVALID_SCREEN_ID;
25559b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung
25569b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // Separate the items that are on the current screen, and all the other remaining items
255744c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
255844c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
255944c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>();
256044c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>();
2561b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
25629b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
2563b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherWorkspaceItems);
25649b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
2565b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherAppWidgets);
2566b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sortWorkspaceItemsSpatially(currentWorkspaceItems);
2567b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sortWorkspaceItemsSpatially(otherWorkspaceItems);
2568b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2569b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Tell the workspace that we're about to start binding items
2570b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r = new Runnable() {
25713611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
25723611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
25733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (callbacks != null) {
2574527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                        callbacks.clearPendingBinds();
2575b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        callbacks.startBinding();
25769c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
25779c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
2578b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            };
2579d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            runOnMainThread(r);
2580b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2581dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
2582dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2583527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            Executor mainExecutor = new DeferredMainThreadExecutor();
2584527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            // Load items on the current page.
258544c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets, mainExecutor);
2586b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2587b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            // In case of validFirstPage, only bind the first screen, and defer binding the
2588b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            // remaining screens after first onDraw (and an optional the fade animation whichever
2589b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            // happens later).
2590b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            // This ensures that the first screen is immediately visible (eg. during rotation)
2591b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            // In case of !validFirstPage, bind all pages one after other.
2592b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            final Executor deferredExecutor =
2593b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    validFirstPage ? new ViewOnDrawExecutor(mHandler) : mainExecutor;
2594b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal
2595b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            mainExecutor.execute(new Runnable() {
2596b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                @Override
2597b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                public void run() {
2598b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2599b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    if (callbacks != null) {
2600b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                        callbacks.finishFirstPageBind(
2601b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                                validFirstPage ? (ViewOnDrawExecutor) deferredExecutor : null);
2602b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                    }
2603b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal                }
2604b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            });
2605527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
260644c06437e2e0476e24b61891d1a4aca9828f5327Sunny Goyal            bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, deferredExecutor);
2607b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2608b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Tell the workspace that we're done binding items
2609b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r = new Runnable() {
26103611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
2611b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2612b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    if (callbacks != null) {
261366cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        callbacks.finishBindingItems();
2614b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2615b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2616639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    mIsLoadingAndBindingWorkspace = false;
2617639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
2618639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    // Run all the bind complete runnables after workspace is bound.
2619639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    if (!mBindCompleteRunnables.isEmpty()) {
2620639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        synchronized (mBindCompleteRunnables) {
2621639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            for (final Runnable r : mBindCompleteRunnables) {
2622639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                runOnWorkerThread(r);
2623639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            }
2624639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            mBindCompleteRunnables.clear();
2625639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        }
2626639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    }
2627639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
262898e030be2abc03e90e9fd9f8bf67e2e01db39cc0Winson Chung                    // If we're profiling, ensure this is the last thing in the queue.
26293611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (DEBUG_LOADERS) {
26303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        Log.d(TAG, "bound workspace in "
26313611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            + (SystemClock.uptimeMillis()-t) + "ms");
26329c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
263336a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung
26349c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
2635b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            };
2636527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            deferredExecutor.execute(r);
2637527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
2638b5b9ad68b707154fcc2c3b04b1b6c0b17127e415Sunny Goyal            if (validFirstPage) {
2639527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                r = new Runnable() {
2640527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                    public void run() {
2641527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2642527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                        if (callbacks != null) {
2643527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            // We are loading synchronously, which means, some of the pages will be
2644527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            // bound after first draw. Inform the callbacks that page binding is
2645527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            // not complete, and schedule the remaining pages.
2646527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            if (currentScreen != PagedView.INVALID_RESTORE_PAGE) {
2647527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                                callbacks.onPageBoundSynchronously(currentScreen);
2648527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            }
2649527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                            callbacks.executeOnNextDraw((ViewOnDrawExecutor) deferredExecutor);
2650527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                        }
2651527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                    }
2652527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal                };
2653d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                runOnMainThread(r);
26544a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            }
26553611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
26563611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
26573611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void loadAndBindAllApps() {
26583611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
26593611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
26603611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
26613611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (!mAllAppsLoaded) {
266264359a53dc827797917a8d9a0697a91996789801Winson Chung                loadAllApps();
2663f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                synchronized (LoaderTask.this) {
2664f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    if (mStopped) {
2665f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                        return;
2666f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    }
2667f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                }
26684e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                updateIconCache();
266993f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                synchronized (LoaderTask.this) {
267093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    if (mStopped) {
267193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                        return;
267293f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    }
267393f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    mAllAppsLoaded = true;
26743611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
26753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            } else {
26763611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                onlyBindAllApps();
26773611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
26783611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
26793611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
26804e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        private void updateIconCache() {
26814e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            // Ignore packages which have a promise icon.
26824e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            HashSet<String> packagesToIgnore = new HashSet<>();
26834e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            synchronized (sBgLock) {
26844e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                for (ItemInfo info : sBgItemsIdMap) {
26854e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    if (info instanceof ShortcutInfo) {
26864e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        ShortcutInfo si = (ShortcutInfo) info;
26874e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        if (si.isPromise() && si.getTargetComponent() != null) {
26884e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            packagesToIgnore.add(si.getTargetComponent().getPackageName());
26894e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        }
26904e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    } else if (info instanceof LauncherAppWidgetInfo) {
26914e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;
26924e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
26934e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            packagesToIgnore.add(lawi.providerName.getPackageName());
26944e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        }
26954e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    }
26964e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                }
26974e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            }
26984e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            mIconCache.updateDbIcons(packagesToIgnore);
26994e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        }
27004e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal
27013611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void onlyBindAllApps() {
27023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Callbacks oldCallbacks = mCallbacks.get();
27033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (oldCallbacks == null) {
27043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // This launcher has exited and nobody bothered to tell us.  Just bail.
27053611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");
27063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return;
27073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
27083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // shallow copy
2710c208ff9c5ded4953ded6a3358097c9f7280df825Winson Chung            @SuppressWarnings("unchecked")
2711eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> list
2712eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                    = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
2713c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            Runnable r = new Runnable() {
27143611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
27153611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    final long t = SystemClock.uptimeMillis();
27163611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
27173611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (callbacks != null) {
27183611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        callbacks.bindAllApplications(list);
27199c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
27203611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (DEBUG_LOADERS) {
27213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        Log.d(TAG, "bound all " + list.size() + " apps from cache in "
2722747a5bc486a7c8335fc4a481cab1567369570c24Hyunyoung Song                                + (SystemClock.uptimeMillis() - t) + "ms");
27239c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
27243611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
2725c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            };
272680f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham            runOnMainThread(r);
27273611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
27283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
272964359a53dc827797917a8d9a0697a91996789801Winson Chung        private void loadAllApps() {
273064359a53dc827797917a8d9a0697a91996789801Winson Chung            final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
27313611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Callbacks oldCallbacks = mCallbacks.get();
27333611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (oldCallbacks == null) {
27343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // This launcher has exited and nobody bothered to tell us.  Just bail.
273564359a53dc827797917a8d9a0697a91996789801Winson Chung                Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");
27363611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return;
27379c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
273831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2739ed13187a745866483139e2878037e1f8427ce567Kenny Guy            final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();
2740ed13187a745866483139e2878037e1f8427ce567Kenny Guy
274164359a53dc827797917a8d9a0697a91996789801Winson Chung            // Clear the list of apps
274264359a53dc827797917a8d9a0697a91996789801Winson Chung            mBgAllAppsList.clear();
2743ed13187a745866483139e2878037e1f8427ce567Kenny Guy            for (UserHandleCompat user : profiles) {
2744ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Query for the set of apps
2745ed13187a745866483139e2878037e1f8427ce567Kenny Guy                final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
2746756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
2747ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (DEBUG_LOADERS) {
2748ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    Log.d(TAG, "getActivityList took "
2749ed13187a745866483139e2878037e1f8427ce567Kenny Guy                            + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);
2750ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);
2751ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
2752ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Fail if we don't have any apps
2753e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                // TODO: Fix this. Only fail for the current user.
2754ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (apps == null || apps.isEmpty()) {
2755ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return;
2756ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
2757ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                boolean quietMode = mUserManager.isQuietModeEnabled(user);
2758ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Create the ApplicationInfos
2759ed13187a745866483139e2878037e1f8427ce567Kenny Guy                for (int i = 0; i < apps.size(); i++) {
2760ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    LauncherActivityInfoCompat app = apps.get(i);
2761ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    // This builds the icon bitmaps.
2762ff05f4375dd47242d7e4864287e0d5af8ac8ba8fKenny Guy                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache, quietMode));
2763ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
2764e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
2765756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                final ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
2766756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                if (heuristic != null) {
2767639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    final Runnable r = new Runnable() {
2768756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
2769756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        @Override
2770756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        public void run() {
2771756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                            heuristic.processUserApps(apps);
2772756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        }
2773639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    };
2774639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    runOnMainThread(new Runnable() {
2775639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
2776639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        @Override
2777639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        public void run() {
2778639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            // Check isLoadingWorkspace on the UI thread, as it is updated on
2779639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            // the UI thread.
2780639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            if (mIsLoadingAndBindingWorkspace) {
2781639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                synchronized (mBindCompleteRunnables) {
2782639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                    mBindCompleteRunnables.add(r);
2783639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                }
2784639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            } else {
2785639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                runOnWorkerThread(r);
2786639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            }
2787639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        }
2788756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                    });
2789e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                }
279064359a53dc827797917a8d9a0697a91996789801Winson Chung            }
279185f418d0f5607c66efef1673075a6d3486e5af83Bjorn Bringert            // Huh? Shouldn't this be inside the Runnable below?
2792eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> added = mBgAllAppsList.added;
2793eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            mBgAllAppsList.added = new ArrayList<AppInfo>();
27943611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
279564359a53dc827797917a8d9a0697a91996789801Winson Chung            // Post callback on main thread
279664359a53dc827797917a8d9a0697a91996789801Winson Chung            mHandler.post(new Runnable() {
279764359a53dc827797917a8d9a0697a91996789801Winson Chung                public void run() {
27989892e5874061233dec57107d1d3d7d5d8e1f5d93Hyunyoung Song
279964359a53dc827797917a8d9a0697a91996789801Winson Chung                    final long bindTime = SystemClock.uptimeMillis();
280011a1a53651924b544513f1f6971a735b18d67539Winson Chung                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
280164359a53dc827797917a8d9a0697a91996789801Winson Chung                    if (callbacks != null) {
280264359a53dc827797917a8d9a0697a91996789801Winson Chung                        callbacks.bindAllApplications(added);
28033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) {
280464359a53dc827797917a8d9a0697a91996789801Winson Chung                            Log.d(TAG, "bound " + added.size() + " apps in "
28052e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                                    + (SystemClock.uptimeMillis() - bindTime) + "ms");
28063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
280764359a53dc827797917a8d9a0697a91996789801Winson Chung                    } else {
280864359a53dc827797917a8d9a0697a91996789801Winson Chung                        Log.i(TAG, "not binding apps: no Launcher activity");
280964359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
28103611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
281164359a53dc827797917a8d9a0697a91996789801Winson Chung            });
281218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            // Cleanup any data stored for a deleted user.
281318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            ManagedProfileHeuristic.processAllUsers(profiles, mContext);
28143611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
281564359a53dc827797917a8d9a0697a91996789801Winson Chung                Log.d(TAG, "Icons processed in "
281664359a53dc827797917a8d9a0697a91996789801Winson Chung                        + (SystemClock.uptimeMillis() - loadTime) + "ms");
28173611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
28183611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
2819dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
2820bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        private void loadAndBindDeepShortcuts() {
2821bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            if (DEBUG_LOADERS) {
2822bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                Log.d(TAG, "loadAndBindDeepShortcuts mDeepShortcutsLoaded=" + mDeepShortcutsLoaded);
2823bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
2824bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            if (!mDeepShortcutsLoaded) {
2825bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                mBgDeepShortcutMap.clear();
282695f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                mHasShortcutHostPermission = mDeepShortcutManager.hasHostPermission();
282795f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                if (mHasShortcutHostPermission) {
282895f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                    for (UserHandleCompat user : mUserManager.getUserProfiles()) {
282995f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                        if (mUserManager.isUserUnlocked(user)) {
283095f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                            List<ShortcutInfoCompat> shortcuts = mDeepShortcutManager
283195f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                                    .queryForAllShortcuts(user);
283295f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                            updateDeepShortcutMap(null, user, shortcuts);
283395f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal                        }
2834d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    }
2835bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
2836bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                synchronized (LoaderTask.this) {
2837bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    if (mStopped) {
2838bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        return;
2839bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    }
2840bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    mDeepShortcutsLoaded = true;
2841bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
2842bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
284380f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham            bindDeepShortcuts();
2844bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
2845bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
284675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        public void dumpState() {
284775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            synchronized (sBgLock) {
284875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mContext=" + mContext);
284975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
285075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
285175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());
285275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            }
285375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
285475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    }
285577919b93b98f5afa1b39546861197d6065847224Sunny Goyal
2856860538df1d72b3840811b7a39940a224f3326066Sunny Goyal    /**
2857860538df1d72b3840811b7a39940a224f3326066Sunny Goyal     * Clear all the shortcuts for the given package, and re-add the new shortcuts.
2858860538df1d72b3840811b7a39940a224f3326066Sunny Goyal     */
2859860538df1d72b3840811b7a39940a224f3326066Sunny Goyal    private void updateDeepShortcutMap(
2860860538df1d72b3840811b7a39940a224f3326066Sunny Goyal            String packageName, UserHandleCompat user, List<ShortcutInfoCompat> shortcuts) {
2861bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        if (packageName != null) {
2862bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            Iterator<ComponentKey> keysIter = mBgDeepShortcutMap.keySet().iterator();
2863bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            while (keysIter.hasNext()) {
2864860538df1d72b3840811b7a39940a224f3326066Sunny Goyal                ComponentKey next = keysIter.next();
2865860538df1d72b3840811b7a39940a224f3326066Sunny Goyal                if (next.componentName.getPackageName().equals(packageName)
2866860538df1d72b3840811b7a39940a224f3326066Sunny Goyal                        && next.user.equals(user)) {
2867bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    keysIter.remove();
2868bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
2869bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
2870bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
2871bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
2872bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        // Now add the new shortcuts to the map.
2873bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        for (ShortcutInfoCompat shortcut : shortcuts) {
2874ca258b36be07f4835c9cc5fbc3e84e9851647dceTony Wickham            boolean shouldShowInContainer = shortcut.isEnabled()
2875ca258b36be07f4835c9cc5fbc3e84e9851647dceTony Wickham                    && (shortcut.isDeclaredInManifest() || shortcut.isDynamic());
2876ca258b36be07f4835c9cc5fbc3e84e9851647dceTony Wickham            if (shouldShowInContainer) {
287770a7c9b70003ae87e2b2968bc6ceded0fe0f0e8bSunny Goyal                ComponentKey targetComponent
287870a7c9b70003ae87e2b2968bc6ceded0fe0f0e8bSunny Goyal                        = new ComponentKey(shortcut.getActivity(), shortcut.getUserHandle());
287970a7c9b70003ae87e2b2968bc6ceded0fe0f0e8bSunny Goyal                mBgDeepShortcutMap.addToList(targetComponent, shortcut.getId());
288070a7c9b70003ae87e2b2968bc6ceded0fe0f0e8bSunny Goyal            }
2881bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
2882bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
2883bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
288480f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham    public void bindDeepShortcuts() {
28855f06401807ef408a4b56a127bef1f0b55b0adcf6Sunny Goyal        final MultiHashMap<ComponentKey, String> shortcutMapCopy = mBgDeepShortcutMap.clone();
288680f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham        Runnable r = new Runnable() {
2887bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            @Override
2888bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            public void run() {
2889bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                Callbacks callbacks = getCallback();
2890bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                if (callbacks != null) {
2891bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    callbacks.bindDeepShortcutMap(shortcutMapCopy);
2892bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
2893bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
289480f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham        };
289580f5787b1c12be2a5ce3d11e01ff9435bae71bdfTony Wickham        runOnMainThread(r);
2896bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
2897bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
289875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    /**
289995f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal     * Refreshes the cached shortcuts if the shortcut permission has changed.
290095f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal     * Current implementation simply reloads the workspace, but it can be optimized to
290195f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal     * use partial updates similar to {@link UserManagerCompat}
290295f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal     */
290395f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    public void refreshShortcutsIfRequired() {
290495f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal        if (Utilities.isNycMR1OrAbove()) {
290595f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal            sWorker.removeCallbacks(mShortcutPermissionCheckRunnable);
290695f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal            sWorker.post(mShortcutPermissionCheckRunnable);
290795f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal        }
290895f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    }
290995f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal
291095f3d6ba2ca02a9841487777cfff43fb9df65ec7Sunny Goyal    /**
291175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     * Called when the icons for packages have been updated in the icon cache.
291275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     */
291375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    public void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandleCompat user) {
291475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final Callbacks callbacks = getCallback();
291575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final ArrayList<AppInfo> updatedApps = new ArrayList<>();
291675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<>();
291777919b93b98f5afa1b39546861197d6065847224Sunny Goyal
291875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        // If any package icon has changed (app was updated while launcher was dead),
291975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        // update the corresponding shortcuts.
292075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        synchronized (sBgLock) {
292175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            for (ItemInfo info : sBgItemsIdMap) {
292275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                if (info instanceof ShortcutInfo && user.equals(info.user)
292375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
292475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    ShortcutInfo si = (ShortcutInfo) info;
292575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    ComponentName cn = si.getTargetComponent();
292675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cn != null && updatedPackages.contains(cn.getPackageName())) {
292775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        si.updateIcon(mIconCache);
292875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        updatedShortcuts.add(si);
292977919b93b98f5afa1b39546861197d6065847224Sunny Goyal                    }
293077919b93b98f5afa1b39546861197d6065847224Sunny Goyal                }
293177919b93b98f5afa1b39546861197d6065847224Sunny Goyal            }
293275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mBgAllAppsList.updateIconsAndLabels(updatedPackages, user, updatedApps);
293375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
293477919b93b98f5afa1b39546861197d6065847224Sunny Goyal
2935bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        bindUpdatedShortcuts(updatedShortcuts, user);
2936bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
2937bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        if (!updatedApps.isEmpty()) {
293875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mHandler.post(new Runnable() {
293975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
294075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                public void run() {
294175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    Callbacks cb = getCallback();
294275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cb != null && callbacks == cb) {
2943bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        cb.bindAppsUpdated(updatedApps);
294477919b93b98f5afa1b39546861197d6065847224Sunny Goyal                    }
294575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
294675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            });
294777919b93b98f5afa1b39546861197d6065847224Sunny Goyal        }
2948bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
294977919b93b98f5afa1b39546861197d6065847224Sunny Goyal
2950d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    private void bindUpdatedShortcuts(
2951d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            ArrayList<ShortcutInfo> updatedShortcuts, UserHandleCompat user) {
2952d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        bindUpdatedShortcuts(updatedShortcuts, new ArrayList<ShortcutInfo>(), user);
2953d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    }
2954d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
2955d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    private void bindUpdatedShortcuts(
2956d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            final ArrayList<ShortcutInfo> updatedShortcuts,
2957d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            final ArrayList<ShortcutInfo> removedShortcuts,
2958d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            final UserHandleCompat user) {
2959d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
2960bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            final Callbacks callbacks = getCallback();
296175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mHandler.post(new Runnable() {
296275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
296375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                public void run() {
296475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    Callbacks cb = getCallback();
296575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cb != null && callbacks == cb) {
2966d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        cb.bindShortcutsChanged(updatedShortcuts, removedShortcuts, user);
296775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    }
296875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
296975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            });
29703611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
29713611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
297231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2973bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    void enqueueItemUpdatedTask(Runnable task) {
2974700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick        sWorker.post(task);
29753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
2976d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
2977091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk class AppsAvailabilityCheck extends BroadcastReceiver {
2978f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
2979f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        @Override
2980f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        public void onReceive(Context context, Intent intent) {
2981f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            synchronized (sBgLock) {
2982f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                final LauncherAppsCompat launcherApps = LauncherAppsCompat
2983f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        .getInstance(mApp.getContext());
29841a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final PackageManager manager = context.getPackageManager();
29851a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final ArrayList<String> packagesRemoved = new ArrayList<String>();
29861a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final ArrayList<String> packagesUnavailable = new ArrayList<String>();
2987f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {
2988f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    UserHandleCompat user = entry.getKey();
29891a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    packagesRemoved.clear();
29901a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    packagesUnavailable.clear();
2991f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    for (String pkg : entry.getValue()) {
2992f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
2993d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal                            if (PackageManagerHelper.isAppOnSdcard(manager, pkg)) {
29941a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesUnavailable.add(pkg);
29951a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            } else {
29961a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesRemoved.add(pkg);
29971a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            }
2998f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        }
2999f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    }
3000f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    if (!packagesRemoved.isEmpty()) {
3001bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        enqueueItemUpdatedTask(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,
3002f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
3003f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    }
30041a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    if (!packagesUnavailable.isEmpty()) {
3005bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                        enqueueItemUpdatedTask(new PackageUpdatedTask(PackageUpdatedTask.OP_UNAVAILABLE,
30061a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesUnavailable.toArray(new String[packagesUnavailable.size()]), user));
30071a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    }
3008f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                }
3009349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                sPendingPackages.clear();
3010f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            }
3011f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        }
3012f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal    }
3013f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
30143611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private class PackageUpdatedTask implements Runnable {
30153611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        int mOp;
30163611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        String[] mPackages;
3017ed13187a745866483139e2878037e1f8427ce567Kenny Guy        UserHandleCompat mUser;
3018d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
30193611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_NONE = 0;
30203611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_ADD = 1;
30213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_UPDATE = 2;
30223611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_REMOVE = 3; // uninstlled
30233611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_UNAVAILABLE = 4; // external media unmounted
302444cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy        public static final int OP_SUSPEND = 5; // package suspended
302544cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy        public static final int OP_UNSUSPEND = 6; // package unsuspended
3026da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal        public static final int OP_USER_AVAILABILITY_CHANGE = 7; // user available/unavailable
3027d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
3028ed13187a745866483139e2878037e1f8427ce567Kenny Guy        public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
30293611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mOp = op;
30303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mPackages = packages;
3031ed13187a745866483139e2878037e1f8427ce567Kenny Guy            mUser = user;
30323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
3033d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
30343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void run() {
3035c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal            if (!mHasLoaderCompletedOnce) {
3036c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal                // Loader has not yet run.
3037c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal                return;
3038c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal            }
3039cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            final Context context = mApp.getContext();
3040dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
30413611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final String[] packages = mPackages;
30423611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final int N = packages.length;
30433bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            FlagOp flagOp = FlagOp.NO_OP;
3044da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal            StringFilter pkgFilter = StringFilter.of(new HashSet<>(Arrays.asList(packages)));
30453611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            switch (mOp) {
304618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                case OP_ADD: {
30473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
30494fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.updateIconsForPkg(packages[i], mUser);
3050ed13187a745866483139e2878037e1f8427ce567Kenny Guy                        mBgAllAppsList.addPackage(context, packages[i], mUser);
3051dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler                    }
3052e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
305318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
305418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    if (heuristic != null) {
305518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        heuristic.processPackageAdd(mPackages);
3056e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    }
30573611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
305818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                }
30593611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                case OP_UPDATE:
30603611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30613611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
30624fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.updateIconsForPkg(packages[i], mUser);
3063ed13187a745866483139e2878037e1f8427ce567Kenny Guy                        mBgAllAppsList.updatePackage(context, packages[i], mUser);
30645b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal                        mApp.getWidgetCache().removePackage(packages[i], mUser);
30653611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
30663bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    // Since package was just updated, the target must be available now.
30673bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
30683611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
306918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                case OP_REMOVE: {
307018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
307118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    if (heuristic != null) {
307218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        heuristic.processPackageRemoved(mPackages);
3073e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    }
30744fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    for (int i=0; i<N; i++) {
30754fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
30764fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.removeIconsForPkg(packages[i], mUser);
30774fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    }
3078e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    // Fall through
307918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                }
30803611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                case OP_UNAVAILABLE:
30813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
30834fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mBgAllAppsList.removePackage(packages[i], mUser);
30845b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal                        mApp.getWidgetCache().removePackage(packages[i], mUser);
30853611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
30863bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    flagOp = FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
30873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
308844cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                case OP_SUSPEND:
308944cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                case OP_UNSUSPEND:
30903bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    flagOp = mOp == OP_SUSPEND ?
30913bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                            FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED) :
30923bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                                    FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED);
309317763cb1d2060fb95873a8920196720c862f0e14Sunny Goyal                    if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.(un)suspend " + N);
3094da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    mBgAllAppsList.updatePackageFlags(pkgFilter, mUser, flagOp);
3095da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    break;
3096da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                case OP_USER_AVAILABILITY_CHANGE:
3097da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    flagOp = UserManagerCompat.getInstance(context).isQuietModeEnabled(mUser)
3098da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                            ? FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_QUIET_USER)
3099da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                            : FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_QUIET_USER);
3100da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    // We want to update all packages for this user.
3101da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    pkgFilter = StringFilter.matchesAll();
3102da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                    mBgAllAppsList.updatePackageFlags(pkgFilter, mUser, flagOp);
310344cba696386b44f9115cad13ec9ecf67a0ac9119Kenny Guy                    break;
31043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3105dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
3106eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            ArrayList<AppInfo> added = null;
3107eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            ArrayList<AppInfo> modified = null;
3108eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();
31093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
3110487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen            if (mBgAllAppsList.added.size() > 0) {
31113bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                added = new ArrayList<>(mBgAllAppsList.added);
31125d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.added.clear();
31133611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3114487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen            if (mBgAllAppsList.modified.size() > 0) {
31153bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                modified = new ArrayList<>(mBgAllAppsList.modified);
31165d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.modified.clear();
31173611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
31185d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung            if (mBgAllAppsList.removed.size() > 0) {
311983892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                removedApps.addAll(mBgAllAppsList.removed);
31205d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.removed.clear();
3121cd81073eac537e9f85eeee14588d513ea8a56e17Winson Chung            }
3122cd81073eac537e9f85eeee14588d513ea8a56e17Winson Chung
31233bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps = new HashMap<>();
31244390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (added != null) {
3126c9acdd51c40c1b397adae6ba62c4acd01914b473Sunny Goyal                addAppsToAllApps(context, added);
31274390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                for (AppInfo ai : added) {
31284390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    addedOrUpdatedApps.put(ai.componentName, ai);
31294390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                }
31303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
313176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
31323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (modified != null) {
31333bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                final Callbacks callbacks = getCallback();
3134eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                final ArrayList<AppInfo> modifiedFinal = modified;
31354390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                for (AppInfo ai : modified) {
31364390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    addedOrUpdatedApps.put(ai.componentName, ai);
313764359a53dc827797917a8d9a0697a91996789801Winson Chung                }
313864359a53dc827797917a8d9a0697a91996789801Winson Chung
31393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.post(new Runnable() {
31403611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    public void run() {
3141e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
3142cd2b01416febb5bf50ed5ede1544dea33fee3b0bWinson Chung                        if (callbacks == cb && cb != null) {
31433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            callbacks.bindAppsUpdated(modifiedFinal);
31443611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
31453611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
31463611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                });
31473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3148780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung
31494390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal            // Update shortcut infos
31503bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
31514390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
31524390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
31534390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
31544390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
3155b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                synchronized (sBgLock) {
3156e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                    for (ItemInfo info : sBgItemsIdMap) {
3157b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
3158b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            ShortcutInfo si = (ShortcutInfo) info;
31594390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            boolean infoUpdated = false;
31604390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            boolean shortcutUpdated = false;
31614390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31624390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            // Update shortcuts which use iconResource.
3163b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            if ((si.iconResource != null)
3164da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                                    && pkgFilter.matches(si.iconResource.packageName)) {
316553d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                Bitmap icon = Utilities.createIconBitmap(
316653d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                        si.iconResource.packageName,
316753d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                        si.iconResource.resourceName, context);
3168b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                if (icon != null) {
3169b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                    si.setIcon(icon);
3170b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                    si.usingFallbackIcon = false;
31714390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
3172b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                }
3173b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            }
31744390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31754390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            ComponentName cn = si.getTargetComponent();
3176da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                            if (cn != null && pkgFilter.matches(cn.getPackageName())) {
31774390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                AppInfo appInfo = addedOrUpdatedApps.get(cn);
31784390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31794390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                if (si.isPromise()) {
31804390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
31814390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        // Auto install icon
31824390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        PackageManager pm = context.getPackageManager();
31834390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        ResolveInfo matched = pm.resolveActivity(
31844390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                new Intent(Intent.ACTION_MAIN)
31854390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
31864390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                PackageManager.MATCH_DEFAULT_ONLY);
31874390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        if (matched == null) {
31884390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            // Try to find the best match activity.
31894390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            Intent intent = pm.getLaunchIntentForPackage(
31904390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                    cn.getPackageName());
31914390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            if (intent != null) {
31924390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                cn = intent.getComponent();
31934390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                appInfo = addedOrUpdatedApps.get(cn);
31944390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            }
31954390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31964390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            if ((intent == null) || (appInfo == null)) {
31974390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                removedShortcuts.add(si);
31984390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                continue;
31994390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            }
32004390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            si.promisedIntent = intent;
32014390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        }
32024390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    }
32034390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
32044390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    // Restore the shortcut.
3205fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                    if (appInfo != null) {
3206fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                        si.flags = appInfo.flags;
3207fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                    }
32084390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
3209756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.intent = si.promisedIntent;
3210756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.promisedIntent = null;
3211756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.status = ShortcutInfo.DEFAULT;
32124390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
32134390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.updateIcon(mIconCache);
32144390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
32154390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
32164390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
32174390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
32184390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.updateIcon(mIconCache);
321982b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                                    si.title = Utilities.trim(appInfo.title);
32204390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.contentDescription = appInfo.contentDescription;
32214390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
32224390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
32234390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
32243bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                                int oldDisabledFlags = si.isDisabled;
32253bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                                si.isDisabled = flagOp.apply(si.isDisabled);
32263bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                                if (si.isDisabled != oldDisabledFlags) {
32274390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    shortcutUpdated = true;
32284390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
32294390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
32304390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
32314390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (infoUpdated || shortcutUpdated) {
32324390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updatedShortcuts.add(si);
32334390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
32344390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (infoUpdated) {
32354390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updateItemInDatabase(context, si);
32364390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
3237da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                        } else if (info instanceof LauncherAppWidgetInfo && mOp == OP_ADD) {
32384390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
32394390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (mUser.equals(widgetInfo.user)
32404390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
3241da891c1a22210e7e75f85796dea528bf8bf12b45Sunny Goyal                                    && pkgFilter.matches(widgetInfo.providerName.getPackageName())) {
324253f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                widgetInfo.restoreStatus &=
324353f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY &
324453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
324584b4adc3fb2301466468828ccbd742209619e597Sunny Goyal
324684b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // adding this flag ensures that launcher shows 'click to setup'
324784b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // if the widget has a config activity. In case there is no config
324884b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // activity, it will be marked as 'restored' during bind.
324984b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
325084b4adc3fb2301466468828ccbd742209619e597Sunny Goyal
32514390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                widgets.add(widgetInfo);
32524390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updateItemInDatabase(context, widgetInfo);
32534390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
3254b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        }
3255b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                    }
3256b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                }
3257b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal
3258d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                bindUpdatedShortcuts(updatedShortcuts, removedShortcuts, mUser);
3259d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                if (!removedShortcuts.isEmpty()) {
3260d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    deleteItemsFromDatabase(context, removedShortcuts);
32614390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                }
3262d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
32634390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                if (!widgets.isEmpty()) {
32643bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    final Callbacks callbacks = getCallback();
32654390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    mHandler.post(new Runnable() {
32664390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        public void run() {
3267e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Callbacks cb = getCallback();
32684390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (callbacks == cb && cb != null) {
32694390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                callbacks.bindWidgetsRestored(widgets);
3270b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            }
3271b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        }
3272b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                    });
3273b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                }
3274b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal            }
3275b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal
32763bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            final HashSet<String> removedPackages = new HashSet<>();
32773bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            final HashSet<ComponentName> removedComponents = new HashSet<>();
32783bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            if (mOp == OP_REMOVE) {
3279df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Mark all packages in the broadcast to be removed
32803bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                Collections.addAll(removedPackages, packages);
32813bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal
32823bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                // No need to update the removedComponents as
32833bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                // removedPackages is a super-set of removedComponents
3284df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            } else if (mOp == OP_UPDATE) {
3285df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Mark disabled packages in the broadcast to be removed
3286df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                for (int i=0; i<N; i++) {
3287ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    if (isPackageDisabled(context, packages[i], mUser)) {
32883bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                        removedPackages.add(packages[i]);
328964359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
329064359a53dc827797917a8d9a0697a91996789801Winson Chung                }
32913bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal
32923bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                // Update removedComponents as some components can get removed during package update
32933bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                for (AppInfo info : removedApps) {
32943bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    removedComponents.add(info.componentName);
32953bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                }
3296df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            }
32971a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
32983bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
32993bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                for (String pn : removedPackages) {
33003bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    deletePackageFromDatabase(context, pn, mUser);
33013bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                }
33023bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                for (ComponentName cn : removedComponents) {
33033bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    deleteItemsFromDatabase(context, getItemInfoForComponentName(cn, mUser));
33041a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                }
33051a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
3306df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Remove any queued items from the install queue
33073bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
33083bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal
3309df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Call the components-removed callback
33103bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                final Callbacks callbacks = getCallback();
33113bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                mHandler.post(new Runnable() {
33123bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    public void run() {
33133bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                        Callbacks cb = getCallback();
33143bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                        if (callbacks == cb && cb != null) {
33153bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                            callbacks.bindWorkspaceComponentsRemoved(
33163bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                                    removedPackages, removedComponents, mUser);
33173bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                        }
33183bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                    }
33193bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                });
33203bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            }
33213bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal
33223bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal            if (!removedApps.isEmpty()) {
33233bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                // Remove corresponding apps from All-Apps
33243bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                final Callbacks callbacks = getCallback();
33253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.post(new Runnable() {
33263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    public void run() {
3327e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
3328cd2b01416febb5bf50ed5ede1544dea33fee3b0bWinson Chung                        if (callbacks == cb && cb != null) {
33293bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                            callbacks.bindAppInfosRemoved(removedApps);
33303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
33313611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
33323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                });
3333be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato            }
3334227239e7c05d26c4098980b991d3472077c01ccbHyunyoung Song
33352e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            // Notify launcher of widget update. From marshmallow onwards we use AppWidgetHost to
33362e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            // get widget update signals.
33372e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            if (!Utilities.ATLEAST_MARSHMALLOW &&
33382e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                    (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) {
33393bbbabc54ac73a4451b0a862a3faac6426b1b7b4Sunny Goyal                final Callbacks callbacks = getCallback();
33402e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                mHandler.post(new Runnable() {
33412e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                    public void run() {
33422e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                        Callbacks cb = getCallback();
33432e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                        if (callbacks == cb && cb != null) {
33442e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                            callbacks.notifyWidgetProvidersChanged();
33453dc7beea3c7f9a60070e767aa43f5877a467d3edSunny Goyal                        }
33462d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    }
33472e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                });
33482d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal            }
334931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
335031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
335131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
335210923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal    /**
335310923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal     * Repopulates the shortcut info, possibly updating any icon already on the workspace.
335410923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal     */
335510923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal    public void updateShortcutInfo(final ShortcutInfoCompat fullDetail, final ShortcutInfo info) {
335610923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal        enqueueItemUpdatedTask(new Runnable() {
335710923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal            @Override
335810923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal            public void run() {
335910923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal                info.updateFromDeepShortcutInfo(
336010923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal                        fullDetail, LauncherAppState.getInstance().getContext());
336110923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal                ArrayList<ShortcutInfo> update = new ArrayList<ShortcutInfo>();
336210923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal                update.add(info);
336310923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal                bindUpdatedShortcuts(update, fullDetail.getUserHandle());
336410923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal            }
336510923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal        });
336610923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal    }
336710923b30a22b4ec8d10cf8536bddf3f176e6c26fSunny Goyal
3368bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private class ShortcutsChangedTask implements Runnable {
336950941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        private final String mPackageName;
337050941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        private final List<ShortcutInfoCompat> mShortcuts;
337150941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        private final UserHandleCompat mUser;
337250941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal        private final boolean mUpdateIdMap;
3373bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
3374bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        public ShortcutsChangedTask(String packageName, List<ShortcutInfoCompat> shortcuts,
337550941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal                UserHandleCompat user, boolean updateIdMap) {
3376bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            mPackageName = packageName;
3377bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            mShortcuts = shortcuts;
3378bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            mUser = user;
337950941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal            mUpdateIdMap = updateIdMap;
3380bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
3381bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
3382bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        @Override
3383bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        public void run() {
3384bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            mDeepShortcutManager.onShortcutsChanged(mShortcuts);
3385bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
3386bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            // Find ShortcutInfo's that have changed on the workspace.
33877695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            final ArrayList<ShortcutInfo> removedShortcutInfos = new ArrayList<>();
3388bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            MultiHashMap<String, ShortcutInfo> idsToWorkspaceShortcutInfos = new MultiHashMap<>();
3389bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            for (ItemInfo itemInfo : sBgItemsIdMap) {
3390bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
3391bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    ShortcutInfo si = (ShortcutInfo) itemInfo;
3392fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                    if (si.getPromisedIntent().getPackage().equals(mPackageName)
3393fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                            && si.user.equals(mUser)) {
33947695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        idsToWorkspaceShortcutInfos.addToList(si.getDeepShortcutId(), si);
3395bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                    }
3396bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
3397bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
3398bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
33997695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            final Context context = LauncherAppState.getInstance().getContext();
34007695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            final ArrayList<ShortcutInfo> updatedShortcutInfos = new ArrayList<>();
34017695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            if (!idsToWorkspaceShortcutInfos.isEmpty()) {
34027695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                // Update the workspace to reflect the changes to updated shortcuts residing on it.
34037695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                List<ShortcutInfoCompat> shortcuts = mDeepShortcutManager.queryForFullDetails(
34047695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        mPackageName, new ArrayList<>(idsToWorkspaceShortcutInfos.keySet()), mUser);
34057695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                for (ShortcutInfoCompat fullDetails : shortcuts) {
34067695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                    List<ShortcutInfo> shortcutInfos = idsToWorkspaceShortcutInfos
34077695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                            .remove(fullDetails.getId());
34087695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                    if (!fullDetails.isPinned()) {
34097695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        // The shortcut was previously pinned but is no longer, so remove it from
34107695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        // the workspace and our pinned shortcut counts.
34117695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        // Note that we put this check here, after querying for full details,
34127695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        // because there's a possible race condition between pinning and
34137695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        // receiving this callback.
34147695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        removedShortcutInfos.addAll(shortcutInfos);
34157695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        continue;
34167695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                    }
34177695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                    for (ShortcutInfo shortcutInfo : shortcutInfos) {
34187695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        shortcutInfo.updateFromDeepShortcutInfo(fullDetails, context);
34197695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                        updatedShortcutInfos.add(shortcutInfo);
34207695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                    }
3421bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham                }
3422bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham            }
34237695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham
34247695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            // If there are still entries in idsToWorkspaceShortcutInfos, that means that
34257695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            // the corresponding shortcuts weren't passed in onShortcutsChanged(). This
34267695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            // means they were cleared, so we remove and unpin them now.
34277695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            for (String id : idsToWorkspaceShortcutInfos.keySet()) {
34287695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                removedShortcutInfos.addAll(idsToWorkspaceShortcutInfos.get(id));
34297695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            }
34307695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham
34317695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            bindUpdatedShortcuts(updatedShortcutInfos, removedShortcutInfos, mUser);
34327695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            if (!removedShortcutInfos.isEmpty()) {
34337695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham                deleteItemsFromDatabase(context, removedShortcutInfos);
34347695e603bf1f4369115ba64c24e8b09c213b4e9cTony Wickham            }
3435bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
343650941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal            if (mUpdateIdMap) {
343750941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal                // Update the deep shortcut map if the list of ids has changed for an activity.
343850941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal                updateDeepShortcutMap(mPackageName, mUser, mShortcuts);
343950941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal                bindDeepShortcuts();
344050941fb8a6ba4e1b6fca6cbf35e1a5efca7156f3Sunny Goyal            }
3441bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        }
3442bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
3443bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
3444d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    /**
3445d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal     * Task to handle changing of lock state of the user
3446d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal     */
3447d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    private class UserLockStateChangedTask implements Runnable {
3448d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3449d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        private final UserHandleCompat mUser;
3450d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3451d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        public UserLockStateChangedTask(UserHandleCompat user) {
3452d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            mUser = user;
3453d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        }
3454d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3455d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        @Override
3456d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        public void run() {
3457d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            boolean isUserUnlocked = mUserManager.isUserUnlocked(mUser);
3458d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            Context context = mApp.getContext();
3459d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3460d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            HashMap<ShortcutKey, ShortcutInfoCompat> pinnedShortcuts = new HashMap<>();
3461d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            if (isUserUnlocked) {
346249f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                List<ShortcutInfoCompat> shortcuts =
346349f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                        mDeepShortcutManager.queryForPinnedShortcuts(null, mUser);
346449f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                if (mDeepShortcutManager.wasLastCallSuccess()) {
346549f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    for (ShortcutInfoCompat shortcut : shortcuts) {
346649f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                        pinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut);
346749f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    }
346849f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                } else {
346949f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    // Shortcut manager can fail due to some race condition when the lock state
347049f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    // changes too frequently. For the purpose of the update,
347149f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    // consider it as still locked.
347249f4f03dc8ed3925e80d379634e43eb24eea25b9Sunny Goyal                    isUserUnlocked = false;
3473d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                }
3474d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            }
3475d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3476d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            // Update the workspace to reflect the changes to updated shortcuts residing on it.
3477d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            ArrayList<ShortcutInfo> updatedShortcutInfos = new ArrayList<>();
3478d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            ArrayList<ShortcutInfo> deletedShortcutInfos = new ArrayList<>();
3479d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            for (ItemInfo itemInfo : sBgItemsIdMap) {
3480d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                if (itemInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
3481d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        && mUser.equals(itemInfo.user)) {
3482d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    ShortcutInfo si = (ShortcutInfo) itemInfo;
3483d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    if (isUserUnlocked) {
3484d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        ShortcutInfoCompat shortcut =
3485fc02c1b446ee54561ac7351fb6ff0f8294785f0eTony Wickham                                pinnedShortcuts.get(ShortcutKey.fromShortcutInfo(si));
3486d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        // We couldn't verify the shortcut during loader. If its no longer available
3487d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        // (probably due to clear data), delete the workspace item as well
3488d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        if (shortcut == null) {
3489d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                            deletedShortcutInfos.add(si);
3490d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                            continue;
3491d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        }
3492d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_LOCKED_USER;
3493d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        si.updateFromDeepShortcutInfo(shortcut, context);
3494d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    } else {
3495d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                        si.isDisabled |= ShortcutInfo.FLAG_DISABLED_LOCKED_USER;
3496d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    }
3497d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    updatedShortcutInfos.add(si);
3498d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                }
3499d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            }
3500d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            bindUpdatedShortcuts(updatedShortcutInfos, deletedShortcutInfos, mUser);
3501d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            if (!deletedShortcutInfos.isEmpty()) {
3502d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                deleteItemsFromDatabase(context, deletedShortcutInfos);
3503d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            }
3504d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3505d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            // Remove shortcut id map for that user
3506d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            Iterator<ComponentKey> keysIter = mBgDeepShortcutMap.keySet().iterator();
3507d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            while (keysIter.hasNext()) {
3508d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                if (keysIter.next().user.equals(mUser)) {
3509d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                    keysIter.remove();
3510d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                }
3511d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            }
3512d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
3513d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            if (isUserUnlocked) {
3514d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                updateDeepShortcutMap(null, mUser, mDeepShortcutManager.queryForAllShortcuts(mUser));
3515d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            }
3516d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            bindDeepShortcuts();
3517d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        }
3518d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    }
3519d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal
35202e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal    private void bindWidgetsModel(final Callbacks callbacks, final WidgetsModel model) {
35212e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal        mHandler.post(new Runnable() {
35222e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            @Override
35232e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            public void run() {
35242e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                Callbacks cb = getCallback();
35252e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                if (callbacks == cb && cb != null) {
35262e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                    callbacks.bindWidgetsModel(model);
352726ace12135a662ad864678c9fede9817e5c02b67Robin Lee                }
35285940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen            }
35292e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal        });
35305940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen    }
35315940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
35322e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal    public void refreshAndBindWidgetsAndShortcuts(
35332e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal            final Callbacks callbacks, final boolean bindFirst) {
3534eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song        runOnWorkerThread(new Runnable() {
3535d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            @Override
3536d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            public void run() {
35372e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                if (bindFirst && !mBgWidgetsModel.isEmpty()) {
35382e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                    bindWidgetsModel(callbacks, mBgWidgetsModel.clone());
35392e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                }
35402e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                final WidgetsModel model = mBgWidgetsModel.updateAndClone(mApp.getContext());
35412e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                bindWidgetsModel(callbacks, model);
35428821ca9a6a5bf34308f9b70c2cabf9da17330497Hyunyoung Song                // update the Widget entries inside DB on the worker thread.
35432bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
35442e1efb480a9b77a97cb623d4f5faf6802a417422Sunny Goyal                        model.getRawList());
3545d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            }
3546d4af1484447129d489203130e0d654f81a10437dHyunyoung Song        });
3547d4af1484447129d489203130e0d654f81a10437dHyunyoung Song    }
3548d4af1484447129d489203130e0d654f81a10437dHyunyoung Song
3549091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static boolean isPackageDisabled(Context context, String packageName,
3550ed13187a745866483139e2878037e1f8427ce567Kenny Guy            UserHandleCompat user) {
3551ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3552ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return !launcherApps.isPackageEnabledForProfile(packageName, user);
3553df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung    }
3554556f6135f992dcd5bfbfffe0172627bfbf57d24eAdam Cohen
3555ed13187a745866483139e2878037e1f8427ce567Kenny Guy    public static boolean isValidPackageActivity(Context context, ComponentName cn,
3556ed13187a745866483139e2878037e1f8427ce567Kenny Guy            UserHandleCompat user) {
3557ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        if (cn == null) {
3558ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung            return false;
3559ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        }
3560ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3561ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {
3562ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung            return false;
3563ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        }
3564ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return launcherApps.isActivityEnabledForProfile(cn, user);
3565ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung    }
3566ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung
3567a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen    public static boolean isValidPackage(Context context, String packageName,
3568a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen            UserHandleCompat user) {
3569a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        if (packageName == null) {
3570a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen            return false;
3571a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        }
3572a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3573a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        return launcherApps.isPackageEnabledForProfile(packageName, user);
3574a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen    }
3575a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen
35769c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
3577f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * Make an ShortcutInfo object for a restored application or shortcut item that points
3578f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * to a package that is not yet installed on the system.
3579f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     */
3580d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    public ShortcutInfo getRestoredItemInfo(Cursor c, Intent intent,
3581d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            int promiseType, int itemType, CursorIconInfo iconInfo) {
3582f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        final ShortcutInfo info = new ShortcutInfo();
3583349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        info.user = UserHandleCompat.myUserHandle();
35844e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal
3585d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        Bitmap icon = iconInfo.loadIcon(c, info);
35864e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        // the fallback icon
35874e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        if (icon == null) {
35884e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
35894e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        } else {
35904e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            info.setIcon(icon);
35914e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        }
3592349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
3593349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
3594d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            String title = iconInfo.getTitle(c);
3595349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            if (!TextUtils.isEmpty(title)) {
359682b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                info.title = Utilities.trim(title);
3597349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            }
3598349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
3599349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            if (TextUtils.isEmpty(info.title)) {
3600d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal                info.title = iconInfo.getTitle(c);
3601349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            }
3602f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        } else {
3603349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            throw new InvalidParameterException("Invalid restoreType " + promiseType);
3604f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        }
3605349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
360682b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
3607c22841bfd1961781a84cfccb98d1c2937a9adee4Sunny Goyal        info.itemType = itemType;
3608349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        info.promisedIntent = intent;
3609756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        info.status = promiseType;
3610f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        return info;
3611f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    }
3612f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
3613f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    /**
3614f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * Make an Intent object for a restored application or shortcut item that points
3615f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * to the market page for the item.
3616f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     */
3617091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
3618f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        ComponentName componentName = intent.getComponent();
3619e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        return getMarketIntent(componentName.getPackageName());
3620e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
3621e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
3622e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    static Intent getMarketIntent(String packageName) {
3623e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        return new Intent(Intent.ACTION_VIEW)
3624e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            .setData(new Uri.Builder()
3625f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                .scheme("market")
3626f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                .authority("details")
3627e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                .appendQueryParameter("id", packageName)
3628e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                .build());
3629f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    }
3630f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
3631f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    /**
363256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     * Make an ShortcutInfo object for a shortcut that is an application.
363356d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     *
363456d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     * If c is not null, then it will be used to fill in missing data like the title and icon.
363556d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     */
3636d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal    public ShortcutInfo getAppShortcutInfo(Intent intent,
3637d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            UserHandleCompat user, Cursor c, CursorIconInfo iconInfo,
363834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            boolean allowMissingTarget, boolean useLowResIcon) {
3639ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (user == null) {
3640ed13187a745866483139e2878037e1f8427ce567Kenny Guy            Log.d(TAG, "Null user found in getShortcutInfo");
3641ed13187a745866483139e2878037e1f8427ce567Kenny Guy            return null;
3642ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3643ed13187a745866483139e2878037e1f8427ce567Kenny Guy
364456d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        ComponentName componentName = intent.getComponent();
3645ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (componentName == null) {
3646b740f59c7d572d54402e3a74fb2a23c0f1b1af48Sunny Goyal            Log.d(TAG, "Missing component found in getShortcutInfo");
36479c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            return null;
364831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
364931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3650ed13187a745866483139e2878037e1f8427ce567Kenny Guy        Intent newIntent = new Intent(intent.getAction(), null);
3651ed13187a745866483139e2878037e1f8427ce567Kenny Guy        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
3652ed13187a745866483139e2878037e1f8427ce567Kenny Guy        newIntent.setComponent(componentName);
3653ed13187a745866483139e2878037e1f8427ce567Kenny Guy        LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);
3654f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        if ((lai == null) && !allowMissingTarget) {
3655ed13187a745866483139e2878037e1f8427ce567Kenny Guy            Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);
3656ed13187a745866483139e2878037e1f8427ce567Kenny Guy            return null;
3657ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3658ed13187a745866483139e2878037e1f8427ce567Kenny Guy
3659ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final ShortcutInfo info = new ShortcutInfo();
366034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        mIconCache.getTitleAndIcon(info, componentName, lai, user, false, useLowResIcon);
36614fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        if (mIconCache.isDefaultIcon(info.getIcon(mIconCache), user) && c != null) {
3662d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            Bitmap icon = iconInfo.loadIcon(c);
36634fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
3664ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3665ed13187a745866483139e2878037e1f8427ce567Kenny Guy
3666d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal        if (lai != null && PackageManagerHelper.isAppSuspended(lai.getApplicationInfo())) {
3667d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal            info.isDisabled = ShortcutInfo.FLAG_DISABLED_SUSPENDED;
3668d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal        }
3669d09c37052ef9a70d4dde53ece6619f04de5f97cbSunny Goyal
367056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        // from the db
36714fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        if (TextUtils.isEmpty(info.title) && c != null) {
3672d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal            info.title = iconInfo.getTitle(c);
367356d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        }
36744fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
367556d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        // fall back to the class name of the activity
36769c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        if (info.title == null) {
367756d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato            info.title = componentName.getClassName();
36789c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
36794fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
36809c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
3681ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = user;
368282b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
3683fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal        if (lai != null) {
3684fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal            info.flags = AppInfo.initFlags(lai);
3685fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal        }
36869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        return info;
36879c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
368831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3689e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static ArrayList<ItemInfo> filterItemInfos(Iterable<ItemInfo> infos,
369064359a53dc827797917a8d9a0697a91996789801Winson Chung            ItemInfoFilter f) {
369164359a53dc827797917a8d9a0697a91996789801Winson Chung        HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();
369264359a53dc827797917a8d9a0697a91996789801Winson Chung        for (ItemInfo i : infos) {
369364359a53dc827797917a8d9a0697a91996789801Winson Chung            if (i instanceof ShortcutInfo) {
369464359a53dc827797917a8d9a0697a91996789801Winson Chung                ShortcutInfo info = (ShortcutInfo) i;
3695349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                ComponentName cn = info.getTargetComponent();
369664359a53dc827797917a8d9a0697a91996789801Winson Chung                if (cn != null && f.filterItem(null, info, cn)) {
369764359a53dc827797917a8d9a0697a91996789801Winson Chung                    filtered.add(info);
369864359a53dc827797917a8d9a0697a91996789801Winson Chung                }
369964359a53dc827797917a8d9a0697a91996789801Winson Chung            } else if (i instanceof FolderInfo) {
370064359a53dc827797917a8d9a0697a91996789801Winson Chung                FolderInfo info = (FolderInfo) i;
370164359a53dc827797917a8d9a0697a91996789801Winson Chung                for (ShortcutInfo s : info.contents) {
3702349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                    ComponentName cn = s.getTargetComponent();
370364359a53dc827797917a8d9a0697a91996789801Winson Chung                    if (cn != null && f.filterItem(info, s, cn)) {
370464359a53dc827797917a8d9a0697a91996789801Winson Chung                        filtered.add(s);
37058a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung                    }
37068a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung                }
370764359a53dc827797917a8d9a0697a91996789801Winson Chung            } else if (i instanceof LauncherAppWidgetInfo) {
370864359a53dc827797917a8d9a0697a91996789801Winson Chung                LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;
370964359a53dc827797917a8d9a0697a91996789801Winson Chung                ComponentName cn = info.providerName;
371064359a53dc827797917a8d9a0697a91996789801Winson Chung                if (cn != null && f.filterItem(null, info, cn)) {
371164359a53dc827797917a8d9a0697a91996789801Winson Chung                    filtered.add(info);
371264359a53dc827797917a8d9a0697a91996789801Winson Chung                }
37138a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung            }
37148a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung        }
371564359a53dc827797917a8d9a0697a91996789801Winson Chung        return new ArrayList<ItemInfo>(filtered);
371664359a53dc827797917a8d9a0697a91996789801Winson Chung    }
371764359a53dc827797917a8d9a0697a91996789801Winson Chung
3718091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,
3719ed13187a745866483139e2878037e1f8427ce567Kenny Guy            final UserHandleCompat user) {
372064359a53dc827797917a8d9a0697a91996789801Winson Chung        ItemInfoFilter filter  = new ItemInfoFilter() {
372164359a53dc827797917a8d9a0697a91996789801Winson Chung            @Override
372264359a53dc827797917a8d9a0697a91996789801Winson Chung            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
3723ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (info.user == null) {
3724ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return cn.equals(cname);
3725ed13187a745866483139e2878037e1f8427ce567Kenny Guy                } else {
3726ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return cn.equals(cname) && info.user.equals(user);
3727ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
372864359a53dc827797917a8d9a0697a91996789801Winson Chung            }
372964359a53dc827797917a8d9a0697a91996789801Winson Chung        };
3730e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal        return filterItemInfos(sBgItemsIdMap, filter);
373164359a53dc827797917a8d9a0697a91996789801Winson Chung    }
373264359a53dc827797917a8d9a0697a91996789801Winson Chung
37331a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal    /**
37340589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     * Make an ShortcutInfo object for a shortcut that isn't an application.
37359c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
3736d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    @Thunk ShortcutInfo getShortcutInfo(Cursor c, CursorIconInfo iconInfo) {
3737c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ShortcutInfo info = new ShortcutInfo();
3738ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // Non-app shortcuts are only supported for current user.
3739ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = UserHandleCompat.myUserHandle();
37409c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
37417376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project
37428ddc4fdba06cfa786950c306475b7a4e3f6846abJoe Onorato        // TODO: If there's an explicit component and we can't install that, delete it.
37438ddc4fdba06cfa786950c306475b7a4e3f6846abJoe Onorato
3744d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        loadInfoFromCursor(info, c, iconInfo);
3745d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        return info;
3746d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    }
374756d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
3748d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    /**
3749d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal     * Make an ShortcutInfo object for a shortcut that isn't an application.
3750d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal     */
3751d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal    public void loadInfoFromCursor(ShortcutInfo info, Cursor c, CursorIconInfo iconInfo) {
3752d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        info.title = iconInfo.getTitle(c);
3753d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        Bitmap icon = iconInfo.loadIcon(c, info);
37544e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        // the fallback icon
37554e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        if (icon == null) {
3756ed13187a745866483139e2878037e1f8427ce567Kenny Guy            icon = mIconCache.getDefaultIcon(info.user);
375756d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato            info.usingFallbackIcon = true;
375831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
3759d8d22da5ca3e8d3e8d2e3616305b038d37486f32Joe Onorato        info.setIcon(icon);
3760f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
376131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
37622350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
37630589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
37640589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
37650589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
37660589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
3767d919882006a457d16dea46bd546472e6534b5c19Adam Cohen        if (intent == null) {
3768d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            // If the intent is null, we can't construct a valid ShortcutInfo, so we return null
3769d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            Log.e(TAG, "Can't construct ShorcutInfo with null intent");
3770d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            return null;
3771d919882006a457d16dea46bd546472e6534b5c19Adam Cohen        }
3772d919882006a457d16dea46bd546472e6534b5c19Adam Cohen
37730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Bitmap icon = null;
37740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        boolean customIcon = false;
37750589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        ShortcutIconResource iconResource = null;
37760589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
37772fce90c38a79d318e96a28107dea287e42509861Sunny Goyal        if (bitmap instanceof Bitmap) {
37782fce90c38a79d318e96a28107dea287e42509861Sunny Goyal            icon = Utilities.createIconBitmap((Bitmap) bitmap, context);
37790589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            customIcon = true;
37800589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        } else {
37810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
3782b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal            if (extra instanceof ShortcutIconResource) {
3783b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                iconResource = (ShortcutIconResource) extra;
3784b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                icon = Utilities.createIconBitmap(iconResource.packageName,
378553d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                        iconResource.resourceName, context);
37860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            }
37870589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
37880589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
3789c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ShortcutInfo info = new ShortcutInfo();
379056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
3791ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // Only support intents for current user for now. Intents sent from other
3792ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // users wouldn't get here without intent forwarding anyway.
3793ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = UserHandleCompat.myUserHandle();
37940589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        if (icon == null) {
37952350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal            icon = mIconCache.getDefaultIcon(info.user);
37962350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal            info.usingFallbackIcon = true;
37970589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
37980589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.setIcon(icon);
379956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
380082b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.title = Utilities.trim(name);
380182b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
38020589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.intent = intent;
38030589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.iconResource = iconResource;
38040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
38050589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        return info;
38060589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
38070589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
380831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
3809df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * Return an existing FolderInfo object if we have encountered this ID previously,
38109c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * or make a new one.
381131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3812e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    @Thunk static FolderInfo findOrMakeFolder(LongArrayMap<FolderInfo> folders, long id) {
38139c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        // See if a placeholder was created for us already
38149c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        FolderInfo folderInfo = folders.get(id);
3815df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        if (folderInfo == null) {
38169c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // No placeholder -- create a new instance
3817c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            folderInfo = new FolderInfo();
38189c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            folders.put(id, folderInfo);
381931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
3820df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        return folderInfo;
382131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
382231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3823be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato
3824651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal    static boolean isValidProvider(AppWidgetProviderInfo provider) {
3825651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal        return (provider != null) && (provider.provider != null)
3826651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                && (provider.provider.getPackageName() != null);
3827651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal    }
3828651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal
3829be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato    public void dumpState() {
3830be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato        Log.d(TAG, "mCallbacks=" + mCallbacks);
3831eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);
3832eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);
3833eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);
3834eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);
38353611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        if (mLoaderTask != null) {
38363611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mLoaderTask.dumpState();
38373611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        } else {
38383611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            Log.d(TAG, "mLoaderTask=null");
38393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
3840be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato    }
3841e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
3842e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    public Callbacks getCallback() {
3843e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        return mCallbacks != null ? mCallbacks.get() : null;
3844e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
384518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal
384618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    /**
384718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal     * @return {@link FolderInfo} if its already loaded.
384818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal     */
384918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public FolderInfo findFolderById(Long folderId) {
385018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal        synchronized (sBgLock) {
385118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            return sBgFolders.get(folderId);
385218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal        }
385318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    }
3854756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
3855527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    @Thunk class DeferredMainThreadExecutor implements Executor {
3856527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
3857527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        @Override
3858527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        public void execute(Runnable command) {
3859527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal            runOnMainThread(command);
3860527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal        }
3861527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal    }
3862527c7d3460345953e6b3427a74b1dacaddcb1111Sunny Goyal
3863756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    /**
3864756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * @return the looper for the worker thread which can be used to start background tasks.
3865756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     */
3866756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    public static Looper getWorkerLooper() {
3867756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        return sWorkerThread.getLooper();
3868756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    }
386931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
3870