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
19cb1a4778686a46c46d8dc88b6c83674f6fac6592Narayan Kamathimport android.app.SearchManager;
202d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyalimport android.appwidget.AppWidgetManager;
21629de3ef739883c0962423cc0c3a26299f162d3dRomain Guyimport android.appwidget.AppWidgetProviderInfo;
22f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.BroadcastReceiver;
23f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ComponentName;
24f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentProviderOperation;
25f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentResolver;
26f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.ContentValues;
27f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.Context;
28f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.Intent;
290589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.content.Intent.ShortcutIconResource;
30f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport android.content.IntentFilter;
3131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.pm.PackageManager;
32bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monkimport android.content.pm.ProviderInfo;
3331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.pm.ResolveInfo;
3431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.database.Cursor;
3531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.graphics.Bitmap;
3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.net.Uri;
3717a8922e2ab2ad599df3750d398a095473ccd1b4Joe Onoratoimport android.os.Environment;
383611578579b4bfb25616085dafdb1a45207394f9Joe Onoratoimport android.os.Handler;
393611578579b4bfb25616085dafdb1a45207394f9Joe Onoratoimport android.os.HandlerThread;
40756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyalimport android.os.Looper;
410589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.os.Parcelable;
4231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.os.Process;
439c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onoratoimport android.os.SystemClock;
443abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Songimport android.os.TransactionTooLargeException;
45c3919c0e994309982efc8779af57e2bc78dcac43Chris Wrenimport android.provider.BaseColumns;
46a90303bb6fdad59e4a55855edba68c9902192599Winson Chungimport android.text.TextUtils;
47aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chungimport android.util.Log;
4871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyalimport android.util.LongSparseArray;
49c916834ad0da535f08325bcd902a60070f2f7e53Winson Chungimport android.util.Pair;
5034c2e6cf7af328aba25c98158161dbad15ae986dMichael Jurka
51ffe83f13319cdb833a25596d47cf1af098cc4c60Sunny Goyalimport com.android.launcher3.compat.AppWidgetManagerCompat;
52ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherActivityInfoCompat;
53ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat;
54349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat;
55e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
56ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserHandleCompat;
57ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.UserManagerCompat;
58e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyalimport com.android.launcher3.model.MigrateFromRestoreTask;
592bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Songimport com.android.launcher3.model.WidgetsModel;
6026ace12135a662ad864678c9fede9817e5c02b67Robin Leeimport com.android.launcher3.util.ComponentKey;
614e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyalimport com.android.launcher3.util.CursorIconInfo;
62e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyalimport com.android.launcher3.util.LongArrayMap;
6318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyalimport com.android.launcher3.util.ManagedProfileHeuristic;
64091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
65edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy
66c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.lang.ref.WeakReference;
67c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.net.URISyntaxException;
68349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyalimport java.security.InvalidParameterException;
69c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.ArrayList;
70dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohenimport java.util.Arrays;
7164359a53dc827797917a8d9a0697a91996789801Winson Chungimport java.util.Collection;
72c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.Collections;
73c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.Comparator;
74c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.HashMap;
75b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chungimport java.util.HashSet;
762abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chungimport java.util.Iterator;
77c2f801e770b4f80354b3edb722ec04222251990cMichael Jurkaimport java.util.List;
78f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyalimport java.util.Map.Entry;
79b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chungimport java.util.Set;
80c2f801e770b4f80354b3edb722ec04222251990cMichael Jurka
8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/**
8231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Maintains in-memory state of the Launcher. It is expected that there should be only one
8331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * LauncherModel object held in a static. Also provide APIs for updating the database state
84bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project * for the Launcher.
8531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */
86ed13187a745866483139e2878037e1f8427ce567Kenny Guypublic class LauncherModel extends BroadcastReceiver
87c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
88a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato    static final boolean DEBUG_LOADERS = false;
89ee52336a9ed0c98f78831a0e44b21f5a8d8c17d1Chris Wren    private static final boolean DEBUG_RECEIVER = false;
909448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal    private static final boolean REMOVE_UNRESTORED_ICONS = true;
91b358f813c93ac0d6c4f31058947efd16b188cd1eChris Wren
929c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    static final String TAG = "Launcher.Model";
939c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
94d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler    public static final int LOADER_FLAG_NONE = 0;
95d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler    public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
96d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler    public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
97d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler
983611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
997aff399974c756930070d82d7b2df88f125dacd6Derek Prothro    private static final long INVALID_SCREEN_ID = -1L;
100a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung
101091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final boolean mAppsCanBeOnRemoveableStorage;
102a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung    private final boolean mOldContentProviderExists;
103dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
104091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final LauncherAppState mApp;
105091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final Object mLock = new Object();
106091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk DeferredHandler mHandler = new DeferredHandler();
107091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk LoaderTask mLoaderTask;
108091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk boolean mIsLoaderTaskRunning;
109756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk boolean mHasLoaderCompletedOnce;
1109c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
111bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk    private static final String MIGRATE_AUTHORITY = "com.android.launcher2.settings";
11281b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung
113091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
114700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick    static {
115700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick        sWorkerThread.start();
116700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick    }
117091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());
118700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick
119cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // We start off with everything not loaded.  After that, we assume that
120cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // our monitoring of the package manager provides all updates and we never
121cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato    // need to do a requery.  These are only ever touched from the loader thread.
122091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk boolean mWorkspaceLoaded;
123091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk boolean mAllAppsLoaded;
124cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato
125b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // When we are loading pages synchronously, we can't just post the binding of items on the side
126b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // pages as this delays the rotation process.  Instead, we wait for a callback from the first
127b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // draw (in Workspace) to initiate the binding of the remaining side pages.  Any time we start
128b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // a normal load, we also clear this set of Runnables.
129b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    static final ArrayList<Runnable> mDeferredBindRunnables = new ArrayList<Runnable>();
130b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
131756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    /**
132756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     * Set of runnables to be called on the background thread after the workspace binding
133756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     * is complete.
134756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal     */
135756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    static final ArrayList<Runnable> mBindCompleteRunnables = new ArrayList<Runnable>();
136756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
137091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk WeakReference<Callbacks> mCallbacks;
1389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
139a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // < only access in worker thread >
1404caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen    AllAppsList mBgAllAppsList;
1419110d485fa12c03df3061278717efb342f1142cfHyunyoung Song    // Entire list of widgets.
1429110d485fa12c03df3061278717efb342f1142cfHyunyoung Song    WidgetsModel mBgWidgetsModel;
143a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
144b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // The lock that must be acquired before referencing any static bg data structures.  Unlike
145b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // other locks, this one can generally be held long-term because we never expect any of these
146b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // static data structures to be referenced outside of the worker thread except on the first
147b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    // load after configuration change.
1482abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung    static final Object sBgLock = new Object();
149b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
150487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
151a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // LauncherModel to their ids
152e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static final LongArrayMap<ItemInfo> sBgItemsIdMap = new LongArrayMap<>();
153a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
154487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgWorkspaceItems is passed to bindItems, which expects a list of all folders and shortcuts
155487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    //       created by LauncherModel that are directly on the home screen (however, no widgets or
156487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    //       shortcuts within folders).
157487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    static final ArrayList<ItemInfo> sBgWorkspaceItems = new ArrayList<ItemInfo>();
1580589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
159487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()
160487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    static final ArrayList<LauncherAppWidgetInfo> sBgAppWidgets =
161a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka        new ArrayList<LauncherAppWidgetInfo>();
162a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
163487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen    // sBgFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
164e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static final LongArrayMap<FolderInfo> sBgFolders = new LongArrayMap<>();
165b1094bd9630f659cc606853b8a244b6a6b6c6943Winson Chung
166dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    // sBgWorkspaceScreens is the ordered set of workspace screens.
167dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
168dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1695940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen    // sBgWidgetProviders is the set of widget providers including custom internal widgets
17026ace12135a662ad864678c9fede9817e5c02b67Robin Lee    public static HashMap<ComponentKey, LauncherAppWidgetProviderInfo> sBgWidgetProviders;
1715940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
172f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal    // sPendingPackages is a set of packages which could be on sdcard and are not available yet
173513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala    static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =
174513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala            new HashMap<UserHandleCompat, HashSet<String>>();
175f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
176a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka    // </ only access in worker thread >
177a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka
178091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk IconCache mIconCache;
1799c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato
180091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final LauncherAppsCompat mLauncherApps;
181091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final UserManagerCompat mUserManager;
182ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1839c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    public interface Callbacks {
184ef2efcff5e70e5900f4f10f9e46c3fa17c03b0ecJoe Onorato        public boolean setLoadOnResume();
1859c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public int getCurrentWorkspaceScreen();
1869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public void startBinding();
18764359a53dc827797917a8d9a0697a91996789801Winson Chung        public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end,
18864359a53dc827797917a8d9a0697a91996789801Winson Chung                              boolean forceAnimateIcons);
189dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        public void bindScreens(ArrayList<Long> orderedScreenIds);
19064359a53dc827797917a8d9a0697a91996789801Winson Chung        public void bindAddScreens(ArrayList<Long> orderedScreenIds);
191e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal        public void bindFolders(LongArrayMap<FolderInfo> folders);
19266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        public void finishBindingItems();
1939c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        public void bindAppWidget(LauncherAppWidgetInfo info);
194eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public void bindAllApplications(ArrayList<AppInfo> apps);
195d64d1763c590b1c954b759156683abf39ff22945Winson Chung        public void bindAppsAdded(ArrayList<Long> newScreens,
196d64d1763c590b1c954b759156683abf39ff22945Winson Chung                                  ArrayList<ItemInfo> addNotAnimated,
197c58497ee619416c4949b16eb43486c11618b69e5Winson Chung                                  ArrayList<ItemInfo> addAnimated,
198c58497ee619416c4949b16eb43486c11618b69e5Winson Chung                                  ArrayList<AppInfo> addedApps);
199eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        public void bindAppsUpdated(ArrayList<AppInfo> apps);
2004390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal        public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
2014390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                ArrayList<ShortcutInfo> removed, UserHandleCompat user);
2024390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal        public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
203756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
20483892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung        public void bindComponentsRemoved(ArrayList<String> packageNames,
2051a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                        ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
2062bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song        public void bindAllPackages(WidgetsModel model);
20788fa741e50760f9da78cba4a766172f23773bb87Winson Chung        public void bindSearchProviderChanged();
208a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung        public boolean isAllAppsButtonRank(int rank);
2091462de39f01cec0ba785386532719cb0207dd827Adam Cohen        public void onPageBoundSynchronously(int page);
210ede4129e77f8347e32c0da9c615bcff2cbc06fd8Winson Chung        public void dumpLogsToLocalData();
2119c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
21231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
21364359a53dc827797917a8d9a0697a91996789801Winson Chung    public interface ItemInfoFilter {
21464359a53dc827797917a8d9a0697a91996789801Winson Chung        public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn);
21564359a53dc827797917a8d9a0697a91996789801Winson Chung    }
21664359a53dc827797917a8d9a0697a91996789801Winson Chung
2171307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert    LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
218a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung        Context context = app.getContext();
219e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler
220ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
22171483f417bb19f524cda41081f5ccac6084dc103Adam Cohen        String oldProvider = context.getString(R.string.old_launcher_provider_uri);
222bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        // This may be the same as MIGRATE_AUTHORITY, or it may be replaced by a different
223bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        // resource string.
224bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        String redirectAuthority = Uri.parse(oldProvider).getAuthority();
225bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        ProviderInfo providerInfo =
226bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk                context.getPackageManager().resolveContentProvider(MIGRATE_AUTHORITY, 0);
227bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        ProviderInfo redirectProvider =
228bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk                context.getPackageManager().resolveContentProvider(redirectAuthority, 0);
22971483f417bb19f524cda41081f5ccac6084dc103Adam Cohen
23071483f417bb19f524cda41081f5ccac6084dc103Adam Cohen        Log.d(TAG, "Old launcher provider: " + oldProvider);
231bbe1e24c5ff470a695510d23d67bcb6f2ad88d0eJason Monk        mOldContentProviderExists = (providerInfo != null) && (redirectProvider != null);
23271483f417bb19f524cda41081f5ccac6084dc103Adam Cohen
23371483f417bb19f524cda41081f5ccac6084dc103Adam Cohen        if (mOldContentProviderExists) {
23471483f417bb19f524cda41081f5ccac6084dc103Adam Cohen            Log.d(TAG, "Old launcher provider exists.");
23571483f417bb19f524cda41081f5ccac6084dc103Adam Cohen        } else {
23671483f417bb19f524cda41081f5ccac6084dc103Adam Cohen            Log.d(TAG, "Old launcher provider does not exist.");
23771483f417bb19f524cda41081f5ccac6084dc103Adam Cohen        }
23871483f417bb19f524cda41081f5ccac6084dc103Adam Cohen
239e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mApp = app;
2401307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert        mBgAllAppsList = new AllAppsList(iconCache, appFilter);
241eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song        mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter);
2420589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        mIconCache = iconCache;
2430589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
244ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mLauncherApps = LauncherAppsCompat.getInstance(context);
245ed13187a745866483139e2878037e1f8427ce567Kenny Guy        mUserManager = UserManagerCompat.getInstance(context);
2460589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
2470589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
248b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    /** Runs the specified runnable immediately if called from the main thread, otherwise it is
249b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung     * posted on the main thread handler. */
250091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk void runOnMainThread(Runnable r) {
251b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        if (sWorkerThread.getThreadId() == Process.myTid()) {
252b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // If we are on the worker thread, post onto the main handler
253b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            mHandler.post(r);
254b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        } else {
255b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r.run();
256b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
257b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
258b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
259b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    /** Runs the specified runnable immediately if called from the worker thread, otherwise it is
260b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung     * posted on the worker thread handler. */
261639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal    @Thunk static void runOnWorkerThread(Runnable r) {
262b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        if (sWorkerThread.getThreadId() == Process.myTid()) {
263b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r.run();
264b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        } else {
265b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // If we are not on the worker thread, then post to the worker handler
266b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sWorker.post(r);
267b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
268b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
269b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
270e43a1e788223ab5a4405c5eeb0133ff57efbc768Winson Chung    boolean canMigrateFromOldLauncherDb(Launcher launcher) {
271e43a1e788223ab5a4405c5eeb0133ff57efbc768Winson Chung        return mOldContentProviderExists && !launcher.isLauncherPreinstalled() ;
272a694524047fda0a51dede4eefb1201a598d2d3a7Winson Chung    }
273a694524047fda0a51dede4eefb1201a598d2d3a7Winson 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) {
338756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    final ArrayList<ShortcutInfo> updates = new ArrayList<>();
339756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    final 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
361756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    if (!updates.isEmpty()) {
362756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        // Push changes to the callback.
363756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        Runnable r = new Runnable() {
364756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            public void run() {
365756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                Callbacks callbacks = getCallback();
366756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                if (callbacks != null) {
367756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    callbacks.bindShortcutsChanged(updates,
368756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            new ArrayList<ShortcutInfo>(), user);
369756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                }
370756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            }
371756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        };
372756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                        mHandler.post(r);
373756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
374a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal                }
375a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal            }
376a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal        };
377756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        runOnWorkerThread(updateRunnable);
378a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal    }
379a22666f68151269853e7ab6ab696ee6361bac793Sunny Goyal
38076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen    public void addAppsToAllApps(final Context ctx, final ArrayList<AppInfo> allAppsApps) {
381e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        final Callbacks callbacks = getCallback();
38276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
38376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (allAppsApps == null) {
38476a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            throw new RuntimeException("allAppsApps must not be null");
38576a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        }
38676a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (allAppsApps.isEmpty()) {
38776a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            return;
38876a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        }
38976a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
39076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        // Process the newly added applications and add them to the database first
39176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        Runnable r = new Runnable() {
39276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            public void run() {
39376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                runOnMainThread(new Runnable() {
39476a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                    public void run() {
395e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
39676a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                        if (callbacks == cb && cb != null) {
3976d0dde01f307051ee1849481c989d9e87774b894Chris Wren                            callbacks.bindAppsAdded(null, null, null, allAppsApps);
39876a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                        }
39976a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                    }
40076a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                });
40176a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen            }
40276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        };
40376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        runOnWorkerThread(r);
404997a92348a6d6e061737399321393449c16cd4d8Winson Chung    }
40576a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
406a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal    private static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> occupiedPos,
40771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            int[] xy, int spanX, int spanY) {
40871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        LauncherAppState app = LauncherAppState.getInstance();
4092e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
4102e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        final int xCount = (int) profile.numColumns;
4112e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        final int yCount = (int) profile.numRows;
41271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        boolean[][] occupied = new boolean[xCount][yCount];
41371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (occupiedPos != null) {
414a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (ItemInfo r : occupiedPos) {
415a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                int right = r.cellX + r.spanX;
416a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                int bottom = r.cellY + r.spanY;
417a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                for (int x = r.cellX; 0 <= x && x < right && x < xCount; x++) {
418a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    for (int y = r.cellY; 0 <= y && y < bottom && y < yCount; y++) {
41971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        occupied[x][y] = true;
42071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    }
42171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                }
42271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
42371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
424f7a29e83f06909b378dba39c83a522375682710aSunny Goyal        return Utilities.findVacantCell(xy, spanX, spanY, xCount, yCount, occupied);
42571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    }
42671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
42771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    /**
42871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * Find a position on the screen for the given size or adds a new screen.
42971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * @return screenId and the coordinates for the item.
43071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     */
431756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk Pair<Long, int[]> findSpaceForItem(
43271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            Context context,
43371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            ArrayList<Long> workspaceScreens,
43471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            ArrayList<Long> addedWorkspaceScreensFinal,
43571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            int spanX, int spanY) {
436a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        LongSparseArray<ArrayList<ItemInfo>> screenItems = new LongSparseArray<>();
437a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal
438a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        // Use sBgItemsIdMap as all the items are already loaded.
439756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        assertWorkspaceLoaded();
440a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        synchronized (sBgLock) {
441a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (ItemInfo info : sBgItemsIdMap) {
442a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
443a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    ArrayList<ItemInfo> items = screenItems.get(info.screenId);
444a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    if (items == null) {
445a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        items = new ArrayList<>();
446a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        screenItems.put(info.screenId, items);
447a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    }
448a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                    items.add(info);
44971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                }
45071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
45171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
45271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
45371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        // Find appropriate space for the item.
45471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        long screenId = 0;
45571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        int[] cordinates = new int[2];
45671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        boolean found = false;
45771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
45871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        int screenCount = workspaceScreens.size();
45971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        // First check the preferred screen.
460a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal        int preferredScreenIndex = workspaceScreens.isEmpty() ? 0 : 1;
46171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (preferredScreenIndex < screenCount) {
46271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            screenId = workspaceScreens.get(preferredScreenIndex);
46371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            found = findNextAvailableIconSpaceInScreen(
46471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    screenItems.get(screenId), cordinates, spanX, spanY);
46571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
46671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
46771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (!found) {
468a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            // Search on any of the screens starting from the first screen.
469a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal            for (int screen = 1; screen < screenCount; screen++) {
47071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                screenId = workspaceScreens.get(screen);
47171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                if (findNextAvailableIconSpaceInScreen(
47271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        screenItems.get(screenId), cordinates, spanX, spanY)) {
47371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    // We found a space for it
47471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    found = true;
47571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    break;
47671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                }
47771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
47871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        }
47971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
48071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        if (!found) {
48171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // Still no position found. Add a new screen to the end.
48271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            screenId = LauncherAppState.getLauncherProvider().generateNewScreenId();
48371b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
48471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // Save the screen id for binding in the workspace
48571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            workspaceScreens.add(screenId);
48671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            addedWorkspaceScreensFinal.add(screenId);
48776a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
48871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            // If we still can't find an empty space, then God help us all!!!
48971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            if (!findNextAvailableIconSpaceInScreen(
49071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    screenItems.get(screenId), cordinates, spanX, spanY)) {
49171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                throw new RuntimeException("Can't find space to add the item");
49271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal            }
493fe9d96a39651de99819208e95c7ec7d432a402e0Winson Chung        }
49471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        return Pair.create(screenId, cordinates);
49571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    }
49671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
49771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal    /**
49871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     * Adds the provided items to the workspace.
49971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal     */
50018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public void addAndBindAddedWorkspaceItems(final Context context,
501a214a63bfe365a0e81bc3082d56896c6df24d0b4Sunny Goyal            final ArrayList<? extends ItemInfo> workspaceApps) {
50271b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal        final Callbacks callbacks = getCallback();
50376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen        if (workspaceApps.isEmpty()) {
5049e6a0a20d40675ef98c7fdb8892cf34b90152f7aWinson Chung            return;
505997a92348a6d6e061737399321393449c16cd4d8Winson Chung        }
50664359a53dc827797917a8d9a0697a91996789801Winson Chung        // Process the newly added applications and add them to the database first
50764359a53dc827797917a8d9a0697a91996789801Winson Chung        Runnable r = new Runnable() {
50864359a53dc827797917a8d9a0697a91996789801Winson Chung            public void run() {
50964359a53dc827797917a8d9a0697a91996789801Winson Chung                final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
51064359a53dc827797917a8d9a0697a91996789801Winson Chung                final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
51164359a53dc827797917a8d9a0697a91996789801Winson Chung
51276828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // Get the list of workspace screens.  We need to append to this list and
51376828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // can not use sBgWorkspaceScreens because loadWorkspace() may not have been
51476828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // called.
515c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
51664359a53dc827797917a8d9a0697a91996789801Winson Chung                synchronized(sBgLock) {
51771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                    for (ItemInfo item : workspaceApps) {
518a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        if (item instanceof ShortcutInfo) {
51971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                            // Short-circuit this logic if the icon exists somewhere on the workspace
520756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                            if (shortcutExists(context, item.getIntent(), item.user)) {
52171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                                continue;
522c763c4e4d28c256d1368be3fc1c4526c8b9bd232Winson Chung                            }
52364359a53dc827797917a8d9a0697a91996789801Winson Chung                        }
52464359a53dc827797917a8d9a0697a91996789801Winson Chung
52571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        // Find appropriate space for the item.
526a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                        Pair<Long, int[]> coords = findSpaceForItem(context,
527a911672f45900fc0ed746e0d84c43c6e5ad89b6aSunny Goyal                                workspaceScreens, addedWorkspaceScreensFinal,
52871b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                                1, 1);
52971b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        long screenId = coords.first;
53071b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        int[] cordinates = coords.second;
53171b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
53218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        ItemInfo itemInfo;
53318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        if (item instanceof ShortcutInfo || item instanceof FolderInfo) {
53418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                            itemInfo = item;
53571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                        } else if (item instanceof AppInfo) {
53618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                            itemInfo = ((AppInfo) item).makeShortcut();
537997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        } else {
538997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            throw new RuntimeException("Unexpected info type");
539997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        }
54094d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung
54164359a53dc827797917a8d9a0697a91996789801Winson Chung                        // Add the shortcut to the db
54218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        addItemToDatabase(context, itemInfo,
54364359a53dc827797917a8d9a0697a91996789801Winson Chung                                LauncherSettings.Favorites.CONTAINER_DESKTOP,
5441d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                                screenId, cordinates[0], cordinates[1]);
54564359a53dc827797917a8d9a0697a91996789801Winson Chung                        // Save the ShortcutInfo for binding in the workspace
54618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        addedShortcutsFinal.add(itemInfo);
54764359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
54864359a53dc827797917a8d9a0697a91996789801Winson Chung                }
54964359a53dc827797917a8d9a0697a91996789801Winson Chung
55076828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                // Update the workspace screens
55176828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                updateWorkspaceScreenOrder(context, workspaceScreens);
55276828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
55376a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                if (!addedShortcutsFinal.isEmpty()) {
554997a92348a6d6e061737399321393449c16cd4d8Winson Chung                    runOnMainThread(new Runnable() {
555997a92348a6d6e061737399321393449c16cd4d8Winson Chung                        public void run() {
556e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Callbacks cb = getCallback();
557997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            if (callbacks == cb && cb != null) {
558997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                final ArrayList<ItemInfo> addAnimated = new ArrayList<ItemInfo>();
559997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                final ArrayList<ItemInfo> addNotAnimated = new ArrayList<ItemInfo>();
56094d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                if (!addedShortcutsFinal.isEmpty()) {
56194d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    ItemInfo info = addedShortcutsFinal.get(addedShortcutsFinal.size() - 1);
56294d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    long lastScreenId = info.screenId;
56394d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                    for (ItemInfo i : addedShortcutsFinal) {
56494d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        if (i.screenId == lastScreenId) {
56594d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                            addAnimated.add(i);
56694d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        } else {
56794d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                            addNotAnimated.add(i);
56894d6768c65929efa21bb893fdef7f269d65da3c3Winson Chung                                        }
569997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                    }
570997a92348a6d6e061737399321393449c16cd4d8Winson Chung                                }
571d64d1763c590b1c954b759156683abf39ff22945Winson Chung                                callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
57276a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen                                        addNotAnimated, addAnimated, null);
573997a92348a6d6e061737399321393449c16cd4d8Winson Chung                            }
57464359a53dc827797917a8d9a0697a91996789801Winson Chung                        }
575997a92348a6d6e061737399321393449c16cd4d8Winson Chung                    });
576997a92348a6d6e061737399321393449c16cd4d8Winson Chung                }
57764359a53dc827797917a8d9a0697a91996789801Winson Chung            }
57864359a53dc827797917a8d9a0697a91996789801Winson Chung        };
57964359a53dc827797917a8d9a0697a91996789801Winson Chung        runOnWorkerThread(r);
58064359a53dc827797917a8d9a0697a91996789801Winson Chung    }
58164359a53dc827797917a8d9a0697a91996789801Winson Chung
582d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal    private void unbindItemInfosAndClearQueuedBindRunnables() {
58381b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung        if (sWorkerThread.getThreadId() == Process.myTid()) {
58481b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung            throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +
58581b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung                    "main thread");
58681b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung        }
58781b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung
58881b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung        // Clear any deferred bind runnables
589a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk        synchronized (mDeferredBindRunnables) {
590a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            mDeferredBindRunnables.clear();
591a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk        }
592d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal
593d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal        // Remove any queued UI runnables
594d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal        mHandler.cancelAll();
59581b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung        // Unbind all the workspace items
59681b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung        unbindWorkspaceItemsOnMainThread();
597603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung    }
598603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung
599b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    /** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
60081b52252796625dcbadc9f8b908f8d8a284565c0Winson Chung    void unbindWorkspaceItemsOnMainThread() {
601603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung        // Ensure that we don't use the same workspace items data structure on the main thread
602603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung        // by making a copy of workspace items first.
603d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal        final ArrayList<ItemInfo> tmpItems = new ArrayList<ItemInfo>();
6042abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung        synchronized (sBgLock) {
605d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            tmpItems.addAll(sBgWorkspaceItems);
606d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            tmpItems.addAll(sBgAppWidgets);
607b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
608b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        Runnable r = new Runnable() {
609b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                @Override
610b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                public void run() {
611d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                   for (ItemInfo item : tmpItems) {
612b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                       item.unbind();
613b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                   }
614b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
615b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            };
616b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnMainThread(r);
6174eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen    }
6184eac29a80b9a73465c8de54f1caec2a8098a73c6Adam Cohen
6199c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
6209c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Adds an item to the DB if it was not created previously, or move it to a new
6219c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * <container, screen, cellX, cellY>
6229c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
6239c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
624dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long screenId, int cellX, int cellY) {
6259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        if (item.container == ItemInfo.NO_ID) {
6269c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // From all apps
6271d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal            addItemToDatabase(context, item, container, screenId, cellX, cellY);
6289c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        } else {
6299c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // From somewhere else
630dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            moveItemInDatabase(context, item, container, screenId, cellX, cellY);
6319c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
6329c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
63331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
634b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka    static void checkItemInfoLocked(
635b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            final long itemId, final ItemInfo item, StackTraceElement[] stackTrace) {
636b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        ItemInfo modelItem = sBgItemsIdMap.get(itemId);
637b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        if (modelItem != null && item != modelItem) {
638b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // check all the data is consistent
639b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {
640b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;
641b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                ShortcutInfo shortcut = (ShortcutInfo) item;
642b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&
643b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.intent.filterEquals(shortcut.intent) &&
644b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.id == shortcut.id &&
645b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.itemType == shortcut.itemType &&
646b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.container == shortcut.container &&
647dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        modelShortcut.screenId == shortcut.screenId &&
648b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.cellX == shortcut.cellX &&
649b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.cellY == shortcut.cellY &&
650b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.spanX == shortcut.spanX &&
651b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.spanY == shortcut.spanY &&
652b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        ((modelShortcut.dropPos == null && shortcut.dropPos == null) ||
653b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        (modelShortcut.dropPos != null &&
654b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                                shortcut.dropPos != null &&
655b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                                modelShortcut.dropPos[0] == shortcut.dropPos[0] &&
656b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                        modelShortcut.dropPos[1] == shortcut.dropPos[1]))) {
657b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    // For all intents and purposes, this is the same object
658b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    return;
659b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                }
660b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
661b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka
662b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // the modelItem needs to match up perfectly with item if our model is
663b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // to be consistent with the database-- for now, just require
664b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            // modelItem == item or the equality check above
665b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            String msg = "item: " + ((item != null) ? item.toString() : "null") +
666b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    "modelItem: " +
667b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    ((modelItem != null) ? modelItem.toString() : "null") +
668b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    "Error: ItemInfo passed to checkItemInfo doesn't match original";
669b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            RuntimeException e = new RuntimeException(msg);
670b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            if (stackTrace != null) {
671b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                e.setStackTrace(stackTrace);
672b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
673b9ada65af30c61c5b35da9b9efac75ffe6c56fd7Adam Cohen            throw e;
674b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        }
675b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka    }
676b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka
677816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka    static void checkItemInfo(final ItemInfo item) {
678816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
679816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        final long itemId = item.id;
680816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        Runnable r = new Runnable() {
681b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            public void run() {
682b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                synchronized (sBgLock) {
683b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka                    checkItemInfoLocked(itemId, item, stackTrace);
684816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka                }
685b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka            }
686b2ae8acc0c65a5464a4782ee43e0594a15b9cc16Michael Jurka        };
687b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
688816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka    }
689816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka
690c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    static void updateItemInDatabaseHelper(Context context, final ContentValues values,
691c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            final ItemInfo item, final String callingFunction) {
692c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final long itemId = item.id;
6931d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal        final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
694c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ContentResolver cr = context.getContentResolver();
695c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
696487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
697c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
698c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            public void run() {
699c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                cr.update(uri, values, null, null);
700f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                updateItemArrays(item, itemId, stackTrace);
701f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
702f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        };
703f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        runOnWorkerThread(r);
704f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
705c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
706f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,
707f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final ArrayList<ItemInfo> items, final String callingFunction) {
708f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        final ContentResolver cr = context.getContentResolver();
709c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
710f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
711f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        Runnable r = new Runnable() {
712f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            public void run() {
713f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                ArrayList<ContentProviderOperation> ops =
714f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        new ArrayList<ContentProviderOperation>();
715f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                int count = items.size();
716f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                for (int i = 0; i < count; i++) {
717f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ItemInfo item = items.get(i);
718f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    final long itemId = item.id;
7191d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
720f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ContentValues values = valuesList.get(i);
721f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
722f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
723f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    updateItemArrays(item, itemId, stackTrace);
724487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen
725f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
726f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                try {
727f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);
728f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                } catch (Exception e) {
729f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    e.printStackTrace();
730c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                }
731c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            }
732c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
733b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
734c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    }
735bebf042666cffe52039b875a549a582abd78a431Adam Cohen
736f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {
737f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        // Lock on mBgLock *after* the db operation
738f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        synchronized (sBgLock) {
739f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            checkItemInfoLocked(itemId, item, stackTrace);
740f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
741f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
742f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
743f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                // Item is in a folder, make sure this folder exists
744f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                if (!sBgFolders.containsKey(item.container)) {
745f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    // An items container is being set to a that of an item which is not in
746f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    // the list of Folders.
747f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    String msg = "item: " + item + " container being set to: " +
748f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                            item.container + ", not in the list of folders";
749f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    Log.e(TAG, msg);
750f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
751f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
752f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
753f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // Items are added/removed from the corresponding FolderInfo elsewhere, such
754f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // as in Workspace.onDrop. Here, we just add/remove them from the list of items
755f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // that are on the desktop, as appropriate
756f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            ItemInfo modelItem = sBgItemsIdMap.get(itemId);
75733231f587e1a6f716af68e6198df774d2847a8e5Winson Chung            if (modelItem != null &&
75833231f587e1a6f716af68e6198df774d2847a8e5Winson Chung                    (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
75933231f587e1a6f716af68e6198df774d2847a8e5Winson Chung                     modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
760f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                switch (modelItem.itemType) {
761f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
762f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
763f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
764f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        if (!sBgWorkspaceItems.contains(modelItem)) {
765f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                            sBgWorkspaceItems.add(modelItem);
766f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        }
767f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        break;
768f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    default:
769f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        break;
770f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                }
771f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            } else {
772f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                sBgWorkspaceItems.remove(modelItem);
773f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
774f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        }
775f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
776f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
7779c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
7789c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Move an item in the DB to a new <container, screen, cellX, cellY>
7799c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
78083a8f042adda926489494dff217c15ab696139b4Sunny Goyal    public static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
781dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final long screenId, final int cellX, final int cellY) {
7829c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.container = container;
7839c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellX = cellX;
7849c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellY = cellY;
785c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
7863d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // We store hotseat items in canonical form which is this orientation invariant position
7873d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // in the hotseat
788dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
7893d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
790dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
7913d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        } else {
792dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
7933d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        }
79431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
7959c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentValues values = new ContentValues();
7969c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
7973d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
7983d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
79908f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal        values.put(LauncherSettings.Favorites.RANK, item.rank);
800dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
801ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
802c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        updateItemInDatabaseHelper(context, values, item, "moveItemInDatabase");
80331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
80431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
80531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
806f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the
807f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     * cellX, cellY have already been updated on the ItemInfos.
808f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen     */
809f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,
810f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final long container, final int screen) {
811f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
812f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();
813f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        int count = items.size();
814f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
815f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        for (int i = 0; i < count; i++) {
816f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            ItemInfo item = items.get(i);
817f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            item.container = container;
818f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
819f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // We store hotseat items in canonical form which is this orientation invariant position
820f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            // in the hotseat
821f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            if (context instanceof Launcher && screen < 0 &&
822f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                    container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
823dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(item.cellX,
824f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen                        item.cellY);
825f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            } else {
826dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                item.screenId = screen;
827f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            }
828f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
829f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            final ContentValues values = new ContentValues();
830f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CONTAINER, item.container);
831f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CELLX, item.cellX);
832f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            values.put(LauncherSettings.Favorites.CELLY, item.cellY);
83308f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal            values.put(LauncherSettings.Favorites.RANK, item.rank);
834dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
835f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
836f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen            contentValues.add(values);
837f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        }
838f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen        updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");
839f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    }
840f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen
841f0f4eda31841f41d892bf18847c1acdc45d2cd64Adam Cohen    /**
842bebf042666cffe52039b875a549a582abd78a431Adam Cohen     * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>
843d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen     */
844bebf042666cffe52039b875a549a582abd78a431Adam Cohen    static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,
845dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {
8460f84a604563037ea65883b99d30e7ff802d986c2Winson Chung        item.container = container;
847d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        item.cellX = cellX;
848d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        item.cellY = cellY;
849bebf042666cffe52039b875a549a582abd78a431Adam Cohen        item.spanX = spanX;
850bebf042666cffe52039b875a549a582abd78a431Adam Cohen        item.spanY = spanY;
851bebf042666cffe52039b875a549a582abd78a431Adam Cohen
852bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // We store hotseat items in canonical form which is this orientation invariant position
853bebf042666cffe52039b875a549a582abd78a431Adam Cohen        // in the hotseat
854dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
855bebf042666cffe52039b875a549a582abd78a431Adam Cohen                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
856dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
857bebf042666cffe52039b875a549a582abd78a431Adam Cohen        } else {
858dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
859bebf042666cffe52039b875a549a582abd78a431Adam Cohen        }
860d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
861d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        final ContentValues values = new ContentValues();
862d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen        values.put(LauncherSettings.Favorites.CONTAINER, item.container);
863bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.CELLX, item.cellX);
864bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.CELLY, item.cellY);
86508f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal        values.put(LauncherSettings.Favorites.RANK, item.rank);
866bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.SPANX, item.spanX);
867bebf042666cffe52039b875a549a582abd78a431Adam Cohen        values.put(LauncherSettings.Favorites.SPANY, item.spanY);
868dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
869d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
870816474f06b9bea400f4511fa35b63a7f18a54c54Michael Jurka        updateItemInDatabaseHelper(context, values, item, "modifyItemInDatabase");
871bebf042666cffe52039b875a549a582abd78a431Adam Cohen    }
872c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
873c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka    /**
874c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * Update an item to the database in a specified container.
875c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     */
87683a8f042adda926489494dff217c15ab696139b4Sunny Goyal    public static void updateItemInDatabase(Context context, final ItemInfo item) {
877c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ContentValues values = new ContentValues();
878ed13187a745866483139e2878037e1f8427ce567Kenny Guy        item.onAddToDatabase(context, values);
879c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase");
880d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    }
881d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen
882756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    private void assertWorkspaceLoaded() {
883639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal        if (LauncherAppState.isDogfoodBuild()) {
884639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal            synchronized (mLock) {
885639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                if (!mHasLoaderCompletedOnce ||
886639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        (mLoaderTask != null && mLoaderTask.mIsLoadingAndBindingWorkspace)) {
887639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    throw new RuntimeException("Trying to add shortcut while loader is running");
888639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                }
889639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal            }
890756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        }
891756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    }
892756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
893d4844c3e731b00547a31f23a00f8bd4a271e2b62Adam Cohen    /**
894756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * Returns true if the shortcuts already exists on the workspace. This must be called after
895756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * the workspace has been loaded. We identify a shortcut by its intent.
896bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project     */
897756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal    @Thunk boolean shortcutExists(Context context, Intent intent, UserHandleCompat user) {
898756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal        assertWorkspaceLoaded();
899dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal        final String intentWithPkg, intentWithoutPkg;
9002a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        if (intent.getComponent() != null) {
9012a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            // If component is not null, an intent with null package will produce
9022a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            // the same result and should also be a match.
9034e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            String packageName = intent.getComponent().getPackageName();
9042a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            if (intent.getPackage() != null) {
905dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithPkg = intent.toUri(0);
906dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithoutPkg = new Intent(intent).setPackage(null).toUri(0);
9072a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            } else {
908dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithPkg = new Intent(intent).setPackage(packageName).toUri(0);
909dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                intentWithoutPkg = intent.toUri(0);
9102a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal            }
9112a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        } else {
912dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal            intentWithPkg = intent.toUri(0);
913dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal            intentWithoutPkg = intent.toUri(0);
9142a6cf09be968f71f23d520f1dc3f339feb61b269Sunny Goyal        }
915756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
916756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        synchronized (sBgLock) {
917e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            for (ItemInfo item : sBgItemsIdMap) {
918756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                if (item instanceof ShortcutInfo) {
919756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    ShortcutInfo info = (ShortcutInfo) item;
9204e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    Intent targetIntent = info.promisedIntent == null
9214e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            ? info.intent : info.promisedIntent;
9224e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    if (targetIntent != null && info.user.equals(user)) {
9234e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        String s = targetIntent.toUri(0);
924dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                        if (intentWithPkg.equals(s) || intentWithoutPkg.equals(s)) {
925dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                            return true;
926dfde999ccd0db397c7e4610444bb3fb69f7aa183Sunny Goyal                        }
927756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                    }
928756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                }
929756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal            }
9309c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
931756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        return false;
932bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project    }
933bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project
934bc219c3c127cb74cf4fe578f05022b745da921b8The Android Open Source Project    /**
9359c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Find a folder in the db, creating the FolderInfo if necessary, and adding it to folderList.
93631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
937e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    FolderInfo getFolderById(Context context, LongArrayMap<FolderInfo> folderList, long id) {
9389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
9399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
9409c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                "_id=? and (itemType=? or itemType=?)",
9419c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                new String[] { String.valueOf(id),
942df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                        String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)}, null);
943f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
9449c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        try {
9459c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            if (c.moveToFirst()) {
9469c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
9479c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
9489c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
9499c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
9509c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
9519c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
9525d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                final int optionsIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.OPTIONS);
953f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
9549c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                FolderInfo folderInfo = null;
9559c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                switch (c.getInt(itemTypeIndex)) {
956df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                    case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
957df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen                        folderInfo = findOrMakeFolder(folderList, id);
9589c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        break;
9599c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
96031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
961a508e4f804c2bddf9e2cdfa3d0bd4a8202ff2151Sunny Goyal                // Do not trim the folder label, as is was set by the user.
962a508e4f804c2bddf9e2cdfa3d0bd4a8202ff2151Sunny Goyal                folderInfo.title = c.getString(titleIndex);
9639c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                folderInfo.id = id;
9649c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                folderInfo.container = c.getInt(containerIndex);
965dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                folderInfo.screenId = c.getInt(screenIndex);
966d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen                folderInfo.cellX = c.getInt(cellXIndex);
967d22015cd37ea6ef53762eca5be57daca123ff607Adam Cohen                folderInfo.cellY = c.getInt(cellYIndex);
9685d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                folderInfo.options = c.getInt(optionsIndex);
969ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
9709c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                return folderInfo;
9719c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
9729c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        } finally {
9739c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            c.close();
9742fcbd686d1c2a9a9e520116a541c9caae0c2dc60Romain Guy        }
975ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
9769c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        return null;
9779c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
97831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
9799c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
9809c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Add an item to the database in a specified container. Sets the container, screen, cellX and
9819c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * cellY fields of the item. Also assigns an ID to the item.
9829c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
98318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public static void addItemToDatabase(Context context, final ItemInfo item, final long container,
9841d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal            final long screenId, final int cellX, final int cellY) {
9859c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.container = container;
9869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellX = cellX;
9879c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        item.cellY = cellY;
9883d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // We store hotseat items in canonical form which is this orientation invariant position
9893d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        // in the hotseat
990dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        if (context instanceof Launcher && screenId < 0 &&
9913d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung                container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
992dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = ((Launcher) context).getHotseat().getOrderInHotseat(cellX, cellY);
9933d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        } else {
994dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            item.screenId = screenId;
9953d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        }
996ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
9979c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentValues values = new ContentValues();
9989c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
999ed13187a745866483139e2878037e1f8427ce567Kenny Guy        item.onAddToDatabase(context, values);
1000ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
1001414300a79d140f8c2c8760d9adab750f69ffeafdMichael Jurka        item.id = LauncherAppState.getLauncherProvider().generateNewItemId();
1002a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka        values.put(LauncherSettings.Favorites._ID, item.id);
1003aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
10048e19cf22a4ab86f982b08e7d10b86ea7be56acccJason Monk        final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
1005c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
1006a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            public void run() {
10071d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.insert(LauncherSettings.Favorites.CONTENT_URI, values);
1008ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project
1009b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
10102abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
10118e19cf22a4ab86f982b08e7d10b86ea7be56acccJason Monk                    checkItemInfoLocked(item.id, item, stackTrace);
1012b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgItemsIdMap.put(item.id, item);
1013b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    switch (item.itemType) {
1014b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
1015b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            sBgFolders.put(item.id, (FolderInfo) item);
1016b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            // Fall through
1017b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1018b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1019b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
1020b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
1021b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgWorkspaceItems.add(item);
1022b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            } else {
1023b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                if (!sBgFolders.containsKey(item.container)) {
1024b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // Adding an item to a folder that doesn't exist.
1025b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    String msg = "adding item: " + item + " to a folder that " +
1026b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            " doesn't exist";
102728b3e10fdea4d719b46d2e0da9a916bacc238fd1Adam Cohen                                    Log.e(TAG, msg);
1028b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
1029487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen                            }
1030b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            break;
1031b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1032b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            sBgAppWidgets.add((LauncherAppWidgetInfo) item);
1033b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            break;
1034b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
1035a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka                }
1036a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            }
1037c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
1038b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
103931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
104031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
10419c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
1042aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     * Creates a new unique child id, for a given cell span across all layouts.
1043aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung     */
1044845ba3b17b83a2b11d79c6fb076cf96ab4a737dfMichael Jurka    static int getCellLayoutChildId(
1045dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long container, long screen, int localCellX, int localCellY, int spanX, int spanY) {
10463d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung        return (((int) container & 0xFF) << 24)
1047dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                | ((int) screen & 0xFF) << 16 | (localCellX & 0xFF) << 8 | (localCellY & 0xFF);
1048aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung    }
1049aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
1050349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    private static ArrayList<ItemInfo> getItemsByPackageName(
1051349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            final String pn, final UserHandleCompat user) {
1052e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        ItemInfoFilter filter  = new ItemInfoFilter() {
1053e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            @Override
1054e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
1055e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                return cn.getPackageName().equals(pn) && info.user.equals(user);
1056e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            }
1057e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        };
1058e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal        return filterItemInfos(sBgItemsIdMap, filter);
1059349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    }
1060349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
1061349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    /**
1062349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     * Removes all the items from the database corresponding to the specified package.
1063349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal     */
1064349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    static void deletePackageFromDatabase(Context context, final String pn,
1065349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            final UserHandleCompat user) {
1066349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        deleteItemsFromDatabase(context, getItemsByPackageName(pn, user));
1067e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
1068e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
1069e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    /**
1070c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * Removes the specified item from the database
1071c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * @param context
1072c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka     * @param item
10739c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
1074fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal    public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
1075e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
1076e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        items.add(item);
1077e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        deleteItemsFromDatabase(context, items);
1078e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
1079e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
1080e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    /**
1081e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     * Removes the specified items from the database
1082e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     * @param context
1083e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     * @param item
1084e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal     */
10854390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal    static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
10869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
108783df188ce0822f4058406e5f2878d1cf34bf413eMichael Jurka        Runnable r = new Runnable() {
1088a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            public void run() {
1089e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                for (ItemInfo item : items) {
10901d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    final Uri uri = LauncherSettings.Favorites.getContentUri(item.id);
1091e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    cr.delete(uri, null, null);
1092b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1093e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    // Lock on mBgLock *after* the db operation
1094e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                    synchronized (sBgLock) {
1095e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        switch (item.itemType) {
1096e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
1097e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgFolders.remove(item.id);
1098e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                                for (ItemInfo info: sBgItemsIdMap) {
1099e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                    if (info.container == item.id) {
1100e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        // We are deleting a folder which still contains items that
1101e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        // think they are contained by that folder.
1102e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        String msg = "deleting a folder (" + item + ") which still " +
1103e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                                "contains items (" + info + ")";
1104e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                        Log.e(TAG, msg);
1105e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                    }
1106b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
1107e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgWorkspaceItems.remove(item);
1108e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1109e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1110e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1111e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgWorkspaceItems.remove(item);
1112e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1113e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
1114e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                sBgAppWidgets.remove((LauncherAppWidgetInfo) item);
1115e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                                break;
1116e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        }
1117e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                        sBgItemsIdMap.remove(item.id);
1118b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
1119a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka                }
1120a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            }
112183df188ce0822f4058406e5f2878d1cf34bf413eMichael Jurka        };
1122b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
112331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
112431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
11259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
1126dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     * Update the order of the workspace screens in the database. The array list contains
1127dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     * a list of screen ids in the order that they should appear.
1128dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen     */
1129e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal    public void updateWorkspaceScreenOrder(Context context, final ArrayList<Long> screens) {
113064359a53dc827797917a8d9a0697a91996789801Winson Chung        final ArrayList<Long> screensCopy = new ArrayList<Long>(screens);
1131dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        final ContentResolver cr = context.getContentResolver();
1132dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        final Uri uri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
1133dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1134dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        // Remove any negative screen ids -- these aren't persisted
113564359a53dc827797917a8d9a0697a91996789801Winson Chung        Iterator<Long> iter = screensCopy.iterator();
1136dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        while (iter.hasNext()) {
1137dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long id = iter.next();
1138dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            if (id < 0) {
1139dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                iter.remove();
1140dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            }
1141dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        }
1142dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1143dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        Runnable r = new Runnable() {
1144dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            @Override
1145dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            public void run() {
1146085c853a5702c45865e9b017d21fa15cf2b151b9Yura                ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
1147dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                // Clear the table
1148085c853a5702c45865e9b017d21fa15cf2b151b9Yura                ops.add(ContentProviderOperation.newDelete(uri).build());
114976828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                int count = screensCopy.size();
1150dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                for (int i = 0; i < count; i++) {
1151dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    ContentValues v = new ContentValues();
115276828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                    long screenId = screensCopy.get(i);
1153dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    v.put(LauncherSettings.WorkspaceScreens._ID, screenId);
1154dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    v.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
1155085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    ops.add(ContentProviderOperation.newInsert(uri).withValues(v).build());
1156085c853a5702c45865e9b017d21fa15cf2b151b9Yura                }
1157085c853a5702c45865e9b017d21fa15cf2b151b9Yura
1158085c853a5702c45865e9b017d21fa15cf2b151b9Yura                try {
1159085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    cr.applyBatch(LauncherProvider.AUTHORITY, ops);
1160085c853a5702c45865e9b017d21fa15cf2b151b9Yura                } catch (Exception ex) {
1161085c853a5702c45865e9b017d21fa15cf2b151b9Yura                    throw new RuntimeException(ex);
1162dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
11639e6a0a20d40675ef98c7fdb8892cf34b90152f7aWinson Chung
1164ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                synchronized (sBgLock) {
1165ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    sBgWorkspaceScreens.clear();
1166ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    sBgWorkspaceScreens.addAll(screensCopy);
11674caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                }
1168dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            }
1169dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        };
1170dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        runOnWorkerThread(r);
1171dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    }
1172dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1173dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen    /**
11749c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Remove the contents of the specified folder from the database
11759c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
1176fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal    public static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
11779c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        final ContentResolver cr = context.getContentResolver();
1178f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1179c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        Runnable r = new Runnable() {
1180c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            public void run() {
11811d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
1182b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
11832abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
1184b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgItemsIdMap.remove(info.id);
1185b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgFolders.remove(info.id);
1186b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sBgWorkspaceItems.remove(info);
1187b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1188c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka
11891d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                cr.delete(LauncherSettings.Favorites.CONTENT_URI,
1190c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka                        LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
1191b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Lock on mBgLock *after* the db operation
11922abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                synchronized (sBgLock) {
1193b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    for (ItemInfo childInfo : info.contents) {
1194b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        sBgItemsIdMap.remove(childInfo.id);
1195b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
1196afb01ee74243cede19088e694ca82cea5983c603Adam Cohen                }
1197c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            }
1198c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        };
1199b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        runOnWorkerThread(r);
12009c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
1201f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
12029c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
12039c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Set this as the current Launcher activity object for the loader.
12049c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
12059c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    public void initialize(Callbacks callbacks) {
12069c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        synchronized (mLock) {
1207d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            // Disconnect any of the callbacks and drawables associated with ItemInfos on the
1208d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            // workspace to prevent leaking Launcher activities on orientation change.
1209d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            unbindItemInfosAndClearQueuedBindRunnables();
12109c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            mCallbacks = new WeakReference<Callbacks>(callbacks);
1211f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
1212f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
1213f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1214ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1215c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageChanged(String packageName, UserHandleCompat user) {
1216ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_UPDATE;
1217ed13187a745866483139e2878037e1f8427ce567Kenny Guy        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
1218ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1219ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1220ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1221ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1222c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageRemoved(String packageName, UserHandleCompat user) {
1223ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_REMOVE;
1224ed13187a745866483139e2878037e1f8427ce567Kenny Guy        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
1225ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1226ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1227ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1228ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1229c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackageAdded(String packageName, UserHandleCompat user) {
1230ed13187a745866483139e2878037e1f8427ce567Kenny Guy        int op = PackageUpdatedTask.OP_ADD;
1231ed13187a745866483139e2878037e1f8427ce567Kenny Guy        enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName },
1232ed13187a745866483139e2878037e1f8427ce567Kenny Guy                user));
1233ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1234ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1235ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1236c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackagesAvailable(String[] packageNames, UserHandleCompat user,
1237ed13187a745866483139e2878037e1f8427ce567Kenny Guy            boolean replacing) {
1238ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!replacing) {
1239ed13187a745866483139e2878037e1f8427ce567Kenny Guy            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packageNames,
1240ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    user));
1241ed13187a745866483139e2878037e1f8427ce567Kenny Guy            if (mAppsCanBeOnRemoveableStorage) {
1242ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Only rebind if we support removable storage. It catches the
1243ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // case where
1244ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // apps on the external sd card need to be reloaded
1245ed13187a745866483139e2878037e1f8427ce567Kenny Guy                startLoaderFromBackground();
1246ed13187a745866483139e2878037e1f8427ce567Kenny Guy            }
1247ed13187a745866483139e2878037e1f8427ce567Kenny Guy        } else {
1248ed13187a745866483139e2878037e1f8427ce567Kenny Guy            // If we are replacing then just update the packages in the list
1249ed13187a745866483139e2878037e1f8427ce567Kenny Guy            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,
1250ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    packageNames, user));
1251ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
1252ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1253ed13187a745866483139e2878037e1f8427ce567Kenny Guy
1254ed13187a745866483139e2878037e1f8427ce567Kenny Guy    @Override
1255c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy    public void onPackagesUnavailable(String[] packageNames, UserHandleCompat user,
1256ed13187a745866483139e2878037e1f8427ce567Kenny Guy            boolean replacing) {
1257ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!replacing) {
1258ed13187a745866483139e2878037e1f8427ce567Kenny Guy            enqueuePackageUpdated(new PackageUpdatedTask(
1259ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    PackageUpdatedTask.OP_UNAVAILABLE, packageNames,
1260ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    user));
1261ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
1262ed13187a745866483139e2878037e1f8427ce567Kenny Guy    }
1263ed13187a745866483139e2878037e1f8427ce567Kenny Guy
12641d8e7bbe09e130af5e9534cc26a65f623be7a424Joe Onorato    /**
12659c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
12669c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * ACTION_PACKAGE_CHANGED.
12679c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
1268cb1a4778686a46c46d8dc88b6c83674f6fac6592Narayan Kamath    @Override
1269f99f8c1ad265cf7bea7e30476911d730b7d0eaaeJoe Onorato    public void onReceive(Context context, Intent intent) {
1270b358f813c93ac0d6c4f31058947efd16b188cd1eChris Wren        if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
1271aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung
12723611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        final String action = intent.getAction();
1273ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
127493f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // If we have changed locale we need to clear out the labels in all apps/workspace.
127593f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            forceReload();
127688fa741e50760f9da78cba4a766172f23773bb87Winson Chung        } else if (SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED.equals(action)) {
1277e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            Callbacks callbacks = getCallback();
1278e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (callbacks != null) {
127988fa741e50760f9da78cba4a766172f23773bb87Winson Chung                callbacks.bindSearchProviderChanged();
1280cfdf7ee64db8820d91a1cd82bf7b961fb2083dceWinson Chung            }
1281957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal        } else if (LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED.equals(action)
1282957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal                || LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
1283823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyal            UserManagerCompat.getInstance(context).enableAndResetCache();
1284957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal            forceReload();
1285e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        }
1286e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    }
1287e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato
12886cc806d678c8a44478308119c087ac9adde73b66Amith Yamasani    void forceReload() {
1289f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        resetLoadedState(true, true);
1290f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
1291f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // Do this here because if the launcher activity is running it will be restarted.
1292f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // If it's not running startLoaderFromBackground will merely tell it that it needs
1293f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        // to reload.
1294f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung        startLoaderFromBackground();
1295f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung    }
1296f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung
1297f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung    public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {
129893f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        synchronized (mLock) {
129993f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // Stop any existing loaders first, so they don't set mAllAppsLoaded or
130093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            // mWorkspaceLoaded to true later
130193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            stopLoaderLocked();
1302f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung            if (resetAllAppsLoaded) mAllAppsLoaded = false;
1303f0c6ae0e35d3e020db55b5b826955da66b14b7f6Winson Chung            if (resetWorkspaceLoaded) mWorkspaceLoaded = false;
130493f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        }
130593f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee    }
130693f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee
1307e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    /**
1308e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * When the launcher is in the background, it's possible for it to miss paired
1309e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * configuration changes.  So whenever we trigger the loader from the background
1310e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * tell the launcher that it needs to re-run the loader when it comes back instead
1311e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     * of doing it now.
1312e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato     */
1313e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato    public void startLoaderFromBackground() {
1314e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        boolean runLoader = false;
1315e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        Callbacks callbacks = getCallback();
1316e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        if (callbacks != null) {
1317e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            // Only actually run the loader if they're not paused.
1318e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            if (!callbacks.setLoadOnResume()) {
1319e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                runLoader = true;
1320e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato            }
1321e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        }
1322e9ad59eba6d8ffd2cbf28520c237ccefd291a33cJoe Onorato        if (runLoader) {
13232bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal            startLoader(PagedView.INVALID_RESTORE_PAGE);
1324f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
13253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
1326f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
13272bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    /**
13282bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal     * If there is already a loader task running, tell it to stop.
13292bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal     */
13302bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    private void stopLoaderLocked() {
133193f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        LoaderTask oldTask = mLoaderTask;
133293f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        if (oldTask != null) {
133393f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee            oldTask.stopLocked();
133493f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee        }
133593f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee    }
133693f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee
13371a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen    public boolean isCurrentCallbacks(Callbacks callbacks) {
13381a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen        return (mCallbacks != null && mCallbacks.get() == callbacks);
13391a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen    }
13401a85c5839c91942b3c7dd0da5992db4d98defdc3Adam Cohen
13412bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    public void startLoader(int synchronousBindPage) {
13422bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal        startLoader(synchronousBindPage, LOADER_FLAG_NONE);
1343d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler    }
1344d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler
13452bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal    public void startLoader(int synchronousBindPage, int loadFlags) {
1346756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        // Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
1347756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        InstallShortcutReceiver.enableInstallQueue();
13483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        synchronized (mLock) {
1349b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Clear any deferred bind-runnables from the synchronized load process
1350b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // We must do this before any loading/binding is scheduled below.
1351a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            synchronized (mDeferredBindRunnables) {
1352a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                mDeferredBindRunnables.clear();
1353a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            }
1354b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
13553611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Don't bother to start the thread if we know it's not going to do anything
13563611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (mCallbacks != null && mCallbacks.get() != null) {
13573611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // If there is already one running, tell it to stop.
13582bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal                stopLoaderLocked();
13592bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal                mLoaderTask = new LoaderTask(mApp.getContext(), loadFlags);
13607aff399974c756930070d82d7b2df88f125dacd6Derek Prothro                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
1361f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                        && mAllAppsLoaded && mWorkspaceLoaded && !mIsLoaderTaskRunning) {
1362b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
1363b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
1364b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
1365b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    sWorker.post(mLoaderTask);
1366b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1367b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1368b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
1369b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    }
1370b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1371b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung    void bindRemainingSynchronousPages() {
1372b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        // Post the remaining side pages to be loaded
1373b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        if (!mDeferredBindRunnables.isEmpty()) {
1374a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            Runnable[] deferredBindRunnables = null;
1375a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            synchronized (mDeferredBindRunnables) {
1376a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                deferredBindRunnables = mDeferredBindRunnables.toArray(
1377a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                        new Runnable[mDeferredBindRunnables.size()]);
1378a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                mDeferredBindRunnables.clear();
1379a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            }
1380a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            for (final Runnable r : deferredBindRunnables) {
1381d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                mHandler.post(r);
1382b132a97cb7ee976bc54370fd0d5899876eaaf33aRomain Guy            }
1383b132a97cb7ee976bc54370fd0d5899876eaaf33aRomain Guy        }
13843611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
1385b132a97cb7ee976bc54370fd0d5899876eaaf33aRomain Guy
13863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    public void stopLoader() {
13873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        synchronized (mLock) {
13883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (mLoaderTask != null) {
13893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mLoaderTask.stopLocked();
13909c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
1391f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project        }
13923611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
1393b132a97cb7ee976bc54370fd0d5899876eaaf33aRomain Guy
1394c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal    /**
1395c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal     * Loads the workspace screen ids in an ordered list.
1396c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal     */
1397e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal    public static ArrayList<Long> loadWorkspaceScreensDb(Context context) {
139876828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        final ContentResolver contentResolver = context.getContentResolver();
139976828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        final Uri screensUri = LauncherSettings.WorkspaceScreens.CONTENT_URI;
140076828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
1401c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal        // Get screens ordered by rank.
1402c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal        final Cursor sc = contentResolver.query(screensUri, null, null, null,
1403c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                LauncherSettings.WorkspaceScreens.SCREEN_RANK);
1404c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal        ArrayList<Long> screenIds = new ArrayList<Long>();
140576828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        try {
1406c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal            final int idIndex = sc.getColumnIndexOrThrow(LauncherSettings.WorkspaceScreens._ID);
140776828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung            while (sc.moveToNext()) {
140876828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                try {
1409c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                    screenIds.add(sc.getLong(idIndex));
141076828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                } catch (Exception e) {
1411c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                    Launcher.addDumpLog(TAG, "Desktop items loading interrupted"
1412c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal                            + " - invalid screens: " + e, true);
141376828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung                }
141476828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung            }
141576828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        } finally {
141676828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung            sc.close();
141776828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung        }
1418c1b7c2ecbdcf6b16e36fd8ad843d017f0eaac594Sunny Goyal        return screenIds;
141976828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung    }
142076828c87ddb50ee3b423ef26f36387a2f03fd562Winson Chung
1421c57b7a8233d32c6dd8de5057c570afe3f50e3ef2Michael Jurka    public boolean isAllAppsLoaded() {
1422c57b7a8233d32c6dd8de5057c570afe3f50e3ef2Michael Jurka        return mAllAppsLoaded;
1423c57b7a8233d32c6dd8de5057c570afe3f50e3ef2Michael Jurka    }
1424c57b7a8233d32c6dd8de5057c570afe3f50e3ef2Michael Jurka
14253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    /**
14263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     * Runnable for the thread that loads the contents of the launcher:
14273611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - workspace icons
14283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - widgets
14293611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     *   - all apps icons
14303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato     */
14313611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private class LoaderTask implements Runnable {
14323611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private Context mContext;
1433091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen        @Thunk boolean mIsLoadingAndBindingWorkspace;
14343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private boolean mStopped;
1435091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen        @Thunk boolean mLoadAndBindStepFinished;
1436d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler        private int mFlags;
1437b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
14382bba4c37c6402dfdc965d0c412c840c57993c7ddSunny Goyal        LoaderTask(Context context, int flags) {
14393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mContext = context;
1440d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            mFlags = flags;
14413611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1442f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
144366cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void loadAndBindWorkspace() {
144436a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung            mIsLoadingAndBindingWorkspace = true;
144536a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung
14463611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Load the workspace
14473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
14483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
14493611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1450288a36b563801a26d00084cb823435a3ba4cb76cMichael Jurka
1451a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka            if (!mWorkspaceLoaded) {
145266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                loadWorkspace();
145393f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                synchronized (LoaderTask.this) {
145493f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    if (mStopped) {
145566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        return;
145693f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    }
145793f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    mWorkspaceLoaded = true;
14589c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
14593611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1460cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato
14613611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Bind the workspace
146266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal            bindWorkspace(-1);
14633611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1464f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
14653611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void waitForIdle() {
14663611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Wait until the either we're stopped or the other threads are done.
14673611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // This way we don't start loading all apps until the workspace has settled
14683611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // down.
14693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (LoaderTask.this) {
14703611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
1471843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
14723611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.postIdle(new Runnable() {
14733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        public void run() {
14743611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            synchronized (LoaderTask.this) {
14753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                mLoadAndBindStepFinished = true;
14763611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                if (DEBUG_LOADERS) {
14773611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                    Log.d(TAG, "done with previous binding step");
14789c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
14793611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                LoaderTask.this.notify();
14809c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                            }
14819c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
14823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    });
14833611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
148471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal                while (!mStopped && !mLoadAndBindStepFinished) {
14853611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    try {
1486c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        // Just in case mFlushingWorkerThread changes but we aren't woken up,
1487c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        // wait no longer than 1sec at a time
1488c7700af21f7b1df939fce22f4ab5072b3ea29b66Michael Jurka                        this.wait(1000);
14893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    } catch (InterruptedException ex) {
14903611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        // Ignore
14919c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
14923611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
14933611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (DEBUG_LOADERS) {
14943611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Log.d(TAG, "waited "
1495aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                            + (SystemClock.uptimeMillis()-workspaceWaitTime)
14963611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            + "ms for previous step to finish binding");
14979c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
1498843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler            }
14993611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1500f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1501b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        void runBindSynchronousPage(int synchronousBindPage) {
15027aff399974c756930070d82d7b2df88f125dacd6Derek Prothro            if (synchronousBindPage == PagedView.INVALID_RESTORE_PAGE) {
1503b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Ensure that we have a valid page index to load synchronously
1504b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                throw new RuntimeException("Should not call runBindSynchronousPage() without " +
1505b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        "valid page index");
1506b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1507b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            if (!mAllAppsLoaded || !mWorkspaceLoaded) {
1508b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Ensure that we don't try and bind a specified page when the pages have not been
1509b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // loaded already (we should load everything asynchronously in that case)
1510b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                throw new RuntimeException("Expecting AllApps and Workspace to be loaded");
1511b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1512b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            synchronized (mLock) {
1513b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (mIsLoaderTaskRunning) {
1514b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // Ensure that we are never running the background loading at this point since
1515b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // we also touch the background collections
1516b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    throw new RuntimeException("Error! Background loading is already running");
1517b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
1518b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
1519b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1520b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // XXX: Throw an exception if we are already loading (since we touch the worker thread
1521b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      data structures, we can't allow any other thread to touch that data, but because
1522b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      this call is synchronous, we can get away with not locking).
1523b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1524cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            // The LauncherModel is static in the LauncherAppState and mHandler may have queued
1525a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            // operations from the previous activity.  We need to ensure that all queued operations
1526a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            // are executed before any synchronous binding work is done.
1527a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen            mHandler.flush();
1528a13a2f2a7bd0550d1ad973f760ff25e1a4137c43Adam Cohen
1529b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Divide the set of loaded items into those that we are binding synchronously, and
1530b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // everything else that is to be bound normally (asynchronously).
153166cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal            bindWorkspace(synchronousBindPage);
1532b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // XXX: For now, continue posting the binding of AllApps as there are other issues that
1533b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            //      arise from that.
1534b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            onlyBindAllApps();
1535b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
1536b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
15373611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void run() {
1538b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            synchronized (mLock) {
1539f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                if (mStopped) {
1540f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    return;
1541f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                }
1542b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                mIsLoaderTaskRunning = true;
1543b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
15443611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Optimize for end-user experience: if the Launcher is up and // running with the
15453611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
15463611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // workspace first (default).
15473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            keep_running: {
154864359a53dc827797917a8d9a0697a91996789801Winson Chung                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
154966cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                loadAndBindWorkspace();
1550843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
15513611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mStopped) {
15523611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break keep_running;
15533611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
15543611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
15553611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                waitForIdle();
1556f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1557843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler                // second step
155864359a53dc827797917a8d9a0697a91996789801Winson Chung                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
155964359a53dc827797917a8d9a0697a91996789801Winson Chung                loadAndBindAllApps();
15603611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1561843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler
15623611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // Clear out this reference, otherwise we end up holding it until all of the
15633611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // callback runnables are done.
15643611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mContext = null;
1565f3d5ea926d4dd1a739b9d3816543728af723cc26Joe Onorato
15663611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (mLock) {
15673611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // If we are still the last one to be scheduled, remove ourselves.
15683611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mLoaderTask == this) {
15693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    mLoaderTask = null;
1570843e860e8ebab96ff70988f2829fac38afd9d937Daniel Sandler                }
1571b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                mIsLoaderTaskRunning = false;
1572756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                mHasLoaderCompletedOnce = true;
15733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
15743611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1575f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15763611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void stopLocked() {
15773611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (LoaderTask.this) {
15783611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mStopped = true;
15793611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                this.notify();
1580f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
15813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1582f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
15833611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        /**
15843611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * Gets the callbacks object.  If we've been stopped, or if the launcher object
15853611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * has somehow been garbage collected, return null instead.  Pass in the Callbacks
15863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * object that was around when the deferred message was scheduled, and if there's
15873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * a new Callbacks object around then also return null.  This will save us from
15883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         * calling onto it with data that will be ignored.
15893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato         */
15903611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
15913611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            synchronized (mLock) {
15923611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mStopped) {
15933611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15943611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
1595ac03330c9684f98b4dd067a87ca70d3e0be1cfedJoe Onorato
15963611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (mCallbacks == null) {
15973611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
15983611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
1599f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
16003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final Callbacks callbacks = mCallbacks.get();
16013611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (callbacks != oldCallbacks) {
16023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
16033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
16043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                if (callbacks == null) {
16053611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Log.w(TAG, "no mCallbacks");
16063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    return null;
16079c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
16083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
16093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return callbacks;
1610f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project            }
16113611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
1612f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
16133611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        // check & update map of what's occupied; used to discard overlapping/invalid items
161441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal        private boolean checkItemPlacement(LongArrayMap<ItemInfo[][]> occupied, ItemInfo item,
161541cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                   ArrayList<Long> workspaceScreens) {
1616892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            LauncherAppState app = LauncherAppState.getInstance();
16172e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
161841cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            final int countX = profile.numColumns;
161941cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            final int countY = profile.numRows;
1620892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung
1621dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            long containerIndex = item.screenId;
1622f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung            if (item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
1623a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                // Return early if we detect that an item is under the hotseat button
1624a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                if (mCallbacks == null ||
1625a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                        mCallbacks.get().isAllAppsButtonRank((int) item.screenId)) {
1626295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                    Log.e(TAG, "Error loading shortcut into hotseat " + item
1627295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                            + " into position (" + item.screenId + ":" + item.cellX + ","
1628295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                            + item.cellY + ") occupied by all apps");
1629a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                    return false;
1630a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung                }
1631a0b7e86299ed9baf278e0c1ed73f4a4f6a057322Winson Chung
1632295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                final ItemInfo[][] hotseatItems =
1633295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                        occupied.get((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT);
1634295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler
16352e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                if (item.screenId >= profile.numHotseatIcons) {
1636ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    Log.e(TAG, "Error loading shortcut " + item
1637ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                            + " into hotseat position " + item.screenId
16382e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                            + ", position out of bounds: (0 to " + (profile.numHotseatIcons - 1)
1639ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                            + ")");
1640ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    return false;
1641ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                }
1642ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
1643295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                if (hotseatItems != null) {
1644295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                    if (hotseatItems[(int) item.screenId][0] != null) {
1645dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        Log.e(TAG, "Error loading shortcut into hotseat " + item
1646dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                + " into position (" + item.screenId + ":" + item.cellX + ","
1647dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                + item.cellY + ") occupied by "
1648dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                + occupied.get(LauncherSettings.Favorites.CONTAINER_HOTSEAT)
1649dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                [(int) item.screenId][0]);
1650dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                            return false;
1651295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                    } else {
1652295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                        hotseatItems[(int) item.screenId][0] = item;
1653295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                        return true;
1654dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
16556ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                } else {
16562e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                    final ItemInfo[][] items = new ItemInfo[(int) profile.numHotseatIcons][1];
1657dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    items[(int) item.screenId][0] = item;
1658dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    occupied.put((long) LauncherSettings.Favorites.CONTAINER_HOTSEAT, items);
16596ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                    return true;
16606ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung                }
166141cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            } else if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
166241cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                if (!workspaceScreens.contains((Long) item.screenId)) {
166341cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                    // The item has an invalid screen id.
166441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                    return false;
166541cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                }
166641cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            } else {
1667f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung                // Skip further checking if it is not the hotseat or workspace container
16683611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return true;
16693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
1670f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung
1671dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            if (!occupied.containsKey(item.screenId)) {
1672892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung                ItemInfo[][] items = new ItemInfo[countX + 1][countY + 1];
1673dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                occupied.put(item.screenId, items);
1674dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            }
1675dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
1676295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler            final ItemInfo[][] screens = occupied.get(item.screenId);
1677ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen            if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
1678ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    item.cellX < 0 || item.cellY < 0 ||
1679ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                    item.cellX + item.spanX > countX || item.cellY + item.spanY > countY) {
1680ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                Log.e(TAG, "Error loading shortcut " + item
1681ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + " into cell (" + containerIndex + "-" + item.screenId + ":"
1682ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + item.cellX + "," + item.cellY
1683ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                        + ") out of screen bounds ( " + countX + "x" + countY + ")");
1684ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen                return false;
1685ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen            }
1686ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
16876ba2a1b6e7595a14ba33e98f728b39d0ecb3ae36Winson Chung            // Check if any workspace icons overlap with each other
16883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
16893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
1690dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    if (screens[x][y] != null) {
16913611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        Log.e(TAG, "Error loading shortcut " + item
1692dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                            + " into cell (" + containerIndex + "-" + item.screenId + ":"
16933611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            + x + "," + y
1694aafa03cbb925c74be1c13f8bb99d928be429e62fWinson Chung                            + ") occupied by "
1695dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                            + screens[x][y]);
16963611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        return false;
16978802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler                    }
16988802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler                }
16993611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
17003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
17013611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
1702dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    screens[x][y] = item;
17038802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler                }
17048802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler            }
1705f30ad5f1bf33baceeca6b770464fb543b58af985Winson Chung
17063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            return true;
17073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
17088802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler
1709ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        /** Clears all the sBg data structures */
1710ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        private void clearSBgDataStructures() {
1711ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung            synchronized (sBgLock) {
1712ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgWorkspaceItems.clear();
1713ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgAppWidgets.clear();
1714ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgFolders.clear();
1715ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgItemsIdMap.clear();
1716ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                sBgWorkspaceScreens.clear();
1717ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung            }
1718ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung        }
1719ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung
172066cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void loadWorkspace() {
17213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
1722f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
17233611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Context context = mContext;
17243611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final ContentResolver contentResolver = context.getContentResolver();
17253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final PackageManager manager = context.getPackageManager();
17263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final boolean isSafeMode = manager.isSafeMode();
1727f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
1728f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            final boolean isSdCardReady = context.registerReceiver(null,
172905e318d8f7d5ea615539d34b181ee44686f1f494Sunny Goyal                    new IntentFilter(StartupReceiver.SYSTEM_READY)) != null;
1730f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
1731892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            LauncherAppState app = LauncherAppState.getInstance();
17322e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
173341cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            int countX = profile.numColumns;
173441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal            int countY = profile.numRows;
1735892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung
17366579e1eee8a6fce44f020d40c3bbdbf245d6c12cSunny Goyal            if (MigrateFromRestoreTask.ENABLED && MigrateFromRestoreTask.shouldRunTask(mContext)) {
1737d934e0b0b7b60c9457fd0eb615355c16bac1a285Sunny Goyal                long migrationStartTime = System.currentTimeMillis();
1738d934e0b0b7b60c9457fd0eb615355c16bac1a285Sunny Goyal                Log.v(TAG, "Starting workspace migration after restore");
1739e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                try {
1740e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    MigrateFromRestoreTask task = new MigrateFromRestoreTask(mContext);
1741e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    // Clear the flags before starting the task, so that we do not run the task
1742e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    // again, in case there was an uncaught error.
1743e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    MigrateFromRestoreTask.clearFlags(mContext);
1744e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    task.execute();
1745e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                } catch (Exception e) {
1746e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    Log.e(TAG, "Error during grid migration", e);
1747e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal
1748e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    // Clear workspace.
1749e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                    mFlags = mFlags | LOADER_FLAG_CLEAR_WORKSPACE;
1750e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal                }
1751d934e0b0b7b60c9457fd0eb615355c16bac1a285Sunny Goyal                Log.v(TAG, "Workspace migration completed in "
1752d934e0b0b7b60c9457fd0eb615355c16bac1a285Sunny Goyal                        + (System.currentTimeMillis() - migrationStartTime));
1753e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal            }
1754e5bb705fb79f18df8680958dcf2c5460e16c90b6Sunny Goyal
1755d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
1756d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
1757d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                LauncherAppState.getLauncherProvider().deleteDatabase();
1758d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            }
1759d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler
1760d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {
1761d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                // append the user's Launcher2 shortcuts
1762d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);
1763d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();
1764d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            } else {
1765d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                // Make sure the default workspace is loaded
1766d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler                Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
17670fe505bf82a265e51c556d7204976651cde7f55cSunny Goyal                LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
1768d502404a44fb7c4ea739622d7f8bdd2a764d97a1Dan Sandler            }
1769e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen
17702abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            synchronized (sBgLock) {
1771ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                clearSBgDataStructures();
1772756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                final HashMap<String, Integer> installingPkgs = PackageInstallerCompat
17739448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                        .getInstance(mContext).updateAndGetActiveSessionCache();
177441cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
1775b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1776b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
1777f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                final ArrayList<Long> restoredRows = new ArrayList<Long>();
17781d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
1779e523e70f75ff90ca5d613fb8398d37208e6cd32dChris Wren                if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
1780e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen                final Cursor c = contentResolver.query(contentUri, null, null, null, null);
1781b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1782b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // +1 for the hotseat (it can be larger than the workspace)
1783b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // Load workspace in reverse order to ensure that latest items are loaded first (and
1784b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // before any earlier duplicates)
1785e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                final LongArrayMap<ItemInfo[][]> occupied = new LongArrayMap<>();
1786b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1787b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                try {
1788b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
1789b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int intentIndex = c.getColumnIndexOrThrow
1790b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.INTENT);
1791b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int titleIndex = c.getColumnIndexOrThrow
1792b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.TITLE);
1793b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int containerIndex = c.getColumnIndexOrThrow(
1794b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.CONTAINER);
1795b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int itemTypeIndex = c.getColumnIndexOrThrow(
1796b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.ITEM_TYPE);
1797b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int appWidgetIdIndex = c.getColumnIndexOrThrow(
1798b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.APPWIDGET_ID);
1799c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                    final int appWidgetProviderIndex = c.getColumnIndexOrThrow(
1800c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                            LauncherSettings.Favorites.APPWIDGET_PROVIDER);
1801b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int screenIndex = c.getColumnIndexOrThrow(
1802b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.SCREEN);
1803b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int cellXIndex = c.getColumnIndexOrThrow
1804b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.CELLX);
1805b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int cellYIndex = c.getColumnIndexOrThrow
1806b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.CELLY);
1807b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int spanXIndex = c.getColumnIndexOrThrow
1808b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            (LauncherSettings.Favorites.SPANX);
1809b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    final int spanYIndex = c.getColumnIndexOrThrow(
1810b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            LauncherSettings.Favorites.SPANY);
181108f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                    final int rankIndex = c.getColumnIndexOrThrow(
181208f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                            LauncherSettings.Favorites.RANK);
1813f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                    final int restoredIndex = c.getColumnIndexOrThrow(
1814f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                            LauncherSettings.Favorites.RESTORED);
1815ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    final int profileIdIndex = c.getColumnIndexOrThrow(
1816ed13187a745866483139e2878037e1f8427ce567Kenny Guy                            LauncherSettings.Favorites.PROFILE_ID);
18175d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                    final int optionsIndex = c.getColumnIndexOrThrow(
18185d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                            LauncherSettings.Favorites.OPTIONS);
18194e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    final CursorIconInfo cursorIconInfo = new CursorIconInfo(c);
1820b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
18217f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    final LongSparseArray<UserHandleCompat> allUsers = new LongSparseArray<>();
18227f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    for (UserHandleCompat user : mUserManager.getUserProfiles()) {
18237f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                        allUsers.put(mUserManager.getSerialNumberForUser(user), user);
18247f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                    }
18257f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal
1826b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    ShortcutInfo info;
1827b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    String intentDescription;
1828b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    LauncherAppWidgetInfo appWidgetInfo;
1829b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    int container;
1830b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    long id;
183126ace12135a662ad864678c9fede9817e5c02b67Robin Lee                    long serialNumber;
1832b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Intent intent;
1833ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    UserHandleCompat user;
1834b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1835b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    while (!mStopped && c.moveToNext()) {
1836b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        try {
1837b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            int itemType = c.getInt(itemTypeIndex);
1838f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                            boolean restored = 0 != c.getInt(restoredIndex);
1839f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                            boolean allowMissingTarget = false;
1840b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            container = c.getInt(containerIndex);
1841b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
1842b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            switch (itemType) {
1843b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
1844b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
1845ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                id = c.getLong(idIndex);
1846b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                intentDescription = c.getString(intentIndex);
184726ace12135a662ad864678c9fede9817e5c02b67Robin Lee                                serialNumber = c.getInt(profileIdIndex);
18487f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                user = allUsers.get(serialNumber);
1849349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                int promiseType = c.getInt(restoredIndex);
18501a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                int disabledState = 0;
1851bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                boolean itemReplaced = false;
1852ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                if (user == null) {
1853ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    // User has been deleted remove the item.
1854ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    itemsToRemove.add(id);
1855ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    continue;
1856ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                }
1857b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                try {
1858b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    intent = Intent.parseUri(intentDescription, 0);
1859ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    ComponentName cn = intent.getComponent();
1860f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                    if (cn != null && cn.getPackageName() != null) {
1861f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        boolean validPkg = launcherApps.isPackageEnabledForProfile(
1862f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                cn.getPackageName(), user);
1863f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        boolean validComponent = validPkg &&
1864f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                launcherApps.isActivityEnabledForProfile(cn, user);
1865f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
1866f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        if (validComponent) {
1867f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            if (restored) {
1868f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                // no special handling necessary for this item
1869f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                restoredRows.add(id);
1870f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                restored = false;
1871f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            }
1872f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        } else if (validPkg) {
1873349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            intent = null;
1874349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            if ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
1875349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // We allow auto install apps to have their intent
1876349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // updated after an install.
1877349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                intent = manager.getLaunchIntentForPackage(
1878349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                        cn.getPackageName());
1879349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                if (intent != null) {
1880349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                    ContentValues values = new ContentValues();
1881349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                    values.put(LauncherSettings.Favorites.INTENT,
1882349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                            intent.toUri(0));
1883bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    updateItem(id, values);
1884349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                }
1885349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            }
1886349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
1887349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            if (intent == null) {
1888349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // The app is installed but the component is no
1889349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // longer available.
1890349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                Launcher.addDumpLog(TAG,
1891349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                        "Invalid component removed: " + cn, true);
1892349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                itemsToRemove.add(id);
1893349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                continue;
1894349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            } else {
1895349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                // no special handling necessary for this item
1896349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                restoredRows.add(id);
1897349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                                restored = false;
1898349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                                            }
1899f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                        } else if (restored) {
1900f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // Package is not yet available but might be
1901f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // installed later.
1902f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                            Launcher.addDumpLog(TAG,
1903f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                                    "package not yet restored: " + cn, true);
19049448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal
19059448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            if ((promiseType & ShortcutInfo.FLAG_RESTORE_STARTED) != 0) {
19069448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                // Restore has started once.
1907756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            } else if (installingPkgs.containsKey(cn.getPackageName())) {
19089448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                // App restore has started. Update the flag
19099448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                promiseType |= ShortcutInfo.FLAG_RESTORE_STARTED;
19109448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                ContentValues values = new ContentValues();
19119448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                values.put(LauncherSettings.Favorites.RESTORED,
19129448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                        promiseType);
1913bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                updateItem(id, values);
1914bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                            } else if ((promiseType & ShortcutInfo.FLAG_RESTORED_APP_TYPE) != 0) {
1915bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                // This is a common app. Try to replace this.
1916bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                int appType = CommonAppTypeParser.decodeItemTypeFromFlag(promiseType);
1917bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                CommonAppTypeParser parser = new CommonAppTypeParser(id, appType, context);
1918bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                if (parser.findDefaultApp()) {
1919bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    // Default app found. Replace it.
1920bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    intent = parser.parsedIntent;
1921bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    cn = intent.getComponent();
1922bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    ContentValues values = parser.parsedValues;
1923bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    values.put(LauncherSettings.Favorites.RESTORED, 0);
1924bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    updateItem(id, values);
1925bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    restored = false;
1926bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    itemReplaced = true;
1927bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal
1928bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                } else if (REMOVE_UNRESTORED_ICONS) {
1929bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    Launcher.addDumpLog(TAG,
1930bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                            "Unrestored package removed: " + cn, true);
1931bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    itemsToRemove.add(id);
1932bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                    continue;
1933bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                                }
19349448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            } else if (REMOVE_UNRESTORED_ICONS) {
19359448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                Launcher.addDumpLog(TAG,
19369448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                        "Unrestored package removed: " + cn, true);
19379448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                itemsToRemove.add(id);
19389448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                continue;
19399448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            }
19401a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        } else if (launcherApps.isAppEnabled(
19411a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                                manager, cn.getPackageName(),
19421a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                                PackageManager.GET_UNINSTALLED_PACKAGES)) {
19431a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Package is present but not available.
19441a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            allowMissingTarget = true;
19451a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            disabledState = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
19461a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        } else if (!isSdCardReady) {
1947f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // SdCard is not ready yet. Package might get available,
1948f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // once it is ready.
1949f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            Launcher.addDumpLog(TAG, "Invalid package: " + cn
1950f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                    + " (check again later)", true);
1951f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            HashSet<String> pkgs = sPendingPackages.get(user);
1952f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            if (pkgs == null) {
1953513edaebce9846c2d5eb4c0c013a9dcf6232c0e3Sameer Padala                                                pkgs = new HashSet<String>();
1954f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                                sPendingPackages.put(user, pkgs);
1955f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                            }
1956f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            pkgs.add(cn.getPackageName());
1957f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            allowMissingTarget = true;
1958f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                            // Add the icon on the workspace anyway.
19591a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
19601a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        } else {
19611a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Do not wait for external media load anymore.
19621a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            // Log the invalid package, and remove it
19631a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            Launcher.addDumpLog(TAG,
19641a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                                    "Invalid package removed: " + cn, true);
19651a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            itemsToRemove.add(id);
19661a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                            continue;
1967ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                        }
1968938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                    } else if (cn == null) {
1969938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        // For shortcuts with no component, keep them as they are
1970938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        restoredRows.add(id);
1971938a53d8640ddec14b36b1e7ddc3e156824d9de0Sunny Goyal                                        restored = false;
1972ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    }
1973b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                } catch (URISyntaxException e) {
1974f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                    Launcher.addDumpLog(TAG,
1975f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                            "Invalid uri: " + intentDescription, true);
197641cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    itemsToRemove.add(id);
1977b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    continue;
1978b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
1979968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka
198034b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                                boolean useLowResIcon = container >= 0 &&
198134b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                                        c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
198234b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal
1983bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                if (itemReplaced) {
1984bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    if (user.equals(UserHandleCompat.myUserHandle())) {
19854fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                                        info = getAppShortcutInfo(manager, intent, user, context, null,
19864e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                                cursorIconInfo.iconIndex, titleIndex,
19874e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                                false, useLowResIcon);
1988bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    } else {
1989bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        // Don't replace items for other profiles.
1990bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        itemsToRemove.add(id);
1991bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                        continue;
1992bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                    }
1993bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                } else if (restored) {
1994ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    if (user.equals(UserHandleCompat.myUserHandle())) {
1995ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        Launcher.addDumpLog(TAG,
1996ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                                "constructing info for partially restored package",
1997ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                                true);
199834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal                                        info = getRestoredItemInfo(c, titleIndex, intent,
1999c22841bfd1961781a84cfccb98d1c2937a9adee4Sunny Goyal                                                promiseType, itemType, cursorIconInfo, context);
2000ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        intent = getRestoredItemIntent(c, context, intent);
2001ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    } else {
2002ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        // Don't restore items for other profiles.
2003ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        itemsToRemove.add(id);
2004ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                        continue;
2005ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    }
2006f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                } else if (itemType ==
2007f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                        LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
20084fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                                    info = getAppShortcutInfo(manager, intent, user, context, c,
20094e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                            cursorIconInfo.iconIndex, titleIndex,
20104e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                            allowMissingTarget, useLowResIcon);
2011b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                } else {
20124e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                    info = getShortcutInfo(c, context, titleIndex, cursorIconInfo);
2013b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2014b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // App shortcuts that used to be automatically added to Launcher
2015b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // didn't always have the correct intent flags set, so do that
2016b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // here
2017b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    if (intent.getAction() != null &&
20189ad005639e1698c94674cdfadf3ae342fb56c9b5Michael Jurka                                        intent.getCategories() != null &&
20199ad005639e1698c94674cdfadf3ae342fb56c9b5Michael Jurka                                        intent.getAction().equals(Intent.ACTION_MAIN) &&
2020968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka                                        intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)) {
2021b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        intent.addFlags(
2022b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            Intent.FLAG_ACTIVITY_NEW_TASK |
2023b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
2024b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2025968795679be0a3f0118d5a6e2e1580808da5716dMichael Jurka                                }
20263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
2027b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                if (info != null) {
2028ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung                                    info.id = id;
2029b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.intent = intent;
2030b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.container = container;
2031dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                    info.screenId = c.getInt(screenIndex);
2032b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.cellX = c.getInt(cellXIndex);
2033b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    info.cellY = c.getInt(cellYIndex);
203408f7261d11a53ae4b330ad4fa897b8519de3d750Sunny Goyal                                    info.rank = c.getInt(rankIndex);
20355f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                    info.spanX = 1;
20365f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                    info.spanY = 1;
2037ed13187a745866483139e2878037e1f8427ce567Kenny Guy                                    info.intent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
20384e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                    if (info.promisedIntent != null) {
20394e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                        info.promisedIntent.putExtra(ItemInfo.EXTRA_PROFILE, serialNumber);
20404e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                                    }
20411a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    info.isDisabled = disabledState;
20421a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    if (isSafeMode && !Utilities.isSystemApp(context, intent)) {
20431a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                        info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SAFEMODE;
20441a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    }
2045ae4409dea97d03f0f0a9195ab648188efa2b5cc1Adam Cohen
2046b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // check & update map of what's occupied
204741cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    if (!checkItemPlacement(occupied, info, sBgWorkspaceScreens)) {
2048fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                        itemsToRemove.add(id);
2049b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2050b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2051b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2052756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    if (restored) {
2053756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        ComponentName cn = info.getTargetComponent();
2054756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        if (cn != null) {
2055756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            Integer progress = installingPkgs.get(cn.getPackageName());
2056756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            if (progress != null) {
2057756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                info.setInstallProgress(progress);
2058756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            } else {
2059756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                info.status &= ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
2060756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                            }
2061756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        }
2062756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    }
2063756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
2064b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    switch (container) {
2065b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
2066b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
2067b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        sBgWorkspaceItems.add(info);
2068b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2069b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    default:
2070b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        // Item is in a user folder
2071b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        FolderInfo folderInfo =
2072b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                                findOrMakeFolder(sBgFolders, container);
2073b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        folderInfo.add(info);
2074b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2075b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2076b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgItemsIdMap.put(info.id, info);
20771323b4856a2a822af77293cadeda9910a5d1ba0eWinson Chung                                } else {
20781323b4856a2a822af77293cadeda9910a5d1ba0eWinson Chung                                    throw new RuntimeException("Unexpected null ShortcutInfo");
2079b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
2080b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                break;
2081b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2082b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
2083b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                id = c.getLong(idIndex);
2084b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                FolderInfo folderInfo = findOrMakeFolder(sBgFolders, id);
2085b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2086a508e4f804c2bddf9e2cdfa3d0bd4a8202ff2151Sunny Goyal                                // Do not trim the folder label, as is was set by the user.
2087a508e4f804c2bddf9e2cdfa3d0bd4a8202ff2151Sunny Goyal                                folderInfo.title = c.getString(titleIndex);
2088b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.id = id;
2089b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.container = container;
2090dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                folderInfo.screenId = c.getInt(screenIndex);
2091b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.cellX = c.getInt(cellXIndex);
2092b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                folderInfo.cellY = c.getInt(cellYIndex);
20935f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                folderInfo.spanX = 1;
20945f8afe6280eae34620067696173e71943e1a30a3Winson Chung                                folderInfo.spanY = 1;
20955d85c44fd873c740dc191b28424c2ee367d730a2Sunny Goyal                                folderInfo.options = c.getInt(optionsIndex);
20965f8afe6280eae34620067696173e71943e1a30a3Winson Chung
20973611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                // check & update map of what's occupied
209841cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                if (!checkItemPlacement(occupied, folderInfo, sBgWorkspaceScreens)) {
2099fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                    itemsToRemove.add(id);
21003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                    break;
21019c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
21025f8afe6280eae34620067696173e71943e1a30a3Winson Chung
21033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                switch (container) {
2104b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_DESKTOP:
2105b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    case LauncherSettings.Favorites.CONTAINER_HOTSEAT:
2106b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        sBgWorkspaceItems.add(folderInfo);
2107b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
21089c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                }
210917a8922e2ab2ad599df3750d398a095473ccd1b4Joe Onorato
2110f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                if (restored) {
2111f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                    // no special handling required for restored folders
2112f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                    restoredRows.add(id);
2113f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                                }
2114f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
2115b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgItemsIdMap.put(folderInfo.id, folderInfo);
2116b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                sBgFolders.put(folderInfo.id, folderInfo);
2117b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                break;
2118b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2119b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
21205940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                            case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
2121b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                // Read all Launcher-specific widget details
21225940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                boolean customWidget = itemType ==
21235940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                    LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
21245940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
2125b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                int appWidgetId = c.getInt(appWidgetIdIndex);
21267f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                serialNumber = c.getLong(profileIdIndex);
2127c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                                String savedProvider = c.getString(appWidgetProviderIndex);
21283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                                id = c.getLong(idIndex);
21297f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                user = allUsers.get(serialNumber);
21307f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                if (user == null) {
21317f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                    itemsToRemove.add(id);
21327f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                    continue;
21337f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                }
21347f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal
2135ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final ComponentName component =
2136ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        ComponentName.unflattenFromString(savedProvider);
2137f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project
2138651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                final int restoreStatus = c.getInt(restoredIndex);
2139ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean isIdValid = (restoreStatus &
2140ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0;
2141ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean wasProviderReady = (restoreStatus &
2142ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
2143ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
21445940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                final LauncherAppWidgetProviderInfo provider =
21455940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        LauncherModel.getProviderInfo(context,
214626ace12135a662ad864678c9fede9817e5c02b67Robin Lee                                                ComponentName.unflattenFromString(savedProvider),
21477f834d2b3084f012b935e6e95f038f2eb4a0acfaSunny Goyal                                                user);
2148ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2149ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                final boolean isProviderReady = isValidProvider(provider);
21505940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                if (!isSafeMode && !customWidget &&
21515940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        wasProviderReady && !isProviderReady) {
2152651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                    String log = "Deleting widget that isn't installed anymore: "
2153ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            + "id=" + id + " appWidgetId=" + appWidgetId;
21545940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
2155b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    Log.e(TAG, log);
21564caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                                    Launcher.addDumpLog(TAG, log, false);
2157b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    itemsToRemove.add(id);
2158b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                } else {
2159ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                    if (isProviderReady) {
2160651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
2161651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                provider.provider);
21625940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
216353f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // The provider is available. So the widget is either
216453f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // available or not available. We do not need to track
216553f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        // any future restore updates.
216653f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        int status = restoreStatus &
216753f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                                ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
2168ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        if (!wasProviderReady) {
2169ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // If provider was not previously ready, update the
2170ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // status and UI flag.
2171ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2172ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            // Id would be valid only if the widget restore broadcast was received.
2173ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            if (isIdValid) {
217484b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                                status = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
2175ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            } else {
2176ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                status &= ~LauncherAppWidgetInfo
2177ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                        .FLAG_PROVIDER_NOT_READY;
2178ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                            }
2179ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        }
2180ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                        appWidgetInfo.restoreStatus = status;
2181651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                    } else {
2182651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        Log.v(TAG, "Widget restore pending id=" + id
2183651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                + " appWidgetId=" + appWidgetId
2184651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                                + " status =" + restoreStatus);
2185651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId,
2186ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal                                                component);
2187651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                        appWidgetInfo.restoreStatus = restoreStatus;
2188756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        Integer installProgress = installingPkgs.get(component.getPackageName());
21899448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal
21909448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                        if ((restoreStatus & LauncherAppWidgetInfo.FLAG_RESTORE_STARTED) != 0) {
21919448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            // Restore has started once.
2192756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        } else if (installProgress != null) {
21939448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            // App restore has started. Update the flag
21949448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            appWidgetInfo.restoreStatus |=
21959448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                                    LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
21969b4b0812fec41c40d81d507cfdb528ba87663f5fSunny Goyal                                        } else if (REMOVE_UNRESTORED_ICONS && !isSafeMode) {
21979448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            Launcher.addDumpLog(TAG,
2198c5fb59fb9a36180ce962f565d85aa92f9991da1aSunny Goyal                                                    "Unrestored widget removed: " + component, true);
21999448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            itemsToRemove.add(id);
22009448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                            continue;
22019448536b113afa6ceefce26604a1b44618d1d4f2Sunny Goyal                                        }
2202756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
2203756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                        appWidgetInfo.installProgress =
2204756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                                installProgress == null ? 0 : installProgress;
2205651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                                    }
2206ff572277112ec3d6a6a8c1be274d6fa1019e3648Sunny Goyal
2207b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.id = id;
2208dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                                    appWidgetInfo.screenId = c.getInt(screenIndex);
2209b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.cellX = c.getInt(cellXIndex);
2210b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.cellY = c.getInt(cellYIndex);
2211b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.spanX = c.getInt(spanXIndex);
2212b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    appWidgetInfo.spanY = c.getInt(spanYIndex);
2213ab7a4fe206b4ca1c18457738d5068df473a01ea5Sunny Goyal                                    appWidgetInfo.user = user;
2214b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2215b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
2216b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
2217b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        Log.e(TAG, "Widget found where container != " +
221841cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                                "CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!");
221941cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                        itemsToRemove.add(id);
2220b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        continue;
2221b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2222b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2223b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    appWidgetInfo.container = container;
2224b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    // check & update map of what's occupied
222541cdc8d20a9ffc35eb5cde29a187a09d62cca8a1Sunny Goyal                                    if (!checkItemPlacement(occupied, appWidgetInfo, sBgWorkspaceScreens)) {
2226fc0fe6b9be040122bc6047ef7f91b20fc8ead9ccSunny Goyal                                        itemsToRemove.add(id);
2227b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                        break;
2228b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    }
2229651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal
22305940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                    if (!customWidget) {
22315940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        String providerName =
22325940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                appWidgetInfo.providerName.flattenToString();
22335940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        if (!providerName.equals(savedProvider) ||
22345940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                (appWidgetInfo.restoreStatus != restoreStatus)) {
22355940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            ContentValues values = new ContentValues();
22365940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            values.put(
22375940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    LauncherSettings.Favorites.APPWIDGET_PROVIDER,
22385940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    providerName);
22395940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                            values.put(LauncherSettings.Favorites.RESTORED,
22405940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                                    appWidgetInfo.restoreStatus);
2241bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                                            updateItem(id, values);
22425940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen                                        }
2243c3919c0e994309982efc8779af57e2bc78dcac43Chris Wren                                    }
2244b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
2245b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                    sBgAppWidgets.add(appWidgetInfo);
2246b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                }
22479c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                                break;
22483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            }
2249b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        } catch (Exception e) {
2250295ae18d0fa7c102c50cf95a2ea09e7f2e9b1539Dan Sandler                            Launcher.addDumpLog(TAG, "Desktop items loading interrupted", e, true);
2251b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        }
2252b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2253b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } finally {
225447b5031c703dbee491af9f49e6e08865452d57efDaniel Sandler                    if (c != null) {
225547b5031c703dbee491af9f49e6e08865452d57efDaniel Sandler                        c.close();
225647b5031c703dbee491af9f49e6e08865452d57efDaniel Sandler                    }
2257b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
2258ad72e1705c32da463a552f2283ae467dc15a4a34Joe Onorato
2259ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                // Break early if we've stopped loading
2260ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                if (mStopped) {
2261ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                    clearSBgDataStructures();
226266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    return;
2263ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung                }
2264ba9c37f41c41121a38d5a52232953d4b103e9471Winson Chung
2265b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (itemsToRemove.size() > 0) {
2266b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    // Remove dead items
2267b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    contentResolver.delete(LauncherSettings.Favorites.CONTENT_URI,
2268b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            Utilities.createDbSelectionQuery(
2269b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    LauncherSettings.Favorites._ID, itemsToRemove), null);
2270b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    if (DEBUG_LOADERS) {
2271b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        Log.d(TAG, "Removed = " + Utilities.createDbSelectionQuery(
2272b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                LauncherSettings.Favorites._ID, itemsToRemove));
2273b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    }
2274b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal
2275b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    // Remove any empty folder
2276b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    for (long folderId : LauncherAppState.getLauncherProvider()
2277b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            .deleteEmptyFolders()) {
2278b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgWorkspaceItems.remove(sBgFolders.get(folderId));
2279b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgFolders.remove(folderId);
2280b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                        sBgItemsIdMap.remove(folderId);
2281b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2282b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
22838802e960495e61803c18ea3dda2e30ef0a611d8fDaniel Sandler
2284317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                // Sort all the folder items and make sure the first 3 items are high resolution.
2285317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                for (FolderInfo folder : sBgFolders) {
2286317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);
2287317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    int pos = 0;
2288317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    for (ShortcutInfo info : folder.contents) {
2289317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        if (info.usingLowResIcon) {
2290317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                            info.updateIcon(mIconCache, false);
2291317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        }
2292317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        pos ++;
2293317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        if (pos >= FolderIcon.NUM_ITEMS_IN_PREVIEW) {
2294317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                            break;
2295317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                        }
2296317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                    }
2297317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal                }
2298317698bd012c1930b83bb4e2e47ac9e363fa6c6aSunny Goyal
2299f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                if (restoredRows.size() > 0) {
2300f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                    // Update restored items that no longer require special handling
2301b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    ContentValues values = new ContentValues();
2302b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    values.put(LauncherSettings.Favorites.RESTORED, 0);
2303b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                    contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, values,
2304b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                            Utilities.createDbSelectionQuery(
2305b1622cc30f2fd9b579cb918083e063685950df92Sunny Goyal                                    LauncherSettings.Favorites._ID, restoredRows), null);
2306f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                }
2307f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
2308f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                if (!isSdCardReady && !sPendingPackages.isEmpty()) {
2309f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    context.registerReceiver(new AppsAvailabilityCheck(),
231005e318d8f7d5ea615539d34b181ee44686f1f494Sunny Goyal                            new IntentFilter(StartupReceiver.SYSTEM_READY),
2311f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                            null, sWorker);
2312f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                }
2313f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
231466cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                // Remove any empty screens
231566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
2316e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                for (ItemInfo item: sBgItemsIdMap) {
231766cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    long screenId = item.screenId;
231866cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
231966cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                            unusedScreens.contains(screenId)) {
232066cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        unusedScreens.remove(screenId);
2321dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
232266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                }
2323dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
232466cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                // If there are any empty screens remove them, and update.
232566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                if (unusedScreens.size() != 0) {
232666cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    sBgWorkspaceScreens.removeAll(unusedScreens);
232766cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                    updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
2328dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
2329dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2330b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (DEBUG_LOADERS) {
2331b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
2332b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Log.d(TAG, "workspace layout: ");
2333dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    int nScreens = occupied.size();
2334892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung                    for (int y = 0; y < countY; y++) {
2335b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        String line = "";
2336dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2337e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                        for (int i = 0; i < nScreens; i++) {
2338e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                            long screenId = occupied.keyAt(i);
2339c916834ad0da535f08325bcd902a60070f2f7e53Winson Chung                            if (screenId > 0) {
2340b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                                line += " | ";
2341b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            }
2342e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                            ItemInfo[][] screen = occupied.valueAt(i);
2343892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung                            for (int x = 0; x < countX; x++) {
2344aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                                if (x < screen.length && y < screen[x].length) {
2345aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                                    line += (screen[x][y] != null) ? "#" : ".";
2346aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                                } else {
2347aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                                    line += "!";
2348aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren                                }
23499c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                            }
23509c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
2351b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        Log.d(TAG, "[ " + line + " ]");
23529c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
23539c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
23543611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2355e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen        }
2356e25af795647a19f1a0d60bc4baea5a996d215fdfAdam Cohen
2357bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        /**
2358bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal         * Partially updates the item without any notification. Must be called on the worker thread.
2359bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal         */
2360bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        private void updateItem(long itemId, ContentValues update) {
2361bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal            mContext.getContentResolver().update(
23621d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal                    LauncherSettings.Favorites.CONTENT_URI,
2363bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    update,
2364bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    BaseColumns._ID + "= ?",
2365bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal                    new String[]{Long.toString(itemId)});
2366bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal        }
2367bb3b02f562bef4de063099c085d3199a77d06cfdSunny Goyal
2368b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Filters the set of items who are directly or indirectly (via another container) on the
2369b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * specified screen. */
23709b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung        private void filterCurrentWorkspaceItems(long currentScreenId,
2371b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> allWorkspaceItems,
2372b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> currentScreenItems,
2373b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<ItemInfo> otherScreenItems) {
23742abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            // Purge any null ItemInfos
23752abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            Iterator<ItemInfo> iter = allWorkspaceItems.iterator();
23762abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            while (iter.hasNext()) {
23772abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                ItemInfo i = iter.next();
23782abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                if (i == null) {
23792abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                    iter.remove();
23802abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                }
23812abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            }
23822abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung
2383b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Order the set of items by their containers first, this allows use to walk through the
2384b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // list sequentially, build up a list of containers that are in the specified screen,
2385b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // as well as all items in those containers.
2386b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Set<Long> itemsOnScreen = new HashSet<Long>();
2387b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Collections.sort(allWorkspaceItems, new Comparator<ItemInfo>() {
2388b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                @Override
2389b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                public int compare(ItemInfo lhs, ItemInfo rhs) {
2390b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    return (int) (lhs.container - rhs.container);
2391b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
2392b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            });
2393b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (ItemInfo info : allWorkspaceItems) {
2394b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
23959b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                    if (info.screenId == currentScreenId) {
2396b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        currentScreenItems.add(info);
2397b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        itemsOnScreen.add(info.id);
2398b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    } else {
2399b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        otherScreenItems.add(info);
24003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
2401b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
2402b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentScreenItems.add(info);
2403b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    itemsOnScreen.add(info.id);
2404b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2405b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    if (itemsOnScreen.contains(info.container)) {
2406b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        currentScreenItems.add(info);
2407b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        itemsOnScreen.add(info.id);
2408b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    } else {
2409b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        otherScreenItems.add(info);
24105c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                    }
24115c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy                }
24123611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2413b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
24145c16f3ecd6b47bff3abbe40deb3d39c66a3b0012Romain Guy
2415b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Filters the set of widgets which are on the specified screen. */
24169b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung        private void filterCurrentAppWidgets(long currentScreenId,
2417b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> appWidgets,
2418b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> currentScreenWidgets,
2419b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<LauncherAppWidgetInfo> otherScreenWidgets) {
2420b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2421b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (LauncherAppWidgetInfo widget : appWidgets) {
24222abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                if (widget == null) continue;
2423b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (widget.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
24249b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                        widget.screenId == currentScreenId) {
2425b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentScreenWidgets.add(widget);
2426b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2427b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherScreenWidgets.add(widget);
2428a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato                }
24299c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
24303611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
243131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2432b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Filters the set of folders which are on the specified screen. */
24339b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung        private void filterCurrentFolders(long currentScreenId,
2434e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                LongArrayMap<ItemInfo> itemsIdMap,
2435e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                LongArrayMap<FolderInfo> folders,
2436e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                LongArrayMap<FolderInfo> currentScreenFolders,
2437e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                LongArrayMap<FolderInfo> otherScreenFolders) {
2438e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal
2439e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            int total = folders.size();
2440e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            for (int i = 0; i < total; i++) {
2441e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                long id = folders.keyAt(i);
2442e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                FolderInfo folder = folders.valueAt(i);
24433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
2444b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ItemInfo info = itemsIdMap.get(id);
24452abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung                if (info == null || folder == null) continue;
2446b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
24479b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                        info.screenId == currentScreenId) {
2448b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentScreenFolders.put(id, folder);
2449b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2450b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherScreenFolders.put(id, folder);
2451b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                }
24523611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2453b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
245431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2455b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /** Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to
2456b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * right) */
2457b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        private void sortWorkspaceItemsSpatially(ArrayList<ItemInfo> workspaceItems) {
2458892c74d460ad98c6306420e1127c9aa3e505ba25Winson Chung            final LauncherAppState app = LauncherAppState.getInstance();
24592e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen            final InvariantDeviceProfile profile = app.getInvariantDeviceProfile();
2460b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // XXX: review this
2461b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Collections.sort(workspaceItems, new Comparator<ItemInfo>() {
2462db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                @Override
2463db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                public int compare(ItemInfo lhs, ItemInfo rhs) {
24642e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                    int cellCountX = (int) profile.numColumns;
24652e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen                    int cellCountY = (int) profile.numRows;
2466db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                    int screenOffset = cellCountX * cellCountY;
2467db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                    int containerOffset = screenOffset * (Launcher.SCREEN_COUNT + 1); // +1 hotseat
2468dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    long lr = (lhs.container * containerOffset + lhs.screenId * screenOffset +
2469db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                            lhs.cellY * cellCountX + lhs.cellX);
2470dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    long rr = (rhs.container * containerOffset + rhs.screenId * screenOffset +
2471db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                            rhs.cellY * cellCountX + rhs.cellX);
2472db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                    return (int) (lr - rr);
2473db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung                }
2474db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung            });
2475b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
2476db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung
2477dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        private void bindWorkspaceScreens(final Callbacks oldCallbacks,
2478dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                final ArrayList<Long> orderedScreens) {
2479dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            final Runnable r = new Runnable() {
2480dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                @Override
2481dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                public void run() {
2482dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2483dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    if (callbacks != null) {
2484dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                        callbacks.bindScreens(orderedScreens);
2485dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                    }
2486dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                }
2487dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            };
2488d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            runOnMainThread(r);
2489dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen        }
2490dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2491b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        private void bindWorkspaceItems(final Callbacks oldCallbacks,
2492b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final ArrayList<ItemInfo> workspaceItems,
2493b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final ArrayList<LauncherAppWidgetInfo> appWidgets,
2494e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                final LongArrayMap<FolderInfo> folders,
2495b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                ArrayList<Runnable> deferredBindRunnables) {
2496b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2497b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            final boolean postOnMainThread = (deferredBindRunnables != null);
2498603bcb91a091d0f4512fdfb92d6df3c6f9fa8059Winson Chung
2499b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Bind the workspace items
2500db8a8944ede3be4ee63b43e24c407a3aaabee4deWinson Chung            int N = workspaceItems.size();
2501b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (int i = 0; i < N; i += ITEMS_CHUNK) {
25023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final int start = i;
25033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
2504b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final Runnable r = new Runnable() {
2505b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    @Override
25069c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    public void run() {
2507c131b74922e6323331c374856bda830010d761c8Joe Onorato                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
25089c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        if (callbacks != null) {
250964359a53dc827797917a8d9a0697a91996789801Winson Chung                            callbacks.bindItems(workspaceItems, start, start+chunkSize,
251064359a53dc827797917a8d9a0697a91996789801Winson Chung                                    false);
25119c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
25129c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
2513b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                };
2514b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (postOnMainThread) {
2515a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                    synchronized (deferredBindRunnables) {
2516a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                        deferredBindRunnables.add(r);
2517a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                    }
2518b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2519d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                    runOnMainThread(r);
25203611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
2521b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2522b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2523b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Bind the folders
2524b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            if (!folders.isEmpty()) {
2525b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final Runnable r = new Runnable() {
2526b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    public void run() {
2527b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2528b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        if (callbacks != null) {
2529b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            callbacks.bindFolders(folders);
25309c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                        }
2531b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2532b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                };
2533b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (postOnMainThread) {
2534a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                    synchronized (deferredBindRunnables) {
2535a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                        deferredBindRunnables.add(r);
2536a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                    }
2537b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2538d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                    runOnMainThread(r);
25399c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
25403611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2541b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2542b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Bind the widgets, one at a time
2543b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            N = appWidgets.size();
2544b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            for (int i = 0; i < N; i++) {
2545b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final LauncherAppWidgetInfo widget = appWidgets.get(i);
2546b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                final Runnable r = new Runnable() {
2547b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    public void run() {
2548b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2549b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        if (callbacks != null) {
2550b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                            callbacks.bindAppWidget(widget);
25513611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
2552b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2553b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                };
2554b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                if (postOnMainThread) {
2555b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    deferredBindRunnables.add(r);
2556b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                } else {
2557d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                    runOnMainThread(r);
25583611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
25593611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
2560b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        }
2561b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2562b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung        /**
2563b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         * Binds all loaded data to actual views on the main thread.
2564b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung         */
256566cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal        private void bindWorkspace(int synchronizeBindPage) {
2566b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            final long t = SystemClock.uptimeMillis();
2567b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            Runnable r;
2568b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2569b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Don't use these two variables in any of the callback runnables.
2570b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Otherwise we hold a reference to them.
2571b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            final Callbacks oldCallbacks = mCallbacks.get();
2572b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            if (oldCallbacks == null) {
2573b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                // This launcher has exited and nobody bothered to tell us.  Just bail.
2574b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                Log.w(TAG, "LoaderTask running with no launcher");
2575b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                return;
2576b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2577b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
25789b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // Save a copy of all the bg-thread collections
2579b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<ItemInfo> workspaceItems = new ArrayList<ItemInfo>();
2580b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<LauncherAppWidgetInfo> appWidgets =
2581b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    new ArrayList<LauncherAppWidgetInfo>();
2582dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            ArrayList<Long> orderedScreenIds = new ArrayList<Long>();
2583e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal
2584e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            final LongArrayMap<FolderInfo> folders;
2585e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            final LongArrayMap<ItemInfo> itemsIdMap;
2586e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal
25872abf94d37c220c3af01aec05cc6ca22f9854d8e0Winson Chung            synchronized (sBgLock) {
2588b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                workspaceItems.addAll(sBgWorkspaceItems);
2589b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                appWidgets.addAll(sBgAppWidgets);
2590dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen                orderedScreenIds.addAll(sBgWorkspaceScreens);
2591e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal
2592e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                folders = sBgFolders.clone();
2593e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                itemsIdMap = sBgItemsIdMap.clone();
2594b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            }
2595b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
25967aff399974c756930070d82d7b2df88f125dacd6Derek Prothro            final boolean isLoadingSynchronously =
25977aff399974c756930070d82d7b2df88f125dacd6Derek Prothro                    synchronizeBindPage != PagedView.INVALID_RESTORE_PAGE;
2598d8dbb46468e0a8860468661a6edfb7969bfdf0a7Adam Cohen            int currScreen = isLoadingSynchronously ? synchronizeBindPage :
25999b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung                oldCallbacks.getCurrentWorkspaceScreen();
2600d8dbb46468e0a8860468661a6edfb7969bfdf0a7Adam Cohen            if (currScreen >= orderedScreenIds.size()) {
2601d8dbb46468e0a8860468661a6edfb7969bfdf0a7Adam Cohen                // There may be no workspace screens (just hotseat items and an empty page).
26027aff399974c756930070d82d7b2df88f125dacd6Derek Prothro                currScreen = PagedView.INVALID_RESTORE_PAGE;
26039b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            }
2604d8dbb46468e0a8860468661a6edfb7969bfdf0a7Adam Cohen            final int currentScreen = currScreen;
26057aff399974c756930070d82d7b2df88f125dacd6Derek Prothro            final long currentScreenId = currentScreen < 0
26067aff399974c756930070d82d7b2df88f125dacd6Derek Prothro                    ? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);
26079b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung
26089b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // Load all the items that are on the current page first (and in the process, unbind
26099b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // all the existing workspace items before we call startBinding() below.
26109b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            unbindWorkspaceItemsOnMainThread();
26119b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung
26129b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            // Separate the items that are on the current screen, and all the other remaining items
2613b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<ItemInfo>();
2614b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<ItemInfo>();
2615b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<LauncherAppWidgetInfo> currentAppWidgets =
2616b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    new ArrayList<LauncherAppWidgetInfo>();
2617b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            ArrayList<LauncherAppWidgetInfo> otherAppWidgets =
2618b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    new ArrayList<LauncherAppWidgetInfo>();
2619e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            LongArrayMap<FolderInfo> currentFolders = new LongArrayMap<>();
2620e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal            LongArrayMap<FolderInfo> otherFolders = new LongArrayMap<>();
2621b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
26229b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            filterCurrentWorkspaceItems(currentScreenId, workspaceItems, currentWorkspaceItems,
2623b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherWorkspaceItems);
26249b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            filterCurrentAppWidgets(currentScreenId, appWidgets, currentAppWidgets,
2625b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherAppWidgets);
26269b9fb967b2305413520dc676d6d3c472b2b6b25eWinson Chung            filterCurrentFolders(currentScreenId, itemsIdMap, folders, currentFolders,
2627b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    otherFolders);
2628b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sortWorkspaceItemsSpatially(currentWorkspaceItems);
2629b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            sortWorkspaceItemsSpatially(otherWorkspaceItems);
2630b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2631b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Tell the workspace that we're about to start binding items
2632b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r = new Runnable() {
26333611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
26343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
26353611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (callbacks != null) {
2636b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                        callbacks.startBinding();
26379c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
26389c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
2639b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            };
2640d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal            runOnMainThread(r);
2641b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2642dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen            bindWorkspaceScreens(oldCallbacks, orderedScreenIds);
2643dcd297f05a866e07090d6e2af8fb4b15f28cb555Adam Cohen
2644b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Load items on the current page
2645b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets,
2646b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    currentFolders, null);
26471462de39f01cec0ba785386532719cb0207dd827Adam Cohen            if (isLoadingSynchronously) {
26481462de39f01cec0ba785386532719cb0207dd827Adam Cohen                r = new Runnable() {
26491462de39f01cec0ba785386532719cb0207dd827Adam Cohen                    public void run() {
26501462de39f01cec0ba785386532719cb0207dd827Adam Cohen                        Callbacks callbacks = tryGetCallbacks(oldCallbacks);
26517aff399974c756930070d82d7b2df88f125dacd6Derek Prothro                        if (callbacks != null && currentScreen != PagedView.INVALID_RESTORE_PAGE) {
26521462de39f01cec0ba785386532719cb0207dd827Adam Cohen                            callbacks.onPageBoundSynchronously(currentScreen);
26531462de39f01cec0ba785386532719cb0207dd827Adam Cohen                        }
26541462de39f01cec0ba785386532719cb0207dd827Adam Cohen                    }
26551462de39f01cec0ba785386532719cb0207dd827Adam Cohen                };
2656d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                runOnMainThread(r);
26571462de39f01cec0ba785386532719cb0207dd827Adam Cohen            }
2658b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
26594a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            // Load all the remaining pages (if we are loading synchronously, we want to defer this
26604a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            // work until after the first render)
2661a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            synchronized (mDeferredBindRunnables) {
2662a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                mDeferredBindRunnables.clear();
2663a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk            }
2664b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            bindWorkspaceItems(oldCallbacks, otherWorkspaceItems, otherAppWidgets, otherFolders,
26654a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung                    (isLoadingSynchronously ? mDeferredBindRunnables : null));
2666b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2667b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            // Tell the workspace that we're done binding items
2668b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            r = new Runnable() {
26693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
2670b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    Callbacks callbacks = tryGetCallbacks(oldCallbacks);
2671b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    if (callbacks != null) {
267266cfdc2549b973496f2d5555defc22b7a15b5620Sunny Goyal                        callbacks.finishBindingItems();
2673b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung                    }
2674b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung
2675639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    mIsLoadingAndBindingWorkspace = false;
2676639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
2677639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    // Run all the bind complete runnables after workspace is bound.
2678639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    if (!mBindCompleteRunnables.isEmpty()) {
2679639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        synchronized (mBindCompleteRunnables) {
2680639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            for (final Runnable r : mBindCompleteRunnables) {
2681639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                runOnWorkerThread(r);
2682639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            }
2683639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            mBindCompleteRunnables.clear();
2684639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        }
2685639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    }
2686639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
268798e030be2abc03e90e9fd9f8bf67e2e01db39cc0Winson Chung                    // If we're profiling, ensure this is the last thing in the queue.
26883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (DEBUG_LOADERS) {
26893611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        Log.d(TAG, "bound workspace in "
26903611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            + (SystemClock.uptimeMillis()-t) + "ms");
26919c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
269236a62fe917be0a2520c457f985075fb5d3d09d1cWinson Chung
26939c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                }
2694b8b2a5aa45d82ce81301250707bc373e1da4aa14Winson Chung            };
26954a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            if (isLoadingSynchronously) {
2696a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                synchronized (mDeferredBindRunnables) {
2697a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                    mDeferredBindRunnables.add(r);
2698a0a7a7440e860c61c8261c5009dbe351869896b3Jason Monk                }
26994a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            } else {
2700d33860f2cc027b91dd09cc38ddd0e37878ba6c69Sunny Goyal                runOnMainThread(r);
27014a2afa36553079e9f75fe7c8fcce863e84578e14Winson Chung            }
27023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
27033611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void loadAndBindAllApps() {
27053611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
27063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
27073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
27083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (!mAllAppsLoaded) {
270964359a53dc827797917a8d9a0697a91996789801Winson Chung                loadAllApps();
2710f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                synchronized (LoaderTask.this) {
2711f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    if (mStopped) {
2712f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                        return;
2713f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                    }
2714f5cd998c25b025e46c56f4e862f4f5573a807745Sunny Goyal                }
27154e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                updateIconCache();
271693f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                synchronized (LoaderTask.this) {
271793f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    if (mStopped) {
271893f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                        return;
271993f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    }
272093f824ac2f2f3ec92a775cad58dcf59e4302fe64Reena Lee                    mAllAppsLoaded = true;
27213611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
27223611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            } else {
27233611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                onlyBindAllApps();
27243611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
27253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
27263611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27274e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        private void updateIconCache() {
27284e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            // Ignore packages which have a promise icon.
27294e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            HashSet<String> packagesToIgnore = new HashSet<>();
27304e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            synchronized (sBgLock) {
27314e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                for (ItemInfo info : sBgItemsIdMap) {
27324e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    if (info instanceof ShortcutInfo) {
27334e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        ShortcutInfo si = (ShortcutInfo) info;
27344e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        if (si.isPromise() && si.getTargetComponent() != null) {
27354e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            packagesToIgnore.add(si.getTargetComponent().getPackageName());
27364e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        }
27374e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    } else if (info instanceof LauncherAppWidgetInfo) {
27384e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        LauncherAppWidgetInfo lawi = (LauncherAppWidgetInfo) info;
27394e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        if (lawi.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
27404e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                            packagesToIgnore.add(lawi.providerName.getPackageName());
27414e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                        }
27424e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                    }
27434e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                }
27444e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            }
27454e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            mIconCache.updateDbIcons(packagesToIgnore);
27464e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        }
27474e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal
27483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        private void onlyBindAllApps() {
27493611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Callbacks oldCallbacks = mCallbacks.get();
27503611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (oldCallbacks == null) {
27513611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // This launcher has exited and nobody bothered to tell us.  Just bail.
27523611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");
27533611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return;
27543611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
27553611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27563611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            // shallow copy
2757c208ff9c5ded4953ded6a3358097c9f7280df825Winson Chung            @SuppressWarnings("unchecked")
2758eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> list
2759eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                    = (ArrayList<AppInfo>) mBgAllAppsList.data.clone();
27609110d485fa12c03df3061278717efb342f1142cfHyunyoung Song            final WidgetsModel widgetList = mBgWidgetsModel.clone();
2761c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            Runnable r = new Runnable() {
27623611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                public void run() {
27633611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    final long t = SystemClock.uptimeMillis();
27643611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
27653611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (callbacks != null) {
27663611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        callbacks.bindAllApplications(list);
27679110d485fa12c03df3061278717efb342f1142cfHyunyoung Song                        callbacks.bindAllPackages(widgetList);
27689c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
27693611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    if (DEBUG_LOADERS) {
27703611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        Log.d(TAG, "bound all " + list.size() + " apps from cache in "
2771a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato                                + (SystemClock.uptimeMillis()-t) + "ms");
27729c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato                    }
27733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
2774c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            };
2775c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            boolean isRunningOnMainThread = !(sWorkerThread.getThreadId() == Process.myTid());
277664359a53dc827797917a8d9a0697a91996789801Winson Chung            if (isRunningOnMainThread) {
2777c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung                r.run();
2778c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            } else {
2779c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung                mHandler.post(r);
2780c93e5ae12018bb214099ff88a48cc21580aec4c3Winson Chung            }
27813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
27823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
278364359a53dc827797917a8d9a0697a91996789801Winson Chung        private void loadAllApps() {
278464359a53dc827797917a8d9a0697a91996789801Winson Chung            final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
27853611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
27863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final Callbacks oldCallbacks = mCallbacks.get();
27873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (oldCallbacks == null) {
27883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                // This launcher has exited and nobody bothered to tell us.  Just bail.
278964359a53dc827797917a8d9a0697a91996789801Winson Chung                Log.w(TAG, "LoaderTask running with no launcher (loadAllApps)");
27903611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return;
27919c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            }
279231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2793ed13187a745866483139e2878037e1f8427ce567Kenny Guy            final List<UserHandleCompat> profiles = mUserManager.getUserProfiles();
2794ed13187a745866483139e2878037e1f8427ce567Kenny Guy
279564359a53dc827797917a8d9a0697a91996789801Winson Chung            // Clear the list of apps
279664359a53dc827797917a8d9a0697a91996789801Winson Chung            mBgAllAppsList.clear();
2797ed13187a745866483139e2878037e1f8427ce567Kenny Guy            for (UserHandleCompat user : profiles) {
2798ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Query for the set of apps
2799ed13187a745866483139e2878037e1f8427ce567Kenny Guy                final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
2800756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                final List<LauncherActivityInfoCompat> apps = mLauncherApps.getActivityList(null, user);
2801ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (DEBUG_LOADERS) {
2802ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    Log.d(TAG, "getActivityList took "
2803ed13187a745866483139e2878037e1f8427ce567Kenny Guy                            + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);
2804ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);
2805ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
2806ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Fail if we don't have any apps
2807e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                // TODO: Fix this. Only fail for the current user.
2808ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (apps == null || apps.isEmpty()) {
2809ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return;
2810ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
28114fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
2812ed13187a745866483139e2878037e1f8427ce567Kenny Guy                // Create the ApplicationInfos
2813ed13187a745866483139e2878037e1f8427ce567Kenny Guy                for (int i = 0; i < apps.size(); i++) {
2814ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    LauncherActivityInfoCompat app = apps.get(i);
2815ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    // This builds the icon bitmaps.
28164fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
2817ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
2818e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
2819756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                final ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
2820756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                if (heuristic != null) {
2821639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    final Runnable r = new Runnable() {
2822756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal
2823756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        @Override
2824756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        public void run() {
2825756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                            heuristic.processUserApps(apps);
2826756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                        }
2827639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    };
2828639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                    runOnMainThread(new Runnable() {
2829639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal
2830639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        @Override
2831639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        public void run() {
2832639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            // Check isLoadingWorkspace on the UI thread, as it is updated on
2833639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            // the UI thread.
2834639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            if (mIsLoadingAndBindingWorkspace) {
2835639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                synchronized (mBindCompleteRunnables) {
2836639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                    mBindCompleteRunnables.add(r);
2837639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                }
2838639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            } else {
2839639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                                runOnWorkerThread(r);
2840639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                            }
2841639e906a0fc205b48512951feec0cbb47513e246Sunny Goyal                        }
2842756a28aeece3b00f40415f1fccae6f7d57104bfbSunny Goyal                    });
2843e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                }
284464359a53dc827797917a8d9a0697a91996789801Winson Chung            }
284585f418d0f5607c66efef1673075a6d3486e5af83Bjorn Bringert            // Huh? Shouldn't this be inside the Runnable below?
2846eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> added = mBgAllAppsList.added;
2847eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            mBgAllAppsList.added = new ArrayList<AppInfo>();
28483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
284964359a53dc827797917a8d9a0697a91996789801Winson Chung            // Post callback on main thread
285064359a53dc827797917a8d9a0697a91996789801Winson Chung            mHandler.post(new Runnable() {
285164359a53dc827797917a8d9a0697a91996789801Winson Chung                public void run() {
28529892e5874061233dec57107d1d3d7d5d8e1f5d93Hyunyoung Song
285364359a53dc827797917a8d9a0697a91996789801Winson Chung                    final long bindTime = SystemClock.uptimeMillis();
285411a1a53651924b544513f1f6971a735b18d67539Winson Chung                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
285564359a53dc827797917a8d9a0697a91996789801Winson Chung                    if (callbacks != null) {
285664359a53dc827797917a8d9a0697a91996789801Winson Chung                        callbacks.bindAllApplications(added);
28573611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) {
285864359a53dc827797917a8d9a0697a91996789801Winson Chung                            Log.d(TAG, "bound " + added.size() + " apps in "
285964359a53dc827797917a8d9a0697a91996789801Winson Chung                                + (SystemClock.uptimeMillis() - bindTime) + "ms");
28603611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
286164359a53dc827797917a8d9a0697a91996789801Winson Chung                    } else {
286264359a53dc827797917a8d9a0697a91996789801Winson Chung                        Log.i(TAG, "not binding apps: no Launcher activity");
286364359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
28643611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                }
286564359a53dc827797917a8d9a0697a91996789801Winson Chung            });
286618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            // Cleanup any data stored for a deleted user.
286718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            ManagedProfileHeuristic.processAllUsers(profiles, mContext);
2868cc67f476c01ee6a7d593fa67f80392c6793432d7Joe Onorato
28692d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal            loadAndBindWidgetsAndShortcuts(tryGetCallbacks(oldCallbacks), true /* refresh */);
28703611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (DEBUG_LOADERS) {
287164359a53dc827797917a8d9a0697a91996789801Winson Chung                Log.d(TAG, "Icons processed in "
287264359a53dc827797917a8d9a0697a91996789801Winson Chung                        + (SystemClock.uptimeMillis() - loadTime) + "ms");
28733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
28743611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
2875dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
287675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        public void dumpState() {
287775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            synchronized (sBgLock) {
287875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mContext=" + mContext);
287975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
288075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
288175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                Log.d(TAG, "mItems size=" + sBgWorkspaceItems.size());
288275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            }
288375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
288475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    }
288577919b93b98f5afa1b39546861197d6065847224Sunny Goyal
288675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    /**
288775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     * Called when the icons for packages have been updated in the icon cache.
288875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal     */
288975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal    public void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandleCompat user) {
289075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final Callbacks callbacks = getCallback();
289175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final ArrayList<AppInfo> updatedApps = new ArrayList<>();
289275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<>();
289377919b93b98f5afa1b39546861197d6065847224Sunny Goyal
289475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        // If any package icon has changed (app was updated while launcher was dead),
289575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        // update the corresponding shortcuts.
289675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        synchronized (sBgLock) {
289775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            for (ItemInfo info : sBgItemsIdMap) {
289875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                if (info instanceof ShortcutInfo && user.equals(info.user)
289975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
290075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    ShortcutInfo si = (ShortcutInfo) info;
290175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    ComponentName cn = si.getTargetComponent();
290275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cn != null && updatedPackages.contains(cn.getPackageName())) {
290375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        si.updateIcon(mIconCache);
290475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        updatedShortcuts.add(si);
290577919b93b98f5afa1b39546861197d6065847224Sunny Goyal                    }
290677919b93b98f5afa1b39546861197d6065847224Sunny Goyal                }
290777919b93b98f5afa1b39546861197d6065847224Sunny Goyal            }
290875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mBgAllAppsList.updateIconsAndLabels(updatedPackages, user, updatedApps);
290975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        }
291077919b93b98f5afa1b39546861197d6065847224Sunny Goyal
291175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        if (!updatedShortcuts.isEmpty()) {
291275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            final UserHandleCompat userFinal = user;
291375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mHandler.post(new Runnable() {
291475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
291575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                public void run() {
291675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    Callbacks cb = getCallback();
291775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cb != null && callbacks == cb) {
291875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        cb.bindShortcutsChanged(updatedShortcuts,
291975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                                new ArrayList<ShortcutInfo>(), userFinal);
292077919b93b98f5afa1b39546861197d6065847224Sunny Goyal                    }
292175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
292275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            });
292377919b93b98f5afa1b39546861197d6065847224Sunny Goyal        }
292477919b93b98f5afa1b39546861197d6065847224Sunny Goyal
292575b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal        if (!updatedApps.isEmpty()) {
292675b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            mHandler.post(new Runnable() {
292775b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal
292875b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                public void run() {
292975b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    Callbacks cb = getCallback();
293075b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    if (cb != null && callbacks == cb) {
293175b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                        cb.bindAppsUpdated(updatedApps);
293275b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                    }
293375b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal                }
293475b0f552ae653a4afc64c5fb6782a481fdb89b4dSunny Goyal            });
29353611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
2936091f0ffd929f7a0a9a6af7d202eae13c48c07daaSunny Goyal
2937091f0ffd929f7a0a9a6af7d202eae13c48c07daaSunny Goyal        // Reload widget list. No need to refresh, as we only want to update the icons and labels.
29382d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal        loadAndBindWidgetsAndShortcuts(callbacks, false);
29393611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
294031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
29413611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    void enqueuePackageUpdated(PackageUpdatedTask task) {
2942700889f504ef134ab307d95b6bfbbb426ea730e3Brad Fitzpatrick        sWorker.post(task);
29433611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    }
2944d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
2945091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk class AppsAvailabilityCheck extends BroadcastReceiver {
2946f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
2947f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        @Override
2948f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        public void onReceive(Context context, Intent intent) {
2949f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            synchronized (sBgLock) {
2950f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                final LauncherAppsCompat launcherApps = LauncherAppsCompat
2951f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        .getInstance(mApp.getContext());
29521a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final PackageManager manager = context.getPackageManager();
29531a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final ArrayList<String> packagesRemoved = new ArrayList<String>();
29541a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final ArrayList<String> packagesUnavailable = new ArrayList<String>();
2955f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                for (Entry<UserHandleCompat, HashSet<String>> entry : sPendingPackages.entrySet()) {
2956f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    UserHandleCompat user = entry.getKey();
29571a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    packagesRemoved.clear();
29581a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    packagesUnavailable.clear();
2959f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    for (String pkg : entry.getValue()) {
2960f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        if (!launcherApps.isPackageEnabledForProfile(pkg, user)) {
29611a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            boolean packageOnSdcard = launcherApps.isAppEnabled(
29621a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    manager, pkg, PackageManager.GET_UNINSTALLED_PACKAGES);
29631a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            if (packageOnSdcard) {
29641a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                Launcher.addDumpLog(TAG, "Package found on sd-card: " + pkg, true);
29651a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesUnavailable.add(pkg);
29661a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            } else {
29671a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                Launcher.addDumpLog(TAG, "Package not found: " + pkg, true);
29681a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesRemoved.add(pkg);
29691a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            }
2970f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        }
2971f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    }
2972f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    if (!packagesRemoved.isEmpty()) {
2973f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_REMOVE,
2974f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                                packagesRemoved.toArray(new String[packagesRemoved.size()]), user));
2975f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                    }
29761a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    if (!packagesUnavailable.isEmpty()) {
29771a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                        enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UNAVAILABLE,
29781a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                packagesUnavailable.toArray(new String[packagesUnavailable.size()]), user));
29791a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    }
2980f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal                }
2981349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                sPendingPackages.clear();
2982f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal            }
2983f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        }
2984f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal    }
2985f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal
29863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato    private class PackageUpdatedTask implements Runnable {
29873611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        int mOp;
29883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        String[] mPackages;
2989ed13187a745866483139e2878037e1f8427ce567Kenny Guy        UserHandleCompat mUser;
2990d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
29913611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_NONE = 0;
29923611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_ADD = 1;
29933611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_UPDATE = 2;
29943611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_REMOVE = 3; // uninstlled
29953611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public static final int OP_UNAVAILABLE = 4; // external media unmounted
299631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
2997d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
2998ed13187a745866483139e2878037e1f8427ce567Kenny Guy        public PackageUpdatedTask(int op, String[] packages, UserHandleCompat user) {
29993611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mOp = op;
30003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mPackages = packages;
3001ed13187a745866483139e2878037e1f8427ce567Kenny Guy            mUser = user;
30023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
3003d65d08e709ec0916446100bae0a7276d0800382fJoe Onorato
30043611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        public void run() {
3005c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal            if (!mHasLoaderCompletedOnce) {
3006c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal                // Loader has not yet run.
3007c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal                return;
3008c905efc89cd8a391ae73f36d356c907b4aaf1bf0Sunny Goyal            }
3009cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            final Context context = mApp.getContext();
3010dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
30113611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final String[] packages = mPackages;
30123611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            final int N = packages.length;
30133611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            switch (mOp) {
301418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                case OP_ADD: {
30153611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30163611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
30174fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.updateIconsForPkg(packages[i], mUser);
3018ed13187a745866483139e2878037e1f8427ce567Kenny Guy                        mBgAllAppsList.addPackage(context, packages[i], mUser);
3019dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler                    }
3020e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
302118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
302218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    if (heuristic != null) {
302318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        heuristic.processPackageAdd(mPackages);
3024e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    }
30253611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
302618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                }
30273611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                case OP_UPDATE:
30283611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30293611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
30304fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.updateIconsForPkg(packages[i], mUser);
3031ed13187a745866483139e2878037e1f8427ce567Kenny Guy                        mBgAllAppsList.updatePackage(context, packages[i], mUser);
30325b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal                        mApp.getWidgetCache().removePackage(packages[i], mUser);
30333611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
30343611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
303518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                case OP_REMOVE: {
303618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
303718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                    if (heuristic != null) {
303818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                        heuristic.processPackageRemoved(mPackages);
3039e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    }
30404fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    for (int i=0; i<N; i++) {
30414fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
30424fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mIconCache.removeIconsForPkg(packages[i], mUser);
30434fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                    }
3044e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    // Fall through
304518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal                }
30463611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                case OP_UNAVAILABLE:
30473611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    for (int i=0; i<N; i++) {
30483611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
30494fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal                        mBgAllAppsList.removePackage(packages[i], mUser);
30505b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal                        mApp.getWidgetCache().removePackage(packages[i], mUser);
30513611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
30523611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    break;
30533611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3054dca661236c73ecd819cfea964c6f8170e5cc40aeDaniel Sandler
3055eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            ArrayList<AppInfo> added = null;
3056eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            ArrayList<AppInfo> modified = null;
3057eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka            final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();
30583611578579b4bfb25616085dafdb1a45207394f9Joe Onorato
3059487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen            if (mBgAllAppsList.added.size() > 0) {
3060eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                added = new ArrayList<AppInfo>(mBgAllAppsList.added);
30615d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.added.clear();
30623611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3063487f7dd3059621527eb439d7d51d34e00293f9b1Adam Cohen            if (mBgAllAppsList.modified.size() > 0) {
3064eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);
30655d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.modified.clear();
30663611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
30675d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung            if (mBgAllAppsList.removed.size() > 0) {
306883892cc0768bd6d7f0827886e9e7a2eb3eed2b01Winson Chung                removedApps.addAll(mBgAllAppsList.removed);
30695d55f33a1d7a16a11fb759d8f37eeef45e132b98Winson Chung                mBgAllAppsList.removed.clear();
3070cd81073eac537e9f85eeee14588d513ea8a56e17Winson Chung            }
3071cd81073eac537e9f85eeee14588d513ea8a56e17Winson Chung
3072e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal            final Callbacks callbacks = getCallback();
30733611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (callbacks == null) {
30743611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");
30753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                return;
3076be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato            }
3077be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato
30784390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
30794390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    new HashMap<ComponentName, AppInfo>();
30804390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
30813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (added != null) {
3082c9acdd51c40c1b397adae6ba62c4acd01914b473Sunny Goyal                addAppsToAllApps(context, added);
30834390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                for (AppInfo ai : added) {
30844390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    addedOrUpdatedApps.put(ai.componentName, ai);
30854390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                }
30863611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
308776a47a1b2273c4d7dfab0beeadc1a8387e6a2840Adam Cohen
30883611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            if (modified != null) {
3089eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka                final ArrayList<AppInfo> modifiedFinal = modified;
30904390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                for (AppInfo ai : modified) {
30914390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    addedOrUpdatedApps.put(ai.componentName, ai);
309264359a53dc827797917a8d9a0697a91996789801Winson Chung                }
309364359a53dc827797917a8d9a0697a91996789801Winson Chung
30943611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.post(new Runnable() {
30953611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    public void run() {
3096e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
3097cd2b01416febb5bf50ed5ede1544dea33fee3b0bWinson Chung                        if (callbacks == cb && cb != null) {
30983611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                            callbacks.bindAppsUpdated(modifiedFinal);
30993611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
31003611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
31013611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                });
31023611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            }
3103780fe59a7af8b12fbdcd7f6841edaa7f2c2e019dWinson Chung
31044390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal            // Update shortcut infos
3105b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal            if (mOp == OP_ADD || mOp == OP_UPDATE) {
31064390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
31074390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
31084390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
31094390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
3110b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
3111b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                synchronized (sBgLock) {
3112e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal                    for (ItemInfo info : sBgItemsIdMap) {
3113b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
3114b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            ShortcutInfo si = (ShortcutInfo) info;
31154390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            boolean infoUpdated = false;
31164390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            boolean shortcutUpdated = false;
31174390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31184390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            // Update shortcuts which use iconResource.
3119b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            if ((si.iconResource != null)
31204390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    && packageSet.contains(si.iconResource.packageName)) {
312153d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                Bitmap icon = Utilities.createIconBitmap(
312253d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                        si.iconResource.packageName,
312353d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                                        si.iconResource.resourceName, context);
3124b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                if (icon != null) {
3125b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                    si.setIcon(icon);
3126b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                    si.usingFallbackIcon = false;
31274390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
3128b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                                }
3129b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            }
31304390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31314390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            ComponentName cn = si.getTargetComponent();
31324390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (cn != null && packageSet.contains(cn.getPackageName())) {
31334390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                AppInfo appInfo = addedOrUpdatedApps.get(cn);
31344390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31354390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                if (si.isPromise()) {
31364390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
31374390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        // Auto install icon
31384390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        PackageManager pm = context.getPackageManager();
31394390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        ResolveInfo matched = pm.resolveActivity(
31404390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                new Intent(Intent.ACTION_MAIN)
31414390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
31424390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                PackageManager.MATCH_DEFAULT_ONLY);
31434390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        if (matched == null) {
31444390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            // Try to find the best match activity.
31454390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            Intent intent = pm.getLaunchIntentForPackage(
31464390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                    cn.getPackageName());
31474390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            if (intent != null) {
31484390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                cn = intent.getComponent();
31494390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                appInfo = addedOrUpdatedApps.get(cn);
31504390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            }
31514390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31524390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            if ((intent == null) || (appInfo == null)) {
31534390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                removedShortcuts.add(si);
31544390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                                continue;
31554390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            }
31564390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                            si.promisedIntent = intent;
31574390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        }
31584390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    }
31594390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31604390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    // Restore the shortcut.
3161fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                    if (appInfo != null) {
3162fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                        si.flags = appInfo.flags;
3163fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal                                    }
31644390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
3165756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.intent = si.promisedIntent;
3166756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.promisedIntent = null;
3167756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal                                    si.status = ShortcutInfo.DEFAULT;
31684390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
31694390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.updateIcon(mIconCache);
31704390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
31714390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31724390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
31734390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
31744390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.updateIcon(mIconCache);
317582b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                                    si.title = Utilities.trim(appInfo.title);
31764390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.contentDescription = appInfo.contentDescription;
31774390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    infoUpdated = true;
31784390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
31794390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31804390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                if ((si.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
31814390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    // Since package was just updated, the target must be available now.
31824390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
31834390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    shortcutUpdated = true;
31844390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                }
31854390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
31864390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
31874390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (infoUpdated || shortcutUpdated) {
31884390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updatedShortcuts.add(si);
31894390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
31904390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (infoUpdated) {
31914390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updateItemInDatabase(context, si);
31924390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
31934390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        } else if (info instanceof LauncherAppWidgetInfo) {
31944390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
31954390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (mUser.equals(widgetInfo.user)
31964390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
31974390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                    && packageSet.contains(widgetInfo.providerName.getPackageName())) {
319853f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                widgetInfo.restoreStatus &=
319953f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY &
320053f9672b30b8a36bfae9f6492f732ccfb87723a4Sunny Goyal                                        ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
320184b4adc3fb2301466468828ccbd742209619e597Sunny Goyal
320284b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // adding this flag ensures that launcher shows 'click to setup'
320384b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // if the widget has a config activity. In case there is no config
320484b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                // activity, it will be marked as 'restored' during bind.
320584b4adc3fb2301466468828ccbd742209619e597Sunny Goyal                                widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
320684b4adc3fb2301466468828ccbd742209619e597Sunny Goyal
32074390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                widgets.add(widgetInfo);
32084390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                updateItemInDatabase(context, widgetInfo);
32094390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
3210b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        }
3211b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                    }
3212b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                }
3213b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal
32144390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
3215b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                    mHandler.post(new Runnable() {
32164390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal
3217b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        public void run() {
3218e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Callbacks cb = getCallback();
3219b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            if (callbacks == cb && cb != null) {
32204390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                callbacks.bindShortcutsChanged(
32214390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                        updatedShortcuts, removedShortcuts, mUser);
32224390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            }
32234390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        }
32244390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    });
32254390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    if (!removedShortcuts.isEmpty()) {
32264390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        deleteItemsFromDatabase(context, removedShortcuts);
32274390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    }
32284390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                }
32294390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                if (!widgets.isEmpty()) {
32304390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                    mHandler.post(new Runnable() {
32314390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                        public void run() {
3232e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                            Callbacks cb = getCallback();
32334390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                            if (callbacks == cb && cb != null) {
32344390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal                                callbacks.bindWidgetsRestored(widgets);
3235b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                            }
3236b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                        }
3237b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                    });
3238b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                }
3239b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal            }
3240b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal
3241df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            final ArrayList<String> removedPackageNames =
3242df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                    new ArrayList<String>();
32431a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal            if (mOp == OP_REMOVE || mOp == OP_UNAVAILABLE) {
3244df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Mark all packages in the broadcast to be removed
3245df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                removedPackageNames.addAll(Arrays.asList(packages));
3246df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            } else if (mOp == OP_UPDATE) {
3247df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Mark disabled packages in the broadcast to be removed
3248df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                for (int i=0; i<N; i++) {
3249ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    if (isPackageDisabled(context, packages[i], mUser)) {
3250df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                        removedPackageNames.add(packages[i]);
325164359a53dc827797917a8d9a0697a91996789801Winson Chung                    }
325264359a53dc827797917a8d9a0697a91996789801Winson Chung                }
3253df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            }
32541a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
3255df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung            if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {
32561a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                final int removeReason;
32571a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                if (mOp == OP_UNAVAILABLE) {
32581a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    removeReason = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
32591a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                } else {
32601a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    // Remove all the components associated with this package
32611a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    for (String pn : removedPackageNames) {
32621a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                        deletePackageFromDatabase(context, pn, mUser);
32631a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    }
32641a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    // Remove all the specific components
32651a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    for (AppInfo a : removedApps) {
32661a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                        ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);
32671a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                        deleteItemsFromDatabase(context, infos);
32681a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    }
32691a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                    removeReason = 0;
32701a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                }
32711a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal
3272df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Remove any queued items from the install queue
3273e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackageNames, mUser);
3274df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung                // Call the components-removed callback
32753611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                mHandler.post(new Runnable() {
32763611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    public void run() {
3277e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                        Callbacks cb = getCallback();
3278cd2b01416febb5bf50ed5ede1544dea33fee3b0bWinson Chung                        if (callbacks == cb && cb != null) {
32791a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                            callbacks.bindComponentsRemoved(
32801a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal                                    removedPackageNames, removedApps, mUser, removeReason);
32813611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                        }
32823611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                    }
32833611578579b4bfb25616085dafdb1a45207394f9Joe Onorato                });
3284be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato            }
3285227239e7c05d26c4098980b991d3472077c01ccbHyunyoung Song
32862d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal            // Update widgets
32872d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal            if (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE) {
32882d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                // Always refresh for a package event on secondary user
32892d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                boolean needToRefresh = !mUser.equals(UserHandleCompat.myUserHandle());
32902d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal
32912d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                // Refresh widget list, if the package already had a widget.
32922d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                synchronized (sBgLock) {
32932d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    if (sBgWidgetProviders != null) {
32942d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                        HashSet<String> pkgSet = new HashSet<>();
32952d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                        Collections.addAll(pkgSet, mPackages);
32962d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal
32972d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                        for (ComponentKey key : sBgWidgetProviders.keySet()) {
32982d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                            needToRefresh |= key.user.equals(mUser) &&
32992d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                                    pkgSet.contains(key.componentName.getPackageName());
33002d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                        }
33012d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    }
33022d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                }
33032d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal
33042d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                if (!needToRefresh && mOp != OP_REMOVE) {
33052d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    // Refresh widget list, if there is any newly added widget
33062d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    PackageManager pm = context.getPackageManager();
33072d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    for (String pkg : mPackages) {
33082d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                        needToRefresh |= !pm.queryBroadcastReceivers(
33092d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                                new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
33102d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                                    .setPackage(pkg), 0).isEmpty();
33112d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                    }
33122d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                }
33132d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal
33142d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                loadAndBindWidgetsAndShortcuts(callbacks, needToRefresh);
33152d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal            }
3316227239e7c05d26c4098980b991d3472077c01ccbHyunyoung Song
33174caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen            // Write all the logs to disk
33184caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen            mHandler.post(new Runnable() {
33194caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                public void run() {
3320e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal                    Callbacks cb = getCallback();
33214caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                    if (callbacks == cb && cb != null) {
3322ede4129e77f8347e32c0da9c615bcff2cbc06fd8Winson Chung                        callbacks.dumpLogsToLocalData();
33234caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                    }
33244caf298a2c9d861d69f5a47b747ada911b125b6dAdam Cohen                }
332580baf5a6b3c62a62265f626d43d1167783c94131Winson Chung            });
332631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
332731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
332831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
332970a48befe48af0a318e88745f480d2ed42936bb5Hyunyoung Song    public static List<LauncherAppWidgetProviderInfo> getWidgetProviders(Context context,
333070a48befe48af0a318e88745f480d2ed42936bb5Hyunyoung Song            boolean refresh) {
33313abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song        ArrayList<LauncherAppWidgetProviderInfo> results =
33323abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                new ArrayList<LauncherAppWidgetProviderInfo>();
33333abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song        try {
33343abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song            synchronized (sBgLock) {
33353abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                if (sBgWidgetProviders == null || refresh) {
33363abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    HashMap<ComponentKey, LauncherAppWidgetProviderInfo> tmpWidgetProviders
33373abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                            = new HashMap<>();
33383abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    AppWidgetManagerCompat wm = AppWidgetManagerCompat.getInstance(context);
33393abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    LauncherAppWidgetProviderInfo info;
33403abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song
33413abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    List<AppWidgetProviderInfo> widgets = wm.getAllProviders();
33423abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    for (AppWidgetProviderInfo pInfo : widgets) {
33433abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, pInfo);
33443abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        UserHandleCompat user = wm.getUser(info);
33453abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
33463abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    }
33475940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
33483abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    Collection<CustomAppWidget> customWidgets = Launcher.getCustomAppWidgets().values();
33493abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    for (CustomAppWidget widget : customWidgets) {
33503abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        info = new LauncherAppWidgetProviderInfo(context, widget);
33513abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        UserHandleCompat user = wm.getUser(info);
33523abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
33533abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    }
33543abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    // Replace the global list at the very end, so that if there is an exception,
33553abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    // previously loaded provider list is used.
33563abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    sBgWidgetProviders = tmpWidgetProviders;
33573abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                }
33583abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                results.addAll(sBgWidgetProviders.values());
33593abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                return results;
33603abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song            }
33613abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song        } catch (Exception e) {
33623abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song            if (e.getCause() instanceof TransactionTooLargeException) {
33633abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                // the returned value may be incomplete and will not be refreshed until the next
33643abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                // time Launcher starts.
33653abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                // TODO: after figuring out a repro step, introduce a dirty bit to check when
33663abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                // onResume is called to refresh the widget provider list.
33673abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                synchronized (sBgLock) {
33683abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    if (sBgWidgetProviders != null) {
33693abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                        results.addAll(sBgWidgetProviders.values());
33703abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    }
33713abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                    return results;
337226ace12135a662ad864678c9fede9817e5c02b67Robin Lee                }
33733abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song            } else {
33743abd5488cca5b06c97251db453a5a6ed61e33ce8Hyunyoung Song                throw e;
33755940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen            }
33765940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen        }
33775940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen    }
33785940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
337926ace12135a662ad864678c9fede9817e5c02b67Robin Lee    public static LauncherAppWidgetProviderInfo getProviderInfo(Context ctx, ComponentName name,
338026ace12135a662ad864678c9fede9817e5c02b67Robin Lee            UserHandleCompat user) {
33815940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen        synchronized (sBgLock) {
33825940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen            if (sBgWidgetProviders == null) {
338370a48befe48af0a318e88745f480d2ed42936bb5Hyunyoung Song                getWidgetProviders(ctx, false /* refresh */);
33845940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen            }
338526ace12135a662ad864678c9fede9817e5c02b67Robin Lee            return sBgWidgetProviders.get(new ComponentKey(name, user));
33865940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen        }
33875940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen    }
33885940042d39b576553c2499bcf3d0641281e6ad52Adam Cohen
33892d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal    public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {
33909110d485fa12c03df3061278717efb342f1142cfHyunyoung Song
3391eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song        runOnWorkerThread(new Runnable() {
3392d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            @Override
3393d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            public void run() {
33942d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal                updateWidgetsModel(refresh);
3395eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song                final WidgetsModel model = mBgWidgetsModel.clone();
3396eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song
3397d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                mHandler.post(new Runnable() {
3398d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                    @Override
3399d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                    public void run() {
3400d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                        Callbacks cb = getCallback();
3401d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                        if (callbacks == cb && cb != null) {
34022bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song                            callbacks.bindAllPackages(model);
3403d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                        }
3404d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                    }
3405d4af1484447129d489203130e0d654f81a10437dHyunyoung Song                });
34068821ca9a6a5bf34308f9b70c2cabf9da17330497Hyunyoung Song                // update the Widget entries inside DB on the worker thread.
34072bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song                LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
34082bd3d7d1cb5e4d8d826982d11b456739fed6b817Hyunyoung Song                        model.getRawList());
3409d4af1484447129d489203130e0d654f81a10437dHyunyoung Song            }
3410d4af1484447129d489203130e0d654f81a10437dHyunyoung Song        });
3411d4af1484447129d489203130e0d654f81a10437dHyunyoung Song    }
3412d4af1484447129d489203130e0d654f81a10437dHyunyoung Song
34138821ca9a6a5bf34308f9b70c2cabf9da17330497Hyunyoung Song    /**
34149110d485fa12c03df3061278717efb342f1142cfHyunyoung Song     * Returns a list of ResolveInfos/AppWidgetInfos.
34158821ca9a6a5bf34308f9b70c2cabf9da17330497Hyunyoung Song     *
34169110d485fa12c03df3061278717efb342f1142cfHyunyoung Song     * @see #loadAndBindWidgetsAndShortcuts
34178821ca9a6a5bf34308f9b70c2cabf9da17330497Hyunyoung Song     */
34182d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal    @Thunk void updateWidgetsModel(boolean refresh) {
34192d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal        PackageManager packageManager = mApp.getContext().getPackageManager();
3420c402cd9992d431b6beacdf3c75e31cf103e230cbMichael Jurka        final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
34212d648b057fa2d6410b1472c1b9dd5b65cd9c9414Sunny Goyal        widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
3422c402cd9992d431b6beacdf3c75e31cf103e230cbMichael Jurka        Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
3423c402cd9992d431b6beacdf3c75e31cf103e230cbMichael Jurka        widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
3424eaf291b9feba4e332d258b6d53ff119c88dc0d39Hyunyoung Song        mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
3425c402cd9992d431b6beacdf3c75e31cf103e230cbMichael Jurka    }
3426c402cd9992d431b6beacdf3c75e31cf103e230cbMichael Jurka
3427091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk static boolean isPackageDisabled(Context context, String packageName,
3428ed13187a745866483139e2878037e1f8427ce567Kenny Guy            UserHandleCompat user) {
3429ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3430ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return !launcherApps.isPackageEnabledForProfile(packageName, user);
3431df95eb12a4d288ffa143a0c3db60e7e98f3e03b9Winson Chung    }
3432556f6135f992dcd5bfbfffe0172627bfbf57d24eAdam Cohen
3433ed13187a745866483139e2878037e1f8427ce567Kenny Guy    public static boolean isValidPackageActivity(Context context, ComponentName cn,
3434ed13187a745866483139e2878037e1f8427ce567Kenny Guy            UserHandleCompat user) {
3435ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        if (cn == null) {
3436ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung            return false;
3437ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        }
3438ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3439ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (!launcherApps.isPackageEnabledForProfile(cn.getPackageName(), user)) {
3440ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung            return false;
3441ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung        }
3442ed13187a745866483139e2878037e1f8427ce567Kenny Guy        return launcherApps.isActivityEnabledForProfile(cn, user);
3443ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung    }
3444ee055715cfe5085aa7c1ff1f8a14348bd0cef604Winson Chung
3445a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen    public static boolean isValidPackage(Context context, String packageName,
3446a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen            UserHandleCompat user) {
3447a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        if (packageName == null) {
3448a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen            return false;
3449a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        }
3450a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
3451a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen        return launcherApps.isPackageEnabledForProfile(packageName, user);
3452a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen    }
3453a28b78e8385f0f590b144038157afc7d34cd48b7Adam Cohen
34549c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    /**
3455f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * Make an ShortcutInfo object for a restored application or shortcut item that points
3456f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * to a package that is not yet installed on the system.
3457f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     */
34584e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal    public ShortcutInfo getRestoredItemInfo(Cursor c, int titleIndex, Intent intent,
3459c22841bfd1961781a84cfccb98d1c2937a9adee4Sunny Goyal            int promiseType, int itemType, CursorIconInfo iconInfo, Context context) {
3460f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        final ShortcutInfo info = new ShortcutInfo();
3461349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        info.user = UserHandleCompat.myUserHandle();
34624e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal
34634e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        Bitmap icon = iconInfo.loadIcon(c, info, context);
34644e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        // the fallback icon
34654e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        if (icon == null) {
34664e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
34674e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        } else {
34684e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            info.setIcon(icon);
34694e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        }
3470349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
3471349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
34724e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            String title = (c != null) ? c.getString(titleIndex) : null;
3473349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            if (!TextUtils.isEmpty(title)) {
347482b016cb56540fe26213e817dd0dd668099c8e20Winson Chung                info.title = Utilities.trim(title);
3475349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            }
3476349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        } else if  ((promiseType & ShortcutInfo.FLAG_AUTOINTALL_ICON) != 0) {
3477349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            if (TextUtils.isEmpty(info.title)) {
34784e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal                info.title = (c != null) ? Utilities.trim(c.getString(titleIndex)) : "";
3479349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            }
3480f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        } else {
3481349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal            throw new InvalidParameterException("Invalid restoreType " + promiseType);
3482f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        }
3483349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal
348482b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
3485c22841bfd1961781a84cfccb98d1c2937a9adee4Sunny Goyal        info.itemType = itemType;
3486349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal        info.promisedIntent = intent;
3487756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        info.status = promiseType;
3488f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        return info;
3489f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    }
3490f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
3491f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    /**
3492f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * Make an Intent object for a restored application or shortcut item that points
3493f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     * to the market page for the item.
3494f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren     */
3495091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk Intent getRestoredItemIntent(Cursor c, Context context, Intent intent) {
3496f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren        ComponentName componentName = intent.getComponent();
3497e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        return getMarketIntent(componentName.getPackageName());
3498e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    }
3499e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal
3500e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal    static Intent getMarketIntent(String packageName) {
3501e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal        return new Intent(Intent.ACTION_VIEW)
3502e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal            .setData(new Uri.Builder()
3503f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                .scheme("market")
3504f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren                .authority("details")
3505e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                .appendQueryParameter("id", packageName)
3506e7b8cd9e4f8d38d0445f3a032fafd44332f70878Sunny Goyal                .build());
3507f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    }
3508f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren
3509f4d081107f5984bfb92cb1a627667fea5bf1498cChris Wren    /**
351056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     * Make an ShortcutInfo object for a shortcut that is an application.
351156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     *
351256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     * If c is not null, then it will be used to fill in missing data like the title and icon.
351356d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato     */
35144fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal    public ShortcutInfo getAppShortcutInfo(PackageManager manager, Intent intent,
3515ed13187a745866483139e2878037e1f8427ce567Kenny Guy            UserHandleCompat user, Context context, Cursor c, int iconIndex, int titleIndex,
351634b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal            boolean allowMissingTarget, boolean useLowResIcon) {
3517ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (user == null) {
3518ed13187a745866483139e2878037e1f8427ce567Kenny Guy            Log.d(TAG, "Null user found in getShortcutInfo");
3519ed13187a745866483139e2878037e1f8427ce567Kenny Guy            return null;
3520ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3521ed13187a745866483139e2878037e1f8427ce567Kenny Guy
352256d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        ComponentName componentName = intent.getComponent();
3523ed13187a745866483139e2878037e1f8427ce567Kenny Guy        if (componentName == null) {
3524ed13187a745866483139e2878037e1f8427ce567Kenny Guy            Log.d(TAG, "Missing component found in getShortcutInfo: " + componentName);
35259c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            return null;
352631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
352731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3528ed13187a745866483139e2878037e1f8427ce567Kenny Guy        Intent newIntent = new Intent(intent.getAction(), null);
3529ed13187a745866483139e2878037e1f8427ce567Kenny Guy        newIntent.addCategory(Intent.CATEGORY_LAUNCHER);
3530ed13187a745866483139e2878037e1f8427ce567Kenny Guy        newIntent.setComponent(componentName);
3531ed13187a745866483139e2878037e1f8427ce567Kenny Guy        LauncherActivityInfoCompat lai = mLauncherApps.resolveActivity(newIntent, user);
3532f599ccfe96eae7e4854bddfedd3df945feb9b7f5Sunny Goyal        if ((lai == null) && !allowMissingTarget) {
3533ed13187a745866483139e2878037e1f8427ce567Kenny Guy            Log.d(TAG, "Missing activity found in getShortcutInfo: " + componentName);
3534ed13187a745866483139e2878037e1f8427ce567Kenny Guy            return null;
3535ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3536ed13187a745866483139e2878037e1f8427ce567Kenny Guy
3537ed13187a745866483139e2878037e1f8427ce567Kenny Guy        final ShortcutInfo info = new ShortcutInfo();
353834b6527cefd36fbd5da78464ce9771e379158552Sunny Goyal        mIconCache.getTitleAndIcon(info, componentName, lai, user, false, useLowResIcon);
35394fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        if (mIconCache.isDefaultIcon(info.getIcon(mIconCache), user) && c != null) {
35404fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            Bitmap icon = Utilities.createIconBitmap(c, iconIndex, context);
35414fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal            info.setIcon(icon == null ? mIconCache.getDefaultIcon(user) : icon);
3542ed13187a745866483139e2878037e1f8427ce567Kenny Guy        }
3543ed13187a745866483139e2878037e1f8427ce567Kenny Guy
354456d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        // from the db
35454fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal        if (TextUtils.isEmpty(info.title) && c != null) {
354682b016cb56540fe26213e817dd0dd668099c8e20Winson Chung            info.title =  Utilities.trim(c.getString(titleIndex));
354756d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        }
35484fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
354956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato        // fall back to the class name of the activity
35509c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        if (info.title == null) {
355156d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato            info.title = componentName.getClassName();
35529c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        }
35534fbc3828c5ae1e8c5789ede974447fa365f3c5a1Sunny Goyal
35549c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
3555ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = user;
355682b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
3557fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal        if (lai != null) {
3558fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal            info.flags = AppInfo.initFlags(lai);
3559fa401a10e7e9341daf6f3c5949bf9331902c26d0Sunny Goyal        }
35609c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        return info;
35619c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato    }
356231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3563e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    static ArrayList<ItemInfo> filterItemInfos(Iterable<ItemInfo> infos,
356464359a53dc827797917a8d9a0697a91996789801Winson Chung            ItemInfoFilter f) {
356564359a53dc827797917a8d9a0697a91996789801Winson Chung        HashSet<ItemInfo> filtered = new HashSet<ItemInfo>();
356664359a53dc827797917a8d9a0697a91996789801Winson Chung        for (ItemInfo i : infos) {
356764359a53dc827797917a8d9a0697a91996789801Winson Chung            if (i instanceof ShortcutInfo) {
356864359a53dc827797917a8d9a0697a91996789801Winson Chung                ShortcutInfo info = (ShortcutInfo) i;
3569349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                ComponentName cn = info.getTargetComponent();
357064359a53dc827797917a8d9a0697a91996789801Winson Chung                if (cn != null && f.filterItem(null, info, cn)) {
357164359a53dc827797917a8d9a0697a91996789801Winson Chung                    filtered.add(info);
357264359a53dc827797917a8d9a0697a91996789801Winson Chung                }
357364359a53dc827797917a8d9a0697a91996789801Winson Chung            } else if (i instanceof FolderInfo) {
357464359a53dc827797917a8d9a0697a91996789801Winson Chung                FolderInfo info = (FolderInfo) i;
357564359a53dc827797917a8d9a0697a91996789801Winson Chung                for (ShortcutInfo s : info.contents) {
3576349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal                    ComponentName cn = s.getTargetComponent();
357764359a53dc827797917a8d9a0697a91996789801Winson Chung                    if (cn != null && f.filterItem(info, s, cn)) {
357864359a53dc827797917a8d9a0697a91996789801Winson Chung                        filtered.add(s);
35798a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung                    }
35808a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung                }
358164359a53dc827797917a8d9a0697a91996789801Winson Chung            } else if (i instanceof LauncherAppWidgetInfo) {
358264359a53dc827797917a8d9a0697a91996789801Winson Chung                LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) i;
358364359a53dc827797917a8d9a0697a91996789801Winson Chung                ComponentName cn = info.providerName;
358464359a53dc827797917a8d9a0697a91996789801Winson Chung                if (cn != null && f.filterItem(null, info, cn)) {
358564359a53dc827797917a8d9a0697a91996789801Winson Chung                    filtered.add(info);
358664359a53dc827797917a8d9a0697a91996789801Winson Chung                }
35878a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung            }
35888a4351063f02c0e8d64ee3ace651b227e9f8321fWinson Chung        }
358964359a53dc827797917a8d9a0697a91996789801Winson Chung        return new ArrayList<ItemInfo>(filtered);
359064359a53dc827797917a8d9a0697a91996789801Winson Chung    }
359164359a53dc827797917a8d9a0697a91996789801Winson Chung
3592091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk ArrayList<ItemInfo> getItemInfoForComponentName(final ComponentName cname,
3593ed13187a745866483139e2878037e1f8427ce567Kenny Guy            final UserHandleCompat user) {
359464359a53dc827797917a8d9a0697a91996789801Winson Chung        ItemInfoFilter filter  = new ItemInfoFilter() {
359564359a53dc827797917a8d9a0697a91996789801Winson Chung            @Override
359664359a53dc827797917a8d9a0697a91996789801Winson Chung            public boolean filterItem(ItemInfo parent, ItemInfo info, ComponentName cn) {
3597ed13187a745866483139e2878037e1f8427ce567Kenny Guy                if (info.user == null) {
3598ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return cn.equals(cname);
3599ed13187a745866483139e2878037e1f8427ce567Kenny Guy                } else {
3600ed13187a745866483139e2878037e1f8427ce567Kenny Guy                    return cn.equals(cname) && info.user.equals(user);
3601ed13187a745866483139e2878037e1f8427ce567Kenny Guy                }
360264359a53dc827797917a8d9a0697a91996789801Winson Chung            }
360364359a53dc827797917a8d9a0697a91996789801Winson Chung        };
3604e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal        return filterItemInfos(sBgItemsIdMap, filter);
360564359a53dc827797917a8d9a0697a91996789801Winson Chung    }
360664359a53dc827797917a8d9a0697a91996789801Winson Chung
36071a745e8f18e54aff152ff51743ae7595adde6927Sunny Goyal    /**
36080589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato     * Make an ShortcutInfo object for a shortcut that isn't an application.
36099c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     */
3610091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk ShortcutInfo getShortcutInfo(Cursor c, Context context,
36114e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal            int titleIndex, CursorIconInfo iconInfo) {
3612c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ShortcutInfo info = new ShortcutInfo();
3613ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // Non-app shortcuts are only supported for current user.
3614ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = UserHandleCompat.myUserHandle();
36159c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
36167376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project
36178ddc4fdba06cfa786950c306475b7a4e3f6846abJoe Onorato        // TODO: If there's an explicit component and we can't install that, delete it.
36188ddc4fdba06cfa786950c306475b7a4e3f6846abJoe Onorato
361982b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.title = Utilities.trim(c.getString(titleIndex));
362056d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
36214e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        Bitmap icon = iconInfo.loadIcon(c, info, context);
36224e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        // the fallback icon
36234e5cc64eaf1f63d866d51ce0a6bbafb3d4085c21Sunny Goyal        if (icon == null) {
3624ed13187a745866483139e2878037e1f8427ce567Kenny Guy            icon = mIconCache.getDefaultIcon(info.user);
362556d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato            info.usingFallbackIcon = true;
362631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
3627d8d22da5ca3e8d3e8d2e3616305b038d37486f32Joe Onorato        info.setIcon(icon);
36289c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        return info;
3629f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project    }
363031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
36312350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal    ShortcutInfo infoFromShortcutIntent(Context context, Intent data) {
36320589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
36330589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
36340589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Parcelable bitmap = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON);
36350589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
3636d919882006a457d16dea46bd546472e6534b5c19Adam Cohen        if (intent == null) {
3637d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            // If the intent is null, we can't construct a valid ShortcutInfo, so we return null
3638d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            Log.e(TAG, "Can't construct ShorcutInfo with null intent");
3639d919882006a457d16dea46bd546472e6534b5c19Adam Cohen            return null;
3640d919882006a457d16dea46bd546472e6534b5c19Adam Cohen        }
3641d919882006a457d16dea46bd546472e6534b5c19Adam Cohen
36420589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        Bitmap icon = null;
36430589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        boolean customIcon = false;
36440589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        ShortcutIconResource iconResource = null;
36450589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
36462fce90c38a79d318e96a28107dea287e42509861Sunny Goyal        if (bitmap instanceof Bitmap) {
36472fce90c38a79d318e96a28107dea287e42509861Sunny Goyal            icon = Utilities.createIconBitmap((Bitmap) bitmap, context);
36480589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            customIcon = true;
36490589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        } else {
36500589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            Parcelable extra = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
3651b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal            if (extra instanceof ShortcutIconResource) {
3652b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                iconResource = (ShortcutIconResource) extra;
3653b50cc8c5d6125715b139d978887830a5341971aaSunny Goyal                icon = Utilities.createIconBitmap(iconResource.packageName,
365453d7ee4285842732517edcccbdcaa92dccb1e107Sunny Goyal                        iconResource.resourceName, context);
36550589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato            }
36560589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
36570589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
3658c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka        final ShortcutInfo info = new ShortcutInfo();
365956d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
3660ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // Only support intents for current user for now. Intents sent from other
3661ed13187a745866483139e2878037e1f8427ce567Kenny Guy        // users wouldn't get here without intent forwarding anyway.
3662ed13187a745866483139e2878037e1f8427ce567Kenny Guy        info.user = UserHandleCompat.myUserHandle();
36630589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        if (icon == null) {
36642350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal            icon = mIconCache.getDefaultIcon(info.user);
36652350bc97851eea1662eee43d61290eb7a8382021Sunny Goyal            info.usingFallbackIcon = true;
36660589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        }
36670589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.setIcon(icon);
366856d8291af6a28c6ba64113120efdf84a785e816cJoe Onorato
366982b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.title = Utilities.trim(name);
367082b016cb56540fe26213e817dd0dd668099c8e20Winson Chung        info.contentDescription = mUserManager.getBadgedLabelForUser(info.title, info.user);
36710589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.intent = intent;
36720589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.customIcon = customIcon;
36730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        info.iconResource = iconResource;
36740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
36750589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato        return info;
36760589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato    }
36770589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato
367831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    /**
3679df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen     * Return an existing FolderInfo object if we have encountered this ID previously,
36809c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato     * or make a new one.
368131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project     */
3682e2df0620c13b9dc7e63224153b98fdbb48546f9bSunny Goyal    @Thunk static FolderInfo findOrMakeFolder(LongArrayMap<FolderInfo> folders, long id) {
36839c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        // See if a placeholder was created for us already
36849c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato        FolderInfo folderInfo = folders.get(id);
3685df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        if (folderInfo == null) {
36869c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            // No placeholder -- create a new instance
3687c9d95c5897fc5ebbf53903d4ab18ad13d196f643Michael Jurka            folderInfo = new FolderInfo();
36889c1289cb3bfb74f86e53ec7ac6dd76bb39666b2dJoe Onorato            folders.put(id, folderInfo);
368931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project        }
3690df2cc41acbfacd576f99483a4af1cda32ebd3d09Adam Cohen        return folderInfo;
369131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project    }
369231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project
3693be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato
3694651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal    static boolean isValidProvider(AppWidgetProviderInfo provider) {
3695651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal        return (provider != null) && (provider.provider != null)
3696651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal                && (provider.provider.getPackageName() != null);
3697651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal    }
3698651077bdd603bb182be039925fd17bdf0da15016Sunny Goyal
3699be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato    public void dumpState() {
3700be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato        Log.d(TAG, "mCallbacks=" + mCallbacks);
3701eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mBgAllAppsList.data);
3702eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mBgAllAppsList.added);
3703eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mBgAllAppsList.removed);
3704eadbfc564d84aaf1d800da3d0d6edf6312f89648Michael Jurka        AppInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mBgAllAppsList.modified);
37053611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        if (mLoaderTask != null) {
37063611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            mLoaderTask.dumpState();
37073611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        } else {
37083611578579b4bfb25616085dafdb1a45207394f9Joe Onorato            Log.d(TAG, "mLoaderTask=null");
37093611578579b4bfb25616085dafdb1a45207394f9Joe Onorato        }
3710be38609f875f9b9374ceaf723135c0a624637fcbJoe Onorato    }
3711e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
3712e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    public Callbacks getCallback() {
3713e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal        return mCallbacks != null ? mCallbacks.get() : null;
3714e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    }
371518bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal
371618bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    /**
371718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal     * @return {@link FolderInfo} if its already loaded.
371818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal     */
371918bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public FolderInfo findFolderById(Long folderId) {
372018bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal        synchronized (sBgLock) {
372118bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal            return sBgFolders.get(folderId);
372218bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal        }
372318bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    }
3724756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal
3725756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    /**
3726756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     * @return the looper for the worker thread which can be used to start background tasks.
3727756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal     */
3728756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    public static Looper getWorkerLooper() {
3729756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal        return sWorkerThread.getLooper();
3730756adbc3e41ee1edb53c580b8c679f343924fab5Sunny Goyal    }
373131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project}
3732