diff options
Diffstat (limited to 'src/com/android/launcher3/LauncherModel.java')
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 212 |
1 files changed, 109 insertions, 103 deletions
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index e68e637c5..ca9f3120d 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.LauncherActivityInfo; +import android.content.pm.PackageInstaller; import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; @@ -45,10 +46,11 @@ import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.UserManagerCompat; -import com.android.launcher3.config.ProviderConfig; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dynamicui.ExtractionUtils; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.folder.FolderIconPreviewVerifier; import com.android.launcher3.graphics.LauncherIcons; import com.android.launcher3.logging.FileLog; import com.android.launcher3.model.AddWorkspaceItemsTask; @@ -72,6 +74,7 @@ import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutInfoCompat; import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.ComponentKey; +import com.android.launcher3.util.LooperIdleLock; import com.android.launcher3.util.ManagedProfileHeuristic; import com.android.launcher3.util.MultiHashMap; import com.android.launcher3.util.PackageManagerHelper; @@ -111,9 +114,9 @@ public class LauncherModel extends BroadcastReceiver private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons private static final long INVALID_SCREEN_ID = -1L; + private final MainThreadExecutor mUiExecutor = new MainThreadExecutor(); @Thunk final LauncherAppState mApp; @Thunk final Object mLock = new Object(); - @Thunk DeferredHandler mHandler = new DeferredHandler(); @Thunk LoaderTask mLoaderTask; @Thunk boolean mIsLoaderTaskRunning; @Thunk boolean mHasLoaderCompletedOnce; @@ -193,6 +196,7 @@ public class LauncherModel extends BroadcastReceiver ArrayList<ItemInfo> addAnimated, ArrayList<AppInfo> addedApps); public void bindAppsUpdated(ArrayList<AppInfo> apps); + public void bindPromiseAppProgressUpdated(PromiseAppInfo app); public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated, ArrayList<ShortcutInfo> removed, UserHandle user); public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets); @@ -219,17 +223,6 @@ public class LauncherModel extends BroadcastReceiver mUserManager = UserManagerCompat.getInstance(context); } - /** Runs the specified runnable immediately if called from the main thread, otherwise it is - * posted on the main thread handler. */ - private void runOnMainThread(Runnable r) { - if (sWorkerThread.getThreadId() == Process.myTid()) { - // If we are on the worker thread, post onto the main handler - mHandler.post(r); - } else { - r.run(); - } - } - /** Runs the specified runnable immediately if called from the worker thread, otherwise it is * posted on the worker thread handler. */ private static void runOnWorkerThread(Runnable r) { @@ -379,8 +372,6 @@ public class LauncherModel extends BroadcastReceiver public void initialize(Callbacks callbacks) { synchronized (mLock) { Preconditions.assertUIThread(); - // Remove any queued UI runnables - mHandler.cancelAll(); mCallbacks = new WeakReference<>(callbacks); } } @@ -544,11 +535,11 @@ public class LauncherModel extends BroadcastReceiver if (mCallbacks != null && mCallbacks.get() != null) { final Callbacks oldCallbacks = mCallbacks.get(); // Clear any pending bind-runnables from the synchronized load process. - runOnMainThread(new Runnable() { - public void run() { - oldCallbacks.clearPendingBinds(); - } - }); + mUiExecutor.execute(new Runnable() { + public void run() { + oldCallbacks.clearPendingBinds(); + } + }); // If there is already one running, tell it to stop. stopLoaderLocked(); @@ -586,6 +577,25 @@ public class LauncherModel extends BroadcastReceiver screensUri, null, null, null, LauncherSettings.WorkspaceScreens.SCREEN_RANK)); } + public void onInstallSessionCreated(final PackageInstallInfo sessionInfo) { + enqueueModelUpdateTask(new ExtendedModelTask() { + @Override + public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { + apps.addPromiseApp(app.getContext(), sessionInfo); + if (!apps.added.isEmpty()) { + final ArrayList<AppInfo> arrayList = new ArrayList<>(apps.added); + apps.added.clear(); + scheduleCallbackTask(new CallbackTask() { + @Override + public void execute(Callbacks callbacks) { + callbacks.bindAppsAdded(null, null, null, arrayList); + } + }); + } + } + }); + } + /** * Runnable for the thread that loads the contents of the launcher: * - workspace icons @@ -599,7 +609,6 @@ public class LauncherModel extends BroadcastReceiver @Thunk boolean mIsLoadingAndBindingWorkspace; private boolean mStopped; - @Thunk boolean mLoadAndBindStepFinished; LoaderTask(Context context, int pageToBindFirst) { mContext = context; @@ -611,34 +620,10 @@ public class LauncherModel extends BroadcastReceiver // This way we don't start loading all apps until the workspace has settled // down. synchronized (LoaderTask.this) { - final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0; - - mHandler.postIdle(new Runnable() { - public void run() { - synchronized (LoaderTask.this) { - mLoadAndBindStepFinished = true; - if (DEBUG_LOADERS) { - Log.d(TAG, "done with previous binding step"); - } - LoaderTask.this.notify(); - } - } - }); - - while (!mStopped && !mLoadAndBindStepFinished) { - try { - // Just in case mFlushingWorkerThread changes but we aren't woken up, - // wait no longer than 1sec at a time - this.wait(1000); - } catch (InterruptedException ex) { - // Ignore - } - } - if (DEBUG_LOADERS) { - Log.d(TAG, "waited " - + (SystemClock.uptimeMillis()-workspaceWaitTime) - + "ms for previous step to finish binding"); - } + 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)); } } @@ -661,15 +646,6 @@ public class LauncherModel extends BroadcastReceiver } } - // XXX: Throw an exception if we are already loading (since we touch the worker thread - // data structures, we can't allow any other thread to touch that data, but because - // this call is synchronous, we can get away with not locking). - - // The LauncherModel is static in the LauncherAppState and mHandler may have queued - // operations from the previous activity. We need to ensure that all queued operations - // are executed before any synchronous binding work is done. - mHandler.flush(); - // Divide the set of loaded items into those that we are binding synchronously, and // everything else that is to be bound normally (asynchronously). bindWorkspace(synchronousBindPage); @@ -697,6 +673,7 @@ public class LauncherModel extends BroadcastReceiver } try { + long now = 0; if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace"); // Set to false in bindWorkspace() mIsLoadingAndBindingWorkspace = true; @@ -707,8 +684,12 @@ public class LauncherModel extends BroadcastReceiver bindWorkspace(mPageToBindFirst); // Take a break - if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle"); + if (DEBUG_LOADERS) { + Log.d(TAG, "step 1 completed, wait for idle"); + now = SystemClock.uptimeMillis(); + } waitForIdle(); + if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms"); verifyNotStopped(); // second step @@ -720,8 +701,12 @@ public class LauncherModel extends BroadcastReceiver updateIconCache(); // Take a break - if (DEBUG_LOADERS) Log.d(TAG, "step 2 completed, wait for idle"); + if (DEBUG_LOADERS) { + Log.d(TAG, "step 2 completed, wait for idle"); + now = SystemClock.uptimeMillis(); + } waitForIdle(); + if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms"); verifyNotStopped(); // third step @@ -900,6 +885,8 @@ public class LauncherModel extends BroadcastReceiver Intent intent; String targetPkg; + FolderIconPreviewVerifier verifier = + new FolderIconPreviewVerifier(mApp.getInvariantDeviceProfile()); while (!mStopped && c.moveToNext()) { try { if (c.user == null) { @@ -954,7 +941,7 @@ public class LauncherModel extends BroadcastReceiver // no special handling necessary for this item c.markRestored(); } else { - if (c.hasRestoreFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) { + if (c.hasRestoreFlag(ShortcutInfo.FLAG_AUTOINSTALL_ICON)) { // We allow auto install apps to have their intent // updated after an install. intent = pmHelper.getAppLaunchIntent(targetPkg, c.user); @@ -1024,7 +1011,7 @@ public class LauncherModel extends BroadcastReceiver } boolean useLowResIcon = !c.isOnWorkspaceOrHotseat() && - c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW; + !verifier.isItemInPreview(c.getInt(rankIndex)); if (c.restoreFlag != 0) { // Already verified above that user is same as default user @@ -1230,6 +1217,16 @@ public class LauncherModel extends BroadcastReceiver .commit(); } } + + if (appWidgetInfo.restoreStatus != + LauncherAppWidgetInfo.RESTORE_COMPLETED) { + String pkg = appWidgetInfo.providerName.getPackageName(); + appWidgetInfo.pendingItemInfo = new PackageItemInfo(pkg); + appWidgetInfo.pendingItemInfo.user = appWidgetInfo.user; + mIconCache.getTitleAndIconForApp( + appWidgetInfo.pendingItemInfo, false); + } + c.checkAndAddItem(appWidgetInfo, sBgDataModel); } break; @@ -1278,17 +1275,23 @@ public class LauncherModel extends BroadcastReceiver } } - // Sort all the folder items and make sure the first 3 items are high resolution. + 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) { Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR); - int pos = 0; + verifier.setFolderInfo(folder); + + int numItemsInPreview = 0; for (ShortcutInfo info : folder.contents) { - if (info.usingLowResIcon && - info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { + if (info.usingLowResIcon + && info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION + && verifier.isItemInPreview(info.rank)) { mIconCache.getTitleAndIcon(info, false); + numItemsInPreview++; } - pos ++; - if (pos >= FolderIcon.NUM_ITEMS_IN_PREVIEW) { + + if (numItemsInPreview >= FolderIcon.NUM_ITEMS_IN_PREVIEW) { break; } } @@ -1413,7 +1416,7 @@ public class LauncherModel extends BroadcastReceiver return Utilities.longCompare(lhs.screenId, rhs.screenId); } default: - if (ProviderConfig.IS_DOGFOOD_BUILD) { + if (FeatureFlags.IS_DOGFOOD_BUILD) { throw new RuntimeException("Unexpected container type when " + "sorting workspace items."); } @@ -1438,7 +1441,7 @@ public class LauncherModel extends BroadcastReceiver } } }; - runOnMainThread(r); + mUiExecutor.execute(r); } private void bindWorkspaceItems(final Callbacks oldCallbacks, @@ -1544,11 +1547,11 @@ public class LauncherModel extends BroadcastReceiver } } }; - runOnMainThread(r); + mUiExecutor.execute(r); bindWorkspaceScreens(oldCallbacks, orderedScreenIds); - Executor mainExecutor = new DeferredMainThreadExecutor(); + Executor mainExecutor = mUiExecutor; // Load items on the current page. bindWorkspaceItems(oldCallbacks, currentWorkspaceItems, currentAppWidgets, mainExecutor); @@ -1558,7 +1561,7 @@ public class LauncherModel extends BroadcastReceiver // This ensures that the first screen is immediately visible (eg. during rotation) // In case of !validFirstPage, bind all pages one after other. final Executor deferredExecutor = - validFirstPage ? new ViewOnDrawExecutor(mHandler) : mainExecutor; + validFirstPage ? new ViewOnDrawExecutor(mUiExecutor) : mainExecutor; mainExecutor.execute(new Runnable() { @Override @@ -1618,7 +1621,7 @@ public class LauncherModel extends BroadcastReceiver } } }; - runOnMainThread(r); + mUiExecutor.execute(r); } } @@ -1668,7 +1671,7 @@ public class LauncherModel extends BroadcastReceiver } } }; - runOnMainThread(r); + mUiExecutor.execute(r); } private void loadAllApps() { @@ -1716,29 +1719,40 @@ public class LauncherModel extends BroadcastReceiver heuristic.processUserApps(apps); } }; - runOnMainThread(new Runnable() { + mUiExecutor.execute(new Runnable() { + + @Override + public void run() { + // Check isLoadingWorkspace on the UI thread, as it is updated on + // the UI thread. + if (mIsLoadingAndBindingWorkspace) { + synchronized (mBindCompleteRunnables) { + mBindCompleteRunnables.add(r); + } + } else { + runOnWorkerThread(r); + } + } + }); + } + } - @Override - public void run() { - // Check isLoadingWorkspace on the UI thread, as it is updated on - // the UI thread. - if (mIsLoadingAndBindingWorkspace) { - synchronized (mBindCompleteRunnables) { - mBindCompleteRunnables.add(r); - } - } else { - runOnWorkerThread(r); - } - } - }); + 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, + PackageInstallInfo.fromInstallingState(info)); } } + // Huh? Shouldn't this be inside the Runnable below? final ArrayList<AppInfo> added = mBgAllAppsList.added; mBgAllAppsList.added = new ArrayList<AppInfo>(); + // Post callback on main thread - mHandler.post(new Runnable() { + mUiExecutor.execute(new Runnable() { public void run() { final long bindTime = SystemClock.uptimeMillis(); @@ -1792,7 +1806,7 @@ public class LauncherModel extends BroadcastReceiver } } }; - runOnMainThread(r); + mUiExecutor.execute(r); } /** @@ -1843,12 +1857,12 @@ public class LauncherModel extends BroadcastReceiver public static abstract class BaseModelUpdateTask implements Runnable { private LauncherModel mModel; - private DeferredHandler mUiHandler; + private Executor mUiExecutor; /* package private */ void init(LauncherModel model) { mModel = model; - mUiHandler = mModel.mHandler; + mUiExecutor = mModel.mUiExecutor; } @Override @@ -1871,7 +1885,7 @@ public class LauncherModel extends BroadcastReceiver */ public final void scheduleCallbackTask(final CallbackTask task) { final Callbacks callbacks = mModel.getCallback(); - mUiHandler.post(new Runnable() { + mUiExecutor.execute(new Runnable() { public void run() { Callbacks cb = mModel.getCallback(); if (callbacks == cb && cb != null) { @@ -1916,7 +1930,7 @@ public class LauncherModel extends BroadcastReceiver private void bindWidgetsModel(final Callbacks callbacks) { final MultiHashMap<PackageItemInfo, WidgetItem> widgets = mBgWidgetsModel.getWidgetsMap().clone(); - mHandler.post(new Runnable() { + mUiExecutor.execute(new Runnable() { @Override public void run() { Callbacks cb = getCallback(); @@ -1974,14 +1988,6 @@ public class LauncherModel extends BroadcastReceiver } } - @Thunk class DeferredMainThreadExecutor implements Executor { - - @Override - public void execute(Runnable command) { - runOnMainThread(command); - } - } - /** * @return the looper for the worker thread which can be used to start background tasks. */ |