From c6e97692e4144a6fc33eb74fabb73b1aae9ff908 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 2 Jun 2017 13:46:55 -0700 Subject: [PATCH] Moving LoaderTask static Will move it to a separate file in a followup cl. This simplifies dependencies between LauncherModel and LoaderTask which and making it easier to start the loader before Launcher activity is created (as the Callbacks in LauncherModel can change while loader is running). Bug: 34112546 Bug: 37616877 Change-Id: Ie9619c6b0de0e3eb60657c04ae1b58d946c829e9 --- src/com/android/launcher3/AppFilter.java | 5 + src/com/android/launcher3/Launcher.java | 2 +- .../android/launcher3/LauncherAppState.java | 4 +- src/com/android/launcher3/LauncherModel.java | 300 +++++++++--------- .../android/launcher3/model/BgDataModel.java | 10 + .../launcher3/model/ExtendedModelTask.java | 11 + .../launcher3/model/LoaderResults.java | 17 +- .../launcher3/model/PackageUpdatedTask.java | 7 +- .../model/SdCardAvailableReceiver.java | 7 +- .../android/launcher3/model/WidgetsModel.java | 41 ++- 10 files changed, 215 insertions(+), 189 deletions(-) diff --git a/src/com/android/launcher3/AppFilter.java b/src/com/android/launcher3/AppFilter.java index db8f5dd0e0..923835a679 100644 --- a/src/com/android/launcher3/AppFilter.java +++ b/src/com/android/launcher3/AppFilter.java @@ -1,9 +1,14 @@ package com.android.launcher3; import android.content.ComponentName; +import android.content.Context; public class AppFilter { + public static AppFilter newInstance(Context context) { + return Utilities.getOverrideObject(AppFilter.class, context, R.string.app_filter_class); + } + public boolean shouldShowApp(ComponentName app) { return true; } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index ff7ca812bf..c8c5661878 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3970,7 +3970,7 @@ public class Launcher extends BaseActivity * refreshes the widgets and shortcuts associated with the given package/user */ public void refreshAndBindWidgetsForPackageUser(@Nullable PackageUserKey packageUser) { - mModel.refreshAndBindWidgetsAndShortcuts(this, mWidgetsView.isEmpty(), packageUser); + mModel.refreshAndBindWidgetsAndShortcuts(packageUser); } public void lockScreenOrientation() { diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 27ccabea9c..cf20febd5b 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -93,9 +93,7 @@ public class LauncherAppState { mInvariantDeviceProfile = new InvariantDeviceProfile(mContext); mIconCache = new IconCache(mContext, mInvariantDeviceProfile); mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); - - mModel = new LauncherModel(this, mIconCache, - Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class)); + mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext)); LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel); diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index ee06d9e587..265c7e33ad 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -69,7 +69,6 @@ import com.android.launcher3.model.SdCardAvailableReceiver; import com.android.launcher3.model.ShortcutsChangedTask; import com.android.launcher3.model.UserLockStateChangedTask; import com.android.launcher3.model.WidgetItem; -import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.provider.ImportDataTask; import com.android.launcher3.provider.LauncherDbUtils; import com.android.launcher3.shortcuts.DeepShortcutManager; @@ -116,7 +115,6 @@ public class LauncherModel extends BroadcastReceiver @Thunk final Object mLock = new Object(); @Thunk LoaderTask mLoaderTask; @Thunk boolean mIsLoaderTaskRunning; - @Thunk boolean mHasLoaderCompletedOnce; @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader"); static { @@ -139,23 +137,6 @@ public class LauncherModel extends BroadcastReceiver // < only access in worker thread > private final AllAppsList mBgAllAppsList; - // Entire list of widgets. - private final WidgetsModel mBgWidgetsModel; - - private boolean mHasShortcutHostPermission; - // Runnable to check if the shortcuts permission has changed. - private final Runnable mShortcutPermissionCheckRunnable = new Runnable() { - @Override - public void run() { - if (mModelLoaded) { - boolean hasShortcutHostPermission = - DeepShortcutManager.getInstance(mApp.getContext()).hasHostPermission(); - if (hasShortcutHostPermission != mHasShortcutHostPermission) { - forceReload(); - } - } - } - }; /** * All the static data should be accessed on the background thread, A lock should be acquired @@ -163,12 +144,19 @@ public class LauncherModel extends BroadcastReceiver */ static final BgDataModel sBgDataModel = new BgDataModel(); - // - - private final IconCache mIconCache; - - private final LauncherAppsCompat mLauncherApps; - private final UserManagerCompat mUserManager; + // Runnable to check if the shortcuts permission has changed. + private final Runnable mShortcutPermissionCheckRunnable = new Runnable() { + @Override + public void run() { + if (mModelLoaded) { + boolean hasShortcutHostPermission = + DeepShortcutManager.getInstance(mApp.getContext()).hasHostPermission(); + if (hasShortcutHostPermission != sBgDataModel.hasShortcutHostPermission) { + forceReload(); + } + } + } + }; public interface Callbacks { public boolean setLoadOnResume(); @@ -204,14 +192,8 @@ public class LauncherModel extends BroadcastReceiver } LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) { - Context context = app.getContext(); mApp = app; mBgAllAppsList = new AllAppsList(iconCache, appFilter); - mBgWidgetsModel = new WidgetsModel(iconCache, appFilter); - mIconCache = iconCache; - - mLauncherApps = LauncherAppsCompat.getInstance(context); - mUserManager = UserManagerCompat.getInstance(context); } /** Runs the specified runnable immediately if called from the worker thread, otherwise it is @@ -539,9 +521,10 @@ public class LauncherModel extends BroadcastReceiver // issues that arise from that. loaderResults.bindAllApps(); loaderResults.bindDeepShortcuts(); + loaderResults.bindWidgets(); return true; } else { - mLoaderTask = new LoaderTask(mApp.getContext(), loaderResults); + mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, loaderResults); sWorker.post(mLoaderTask); } } @@ -588,6 +571,44 @@ public class LauncherModel extends BroadcastReceiver }); } + public class LoaderTransaction implements AutoCloseable { + + private final LoaderTask mTask; + + private LoaderTransaction(LoaderTask task) throws CancellationException { + synchronized (mLock) { + if (mLoaderTask != task) { + throw new CancellationException("Loader already stopped"); + } + mTask = task; + mIsLoaderTaskRunning = true; + mModelLoaded = false; + } + } + + public void commit() { + synchronized (mLock) { + // Everything loaded bind the data. + mModelLoaded = true; + } + } + + @Override + public void close() { + synchronized (mLock) { + // If we are still the last one to be scheduled, remove ourselves. + if (mLoaderTask == mTask) { + mLoaderTask = null; + } + mIsLoaderTaskRunning = false; + } + } + } + + public LoaderTransaction beginLoader(LoaderTask task) throws CancellationException { + return new LoaderTransaction(task); + } + /** * Runnable for the thread that loads the contents of the launcher: * - workspace icons @@ -595,46 +616,62 @@ public class LauncherModel extends BroadcastReceiver * - all apps icons * - deep shortcuts within apps */ - private class LoaderTask implements Runnable { - private Context mContext; + private static class LoaderTask implements Runnable { + private final LauncherAppState mApp; + private final AllAppsList mBgAllAppsList; + private final BgDataModel mBgDataModel; + private final LoaderResults mResults; + private final LauncherAppsCompat mLauncherApps; + private final UserManagerCompat mUserManager; + private final DeepShortcutManager mShortcutManager; + private final PackageInstallerCompat mPackageInstaller; + private final AppWidgetManagerCompat mAppWidgetManager; + private final IconCache mIconCache; + private boolean mStopped; - LoaderTask(Context context, LoaderResults results) { - mContext = context; + LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel, + LoaderResults results) { + mApp = app; + mBgAllAppsList = bgAllAppsList; + mBgDataModel = dataModel; mResults = results; + + mLauncherApps = LauncherAppsCompat.getInstance(mApp.getContext()); + mUserManager = UserManagerCompat.getInstance(mApp.getContext()); + mShortcutManager = DeepShortcutManager.getInstance(mApp.getContext()); + mPackageInstaller = PackageInstallerCompat.getInstance(mApp.getContext()); + mAppWidgetManager = AppWidgetManagerCompat.getInstance(mApp.getContext()); + mIconCache = mApp.getIconCache(); } - private void waitForIdle() { + private synchronized void waitForIdle() { // Wait until the either we're stopped or the other threads are done. // This way we don't start loading all apps until the workspace has settled // down. - synchronized (LoaderTask.this) { - LooperIdleLock idleLock = new LooperIdleLock(this, Looper.getMainLooper()); - // Just in case mFlushingWorkerThread changes but we aren't woken up, - // wait no longer than 1sec at a time - while (!mStopped && idleLock.awaitLocked(1000)); - } + LooperIdleLock idleLock = new LooperIdleLock(this, Looper.getMainLooper()); + // Just in case mFlushingWorkerThread changes but we aren't woken up, + // wait no longer than 1sec at a time + while (!mStopped && idleLock.awaitLocked(1000)); } - private void verifyNotStopped() throws CancellationException { - synchronized (LoaderTask.this) { - if (mStopped) { - throw new CancellationException("Loader stopped"); - } + private synchronized void verifyNotStopped() throws CancellationException { + if (mStopped) { + throw new CancellationException("Loader stopped"); } } public void run() { - synchronized (mLock) { + synchronized (this) { + // Skip fast if we are already stopped. if (mStopped) { return; } - mIsLoaderTaskRunning = true; } - try { + try (LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { long now = 0; if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace"); loadWorkspace(); @@ -688,36 +725,21 @@ public class LauncherModel extends BroadcastReceiver // fourth step if (DEBUG_LOADERS) Log.d(TAG, "step 4.1: loading widgets"); - refreshAndBindWidgetsAndShortcuts(getCallback(), false /* bindFirst */, - null /* packageUser */); + mBgDataModel.widgetsModel.update(mApp, null); - synchronized (mLock) { - // Everything loaded bind the data. - mModelLoaded = true; - mHasLoaderCompletedOnce = true; - } + verifyNotStopped(); + if (DEBUG_LOADERS) Log.d(TAG, "step 4.2: Binding widgets"); + mResults.bindWidgets(); + + transaction.commit(); } catch (CancellationException e) { // Loader stopped, ignore - } finally { - // Clear out this reference, otherwise we end up holding it until all of the - // callback runnables are done. - mContext = null; - - synchronized (mLock) { - // If we are still the last one to be scheduled, remove ourselves. - if (mLoaderTask == this) { - mLoaderTask = null; - } - mIsLoaderTaskRunning = false; - } } } - public void stopLocked() { - synchronized (LoaderTask.this) { - mStopped = true; - this.notify(); - } + public synchronized void stopLocked() { + mStopped = true; + this.notify(); } private void loadWorkspace() { @@ -725,12 +747,10 @@ public class LauncherModel extends BroadcastReceiver Trace.beginSection("Loading Workspace"); } - final Context context = mContext; + final Context context = mApp.getContext(); final ContentResolver contentResolver = context.getContentResolver(); final PackageManagerHelper pmHelper = new PackageManagerHelper(context); final boolean isSafeMode = pmHelper.isSafeMode(); - final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context); - final DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(context); final boolean isSdCardReady = Utilities.isBootCompleted(); final MultiHashMap pendingPackages = new MultiHashMap<>(); @@ -743,7 +763,7 @@ public class LauncherModel extends BroadcastReceiver } if (!clearDb && GridSizeMigrationTask.ENABLED && - !GridSizeMigrationTask.migrateGridIfNeeded(mContext)) { + !GridSizeMigrationTask.migrateGridIfNeeded(context)) { // Migration failed. Clear workspace. clearDb = true; } @@ -758,12 +778,12 @@ public class LauncherModel extends BroadcastReceiver LauncherSettings.Settings.call(contentResolver, LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES); - synchronized (sBgDataModel) { - sBgDataModel.clear(); + synchronized (mBgDataModel) { + mBgDataModel.clear(); - final HashMap installingPkgs = PackageInstallerCompat - .getInstance(mContext).updateAndGetActiveSessionCache(); - sBgDataModel.workspaceScreens.addAll(loadWorkspaceScreensDb(mContext)); + final HashMap installingPkgs = + mPackageInstaller.updateAndGetActiveSessionCache(); + mBgDataModel.workspaceScreens.addAll(loadWorkspaceScreensDb(context)); Map shortcutKeyToPinnedShortcuts = new HashMap<>(); final LoaderCursor c = new LoaderCursor(contentResolver.query( @@ -798,8 +818,8 @@ public class LauncherModel extends BroadcastReceiver // We can only query for shortcuts when the user is unlocked. if (userUnlocked) { List pinnedShortcuts = - shortcutManager.queryForPinnedShortcuts(null, user); - if (shortcutManager.wasLastCallSuccess()) { + mShortcutManager.queryForPinnedShortcuts(null, user); + if (mShortcutManager.wasLastCallSuccess()) { for (ShortcutInfoCompat shortcut : pinnedShortcuts) { shortcutKeyToPinnedShortcuts.put(ShortcutKey.fromInfo(shortcut), shortcut); @@ -864,14 +884,14 @@ public class LauncherModel extends BroadcastReceiver // If there is no target package, its an implicit intent // (legacy shortcut) which is always valid boolean validTarget = TextUtils.isEmpty(targetPkg) || - launcherApps.isPackageEnabledForProfile(targetPkg, c.user); + mLauncherApps.isPackageEnabledForProfile(targetPkg, c.user); if (cn != null && validTarget) { // If the apk is present and the shortcut points to a specific // component. // If the component is already present - if (launcherApps.isActivityEnabledForProfile(cn, c.user)) { + if (mLauncherApps.isActivityEnabledForProfile(cn, c.user)) { // no special handling necessary for this item c.markRestored(); } else { @@ -1022,14 +1042,14 @@ public class LauncherModel extends BroadcastReceiver } } - c.checkAndAddItem(info, sBgDataModel); + c.checkAndAddItem(info, mBgDataModel); } else { throw new RuntimeException("Unexpected null ShortcutInfo"); } break; case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: - FolderInfo folderInfo = sBgDataModel.findOrMakeFolder(c.id); + FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id); c.applyCommonProperties(folderInfo); // Do not trim the folder label, as is was set by the user. @@ -1041,7 +1061,7 @@ public class LauncherModel extends BroadcastReceiver // no special handling required for restored folders c.markRestored(); - c.checkAndAddItem(folderInfo, sBgDataModel); + c.checkAndAddItem(folderInfo, mBgDataModel); break; case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: @@ -1062,8 +1082,7 @@ public class LauncherModel extends BroadcastReceiver LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY); if (widgetProvidersMap == null) { - widgetProvidersMap = AppWidgetManagerCompat - .getInstance(mContext).getAllProvidersMap(); + widgetProvidersMap = mAppWidgetManager.getAllProvidersMap(); } final AppWidgetProviderInfo provider = widgetProvidersMap.get( new ComponentKey( @@ -1161,7 +1180,7 @@ public class LauncherModel extends BroadcastReceiver appWidgetInfo.pendingItemInfo, false); } - c.checkAndAddItem(appWidgetInfo, sBgDataModel); + c.checkAndAddItem(appWidgetInfo, mBgDataModel); } break; } @@ -1175,7 +1194,7 @@ public class LauncherModel extends BroadcastReceiver // Break early if we've stopped loading if (mStopped) { - sBgDataModel.clear(); + mBgDataModel.clear(); return; } @@ -1187,9 +1206,9 @@ public class LauncherModel extends BroadcastReceiver LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS) .getSerializable(LauncherSettings.Settings.EXTRA_VALUE); for (long folderId : deletedFolderIds) { - sBgDataModel.workspaceItems.remove(sBgDataModel.folders.get(folderId)); - sBgDataModel.folders.remove(folderId); - sBgDataModel.itemsIdMap.remove(folderId); + mBgDataModel.workspaceItems.remove(mBgDataModel.folders.get(folderId)); + mBgDataModel.folders.remove(folderId); + mBgDataModel.itemsIdMap.remove(folderId); } // Remove any ghost widgets @@ -1201,18 +1220,18 @@ public class LauncherModel extends BroadcastReceiver HashSet pendingShortcuts = InstallShortcutReceiver.getPendingShortcuts(context); for (ShortcutKey key : shortcutKeyToPinnedShortcuts.keySet()) { - MutableInt numTimesPinned = sBgDataModel.pinnedShortcutCounts.get(key); + MutableInt numTimesPinned = mBgDataModel.pinnedShortcutCounts.get(key); if ((numTimesPinned == null || numTimesPinned.value == 0) && !pendingShortcuts.contains(key)) { // Shortcut is pinned but doesn't exist on the workspace; unpin it. - shortcutManager.unpinShortcut(key); + mShortcutManager.unpinShortcut(key); } } FolderIconPreviewVerifier verifier = new FolderIconPreviewVerifier(mApp.getInvariantDeviceProfile()); // Sort the folder items and make sure all items in the preview are high resolution. - for (FolderInfo folder : sBgDataModel.folders) { + for (FolderInfo folder : mBgDataModel.folders) { Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR); verifier.setFolderInfo(folder); @@ -1234,16 +1253,15 @@ public class LauncherModel extends BroadcastReceiver c.commitRestoredItems(); if (!isSdCardReady && !pendingPackages.isEmpty()) { context.registerReceiver( - new SdCardAvailableReceiver( - LauncherModel.this, mContext, pendingPackages), + new SdCardAvailableReceiver(mApp, pendingPackages), new IntentFilter(Intent.ACTION_BOOT_COMPLETED), null, sWorker); } // Remove any empty screens - ArrayList unusedScreens = new ArrayList<>(sBgDataModel.workspaceScreens); - for (ItemInfo item: sBgDataModel.itemsIdMap) { + ArrayList unusedScreens = new ArrayList<>(mBgDataModel.workspaceScreens); + for (ItemInfo item: mBgDataModel.itemsIdMap) { long screenId = item.screenId; if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP && unusedScreens.contains(screenId)) { @@ -1253,8 +1271,8 @@ public class LauncherModel extends BroadcastReceiver // If there are any empty screens remove them, and update. if (unusedScreens.size() != 0) { - sBgDataModel.workspaceScreens.removeAll(unusedScreens); - updateWorkspaceScreenOrder(context, sBgDataModel.workspaceScreens); + mBgDataModel.workspaceScreens.removeAll(unusedScreens); + updateWorkspaceScreenOrder(context, mBgDataModel.workspaceScreens); } } if (LauncherAppState.PROFILE_STARTUP) { @@ -1265,8 +1283,8 @@ public class LauncherModel extends BroadcastReceiver private void updateIconCache() { // Ignore packages which have a promise icon. HashSet packagesToIgnore = new HashSet<>(); - synchronized (sBgDataModel) { - for (ItemInfo info : sBgDataModel.itemsIdMap) { + synchronized (mBgDataModel) { + for (ItemInfo info : mBgDataModel.itemsIdMap) { if (info instanceof ShortcutInfo) { ShortcutInfo si = (ShortcutInfo) info; if (si.isPromise() && si.getTargetComponent() != null) { @@ -1312,14 +1330,14 @@ public class LauncherModel extends BroadcastReceiver mBgAllAppsList.add(new AppInfo(app, user, quietMode), app); } - ManagedProfileHeuristic.onAllAppsLoaded(mContext, apps, user); + ManagedProfileHeuristic.onAllAppsLoaded(mApp.getContext(), apps, user); } if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) { // get all active sessions and add them to the all apps list - PackageInstallerCompat installer = PackageInstallerCompat.getInstance(mContext); - for (PackageInstaller.SessionInfo info : installer.getAllVerifiedSessions()) { - mBgAllAppsList.addPromiseApp(mContext, + for (PackageInstaller.SessionInfo info : + mPackageInstaller.getAllVerifiedSessions()) { + mBgAllAppsList.addPromiseApp(mApp.getContext(), PackageInstallInfo.fromInstallingState(info)); } } @@ -1332,15 +1350,14 @@ public class LauncherModel extends BroadcastReceiver } private void loadDeepShortcuts() { - sBgDataModel.deepShortcutMap.clear(); - DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(mContext); - mHasShortcutHostPermission = shortcutManager.hasHostPermission(); - if (mHasShortcutHostPermission) { + mBgDataModel.deepShortcutMap.clear(); + mBgDataModel.hasShortcutHostPermission = mShortcutManager.hasHostPermission(); + if (mBgDataModel.hasShortcutHostPermission) { for (UserHandle user : mUserManager.getUserProfiles()) { if (mUserManager.isUserUnlocked(user)) { List shortcuts = - shortcutManager.queryForAllShortcuts(user); - sBgDataModel.updateDeepShortcutMap(null, user, shortcuts); + mShortcutManager.queryForAllShortcuts(user); + mBgDataModel.updateDeepShortcutMap(null, user, shortcuts); } } } @@ -1370,12 +1387,6 @@ public class LauncherModel extends BroadcastReceiver } public void enqueueModelUpdateTask(BaseModelUpdateTask task) { - if (!mModelLoaded && mLoaderTask == null) { - if (DEBUG_LOADERS) { - Log.d(TAG, "enqueueModelUpdateTask Ignoring task since loader is pending=" + task); - } - return; - } task.init(this); runOnWorkerThread(task); } @@ -1404,8 +1415,11 @@ public class LauncherModel extends BroadcastReceiver } @Override - public void run() { - if (!mModel.mHasLoaderCompletedOnce) { + public final void run() { + if (!mModel.mModelLoaded) { + if (DEBUG_LOADERS) { + Log.d(TAG, "Ignoring model task since loader is pending=" + this); + } // Loader has not yet run. return; } @@ -1465,34 +1479,12 @@ public class LauncherModel extends BroadcastReceiver }); } - private void bindWidgetsModel(final Callbacks callbacks) { - final MultiHashMap widgets - = mBgWidgetsModel.getWidgetsMap().clone(); - mUiExecutor.execute(new Runnable() { + public void refreshAndBindWidgetsAndShortcuts(@Nullable final PackageUserKey packageUser) { + enqueueModelUpdateTask(new ExtendedModelTask() { @Override - public void run() { - Callbacks cb = getCallback(); - if (callbacks == cb && cb != null) { - callbacks.bindAllWidgets(widgets); - } - } - }); - } - - public void refreshAndBindWidgetsAndShortcuts(final Callbacks callbacks, - final boolean bindFirst, @Nullable final PackageUserKey packageUser) { - runOnWorkerThread(new Runnable() { - @Override - public void run() { - if (bindFirst && !mBgWidgetsModel.isEmpty()) { - bindWidgetsModel(callbacks); - } - ArrayList widgets = mBgWidgetsModel.update( - mApp.getContext(), packageUser); - bindWidgetsModel(callbacks); - - // update the Widget entries inside DB on the worker thread. - mApp.getWidgetCache().removeObsoletePreviews(widgets, packageUser); + public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { + dataModel.widgetsModel.update(app, packageUser); + bindUpdatedWidgets(dataModel); } }); } diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index be93be4dc3..d9c5143f2e 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -90,11 +90,21 @@ public class BgDataModel { */ public final Map pinnedShortcutCounts = new HashMap<>(); + /** + * True if the launcher has permission to access deep shortcuts. + */ + public boolean hasShortcutHostPermission; + /** * Maps all launcher activities to the id's of their shortcuts (if they have any). */ public final MultiHashMap deepShortcutMap = new MultiHashMap<>(); + /** + * Entire list of widgets. + */ + public final WidgetsModel widgetsModel = new WidgetsModel(); + /** * Clears all the data */ diff --git a/src/com/android/launcher3/model/ExtendedModelTask.java b/src/com/android/launcher3/model/ExtendedModelTask.java index 05419662bc..080aaf54b0 100644 --- a/src/com/android/launcher3/model/ExtendedModelTask.java +++ b/src/com/android/launcher3/model/ExtendedModelTask.java @@ -59,4 +59,15 @@ public abstract class ExtendedModelTask extends BaseModelUpdateTask { } }); } + + public void bindUpdatedWidgets(BgDataModel dataModel) { + final MultiHashMap widgets + = dataModel.widgetsModel.getWidgetsMap(); + scheduleCallbackTask(new CallbackTask() { + @Override + public void execute(Callbacks callbacks) { + callbacks.bindAllWidgets(widgets); + } + }); + } } diff --git a/src/com/android/launcher3/model/LoaderResults.java b/src/com/android/launcher3/model/LoaderResults.java index 61fd356b8d..28df64d39d 100644 --- a/src/com/android/launcher3/model/LoaderResults.java +++ b/src/com/android/launcher3/model/LoaderResults.java @@ -24,6 +24,7 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; +import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.Callbacks; import com.android.launcher3.LauncherSettings; import com.android.launcher3.MainThreadExecutor; @@ -58,6 +59,7 @@ public class LoaderResults { private final BgDataModel mBgDataModel; private final AllAppsList mBgAllAppsList; private final int mPageToBindFirst; + private final WeakReference mCallbacks; public LoaderResults(LauncherAppState app, BgDataModel dataModel, @@ -358,7 +360,6 @@ public class LoaderResults { mUiExecutor.execute(r); } - public void bindAllApps() { // shallow copy @SuppressWarnings("unchecked") @@ -374,4 +375,18 @@ public class LoaderResults { }; mUiExecutor.execute(r); } + + public void bindWidgets() { + final MultiHashMap widgets + = mBgDataModel.widgetsModel.getWidgetsMap(); + Runnable r = new Runnable() { + public void run() { + Callbacks callbacks = mCallbacks.get(); + if (callbacks != null) { + callbacks.bindAllWidgets(widgets); + } + } + }; + mUiExecutor.execute(r); + } } diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index 8380f01361..46fea218fc 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -44,6 +44,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.LauncherIcons; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; @@ -373,11 +374,9 @@ public class PackageUpdatedTask extends ExtendedModelTask { } else if (Utilities.isAtLeastO() && mOp == OP_ADD) { // Load widgets for the new package. for (int i = 0; i < N; i++) { - LauncherModel model = app.getModel(); - model.refreshAndBindWidgetsAndShortcuts( - model.getCallback(), false /* bindFirst */, - new PackageUserKey(packages[i], mUser) /* packageUser */); + dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser)); } + bindUpdatedWidgets(dataModel); } } } diff --git a/src/com/android/launcher3/model/SdCardAvailableReceiver.java b/src/com/android/launcher3/model/SdCardAvailableReceiver.java index bae5c73c1b..3aedae69aa 100644 --- a/src/com/android/launcher3/model/SdCardAvailableReceiver.java +++ b/src/com/android/launcher3/model/SdCardAvailableReceiver.java @@ -21,6 +21,7 @@ import android.content.Context; import android.content.Intent; import android.os.UserHandle; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.util.MultiHashMap; @@ -43,10 +44,10 @@ public class SdCardAvailableReceiver extends BroadcastReceiver { private final Context mContext; private final MultiHashMap mPackages; - public SdCardAvailableReceiver(LauncherModel model, Context context, + public SdCardAvailableReceiver(LauncherAppState app, MultiHashMap packages) { - mModel = model; - mContext = context; + mModel = app.getModel(); + mContext = app.getContext(); mPackages = packages; } diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java index 827675a833..ed900bf358 100644 --- a/src/com/android/launcher3/model/WidgetsModel.java +++ b/src/com/android/launcher3/model/WidgetsModel.java @@ -38,36 +38,26 @@ public class WidgetsModel { private static final boolean DEBUG = false; /* Map of widgets and shortcuts that are tracked per package. */ - private final MultiHashMap mWidgetsList; + private final MultiHashMap mWidgetsList = new MultiHashMap<>(); - private final IconCache mIconCache; - private final AppFilter mAppFilter; + private AppFilter mAppFilter; - public WidgetsModel(IconCache iconCache, AppFilter appFilter) { - mIconCache = iconCache; - mAppFilter = appFilter; - mWidgetsList = new MultiHashMap<>(); - } - - public MultiHashMap getWidgetsMap() { - return mWidgetsList; - } - - public boolean isEmpty() { - return mWidgetsList.isEmpty(); + public synchronized MultiHashMap getWidgetsMap() { + return mWidgetsList.clone(); } /** * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise * only widgets and shortcuts associated with the package/user are. */ - public ArrayList update(Context context, @Nullable PackageUserKey packageUser) { + public void update(LauncherAppState app, @Nullable PackageUserKey packageUser) { Preconditions.assertWorkerThread(); + Context context = app.getContext(); final ArrayList widgetsAndShortcuts = new ArrayList<>(); try { PackageManager pm = context.getPackageManager(); - InvariantDeviceProfile idp = LauncherAppState.getIDP(context); + InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); // Widgets AppWidgetManagerCompat widgetManager = AppWidgetManagerCompat.getInstance(context); @@ -81,7 +71,7 @@ public class WidgetsModel { .getCustomShortcutActivityList(packageUser)) { widgetsAndShortcuts.add(new WidgetItem(info)); } - setWidgetsAndShortcuts(widgetsAndShortcuts, context, packageUser); + setWidgetsAndShortcuts(widgetsAndShortcuts, app, packageUser); } catch (Exception e) { if (!FeatureFlags.IS_DOGFOOD_BUILD && Utilities.isBinderSizeError(e)) { // the returned value may be incomplete and will not be refreshed until the next @@ -92,11 +82,12 @@ public class WidgetsModel { throw e; } } - return widgetsAndShortcuts; + + app.getWidgetCache().removeObsoletePreviews(widgetsAndShortcuts, packageUser); } - private void setWidgetsAndShortcuts(ArrayList rawWidgetsShortcuts, - Context context, @Nullable PackageUserKey packageUser) { + private synchronized void setWidgetsAndShortcuts(ArrayList rawWidgetsShortcuts, + LauncherAppState app, @Nullable PackageUserKey packageUser) { if (DEBUG) { Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size()); } @@ -133,7 +124,7 @@ public class WidgetsModel { } } - InvariantDeviceProfile idp = LauncherAppState.getIDP(context); + InvariantDeviceProfile idp = app.getInvariantDeviceProfile(); UserHandle myUser = Process.myUserHandle(); // add and update. @@ -152,6 +143,9 @@ public class WidgetsModel { } } + if (mAppFilter == null) { + mAppFilter = AppFilter.newInstance(app.getContext()); + } if (!mAppFilter.shouldShowApp(item.componentName)) { if (DEBUG) { Log.d(TAG, String.format("%s is filtered and not added to the widget tray.", @@ -174,8 +168,9 @@ public class WidgetsModel { } // Update each package entry + IconCache iconCache = app.getIconCache(); for (PackageItemInfo p : tmpPackageItemInfos.values()) { - mIconCache.getTitleAndIconForApp(p, true /* userLowResIcon */); + iconCache.getTitleAndIconForApp(p, true /* userLowResIcon */); } } } \ No newline at end of file