Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ec3a0c6 authored by Sunny Goyal's avatar Sunny Goyal Committed by android-build-merger
Browse files

Simplifying Model data load state management

am: dd96a5e4

Change-Id: Ic025e859abf3c9ee4a9be9fc0970a3b42a6a0deb
parents 9f0fa844 dd96a5e4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver {

        LauncherAppState app = LauncherAppState.getInstanceNoCreate();
        if (app != null) {
            app.reloadWorkspace();
            app.getModel().forceReload();
        }
        asyncResult.finish();
    }
+0 −9
Original line number Diff line number Diff line
@@ -134,15 +134,6 @@ public class LauncherAppState {
        PackageInstallerCompat.getInstance(mContext).onStop();
    }

    /**
     * Reloads the workspace items from the DB and re-binds the workspace. This should generally
     * not be called as DB updates are automatically followed by UI update
     */
    public void reloadWorkspace() {
        mModel.resetLoadedState(false, true);
        mModel.startLoaderFromBackground();
    }

    LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
        mModel.initialize(launcher);
+74 −108
Original line number Diff line number Diff line
@@ -71,8 +71,6 @@ 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.ContentWriter;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
@@ -93,6 +91,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;

/**
@@ -123,12 +122,11 @@ public class LauncherModel extends BroadcastReceiver
    }
    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());

    // Indicates whether the current model data is valid or not.
    // We start off with everything not loaded. After that, we assume that
    // our monitoring of the package manager provides all updates and we never
    // need to do a requery.  These are only ever touched from the loader thread.
    private boolean mWorkspaceLoaded;
    private boolean mAllAppsLoaded;
    private boolean mDeepShortcutsLoaded;
    // need to do a requery. This is only ever touched from the loader thread.
    private boolean mModelLoaded;

    /**
     * Set of runnables to be called on the background thread after the workspace binding
@@ -148,11 +146,11 @@ public class LauncherModel extends BroadcastReceiver
    private final Runnable mShortcutPermissionCheckRunnable = new Runnable() {
        @Override
        public void run() {
            if (mDeepShortcutsLoaded) {
            if (mModelLoaded) {
                boolean hasShortcutHostPermission =
                        DeepShortcutManager.getInstance(mApp.getContext()).hasHostPermission();
                if (hasShortcutHostPermission != mHasShortcutHostPermission) {
                    mApp.reloadWorkspace();
                    forceReload();
                }
            }
        }
@@ -480,8 +478,16 @@ public class LauncherModel extends BroadcastReceiver
        }
    }

    void forceReload() {
        resetLoadedState(true, true);
    /**
     * Reloads the workspace items from the DB and re-binds the workspace. This should generally
     * not be called as DB updates are automatically followed by UI update
     */
    public void forceReload() {
        synchronized (mLock) {
            // Stop any existing loaders first, so they don't set mModelLoaded to true later
            stopLoaderLocked();
            mModelLoaded = false;
        }

        // Do this here because if the launcher activity is running it will be restarted.
        // If it's not running startLoaderFromBackground will merely tell it that it needs
@@ -489,19 +495,6 @@ public class LauncherModel extends BroadcastReceiver
        startLoaderFromBackground();
    }

    public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {
        synchronized (mLock) {
            // Stop any existing loaders first, so they don't set mAllAppsLoaded or
            // mWorkspaceLoaded to true later
            stopLoaderLocked();
            if (resetAllAppsLoaded) mAllAppsLoaded = false;
            if (resetWorkspaceLoaded) mWorkspaceLoaded = false;
            // Always reset deep shortcuts loaded.
            // TODO: why?
            mDeepShortcutsLoaded = false;
        }
    }

    /**
     * When the launcher is in the background, it's possible for it to miss paired
     * configuration changes.  So whenever we trigger the loader from the background
@@ -553,9 +546,8 @@ public class LauncherModel extends BroadcastReceiver
                // If there is already one running, tell it to stop.
                stopLoaderLocked();
                mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
                // TODO: mDeepShortcutsLoaded does not need to be true for synchronous bind.
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE && mAllAppsLoaded
                        && mWorkspaceLoaded && mDeepShortcutsLoaded && !mIsLoaderTaskRunning) {
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                        && mModelLoaded && !mIsLoaderTaskRunning) {
                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                    return true;
                } else {
@@ -607,28 +599,6 @@ public class LauncherModel extends BroadcastReceiver
            mPageToBindFirst = pageToBindFirst;
        }

        private void loadAndBindWorkspace() {
            mIsLoadingAndBindingWorkspace = true;

            // Load the workspace
            if (DEBUG_LOADERS) {
                Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
            }

            if (!mWorkspaceLoaded) {
                loadWorkspace();
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return;
                    }
                    mWorkspaceLoaded = true;
                }
            }

            // Bind the workspace
            bindWorkspace(mPageToBindFirst);
        }

        private 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
@@ -671,7 +641,7 @@ public class LauncherModel extends BroadcastReceiver
                throw new RuntimeException("Should not call runBindSynchronousPage() without " +
                        "valid page index");
            }
            if (!mAllAppsLoaded || !mWorkspaceLoaded) {
            if (!mModelLoaded) {
                // Ensure that we don't try and bind a specified page when the pages have not been
                // loaded already (we should load everything asynchronously in that case)
                throw new RuntimeException("Expecting AllApps and Workspace to be loaded");
@@ -703,6 +673,14 @@ public class LauncherModel extends BroadcastReceiver
            bindDeepShortcuts();
        }

        private void verifyNotStopped() throws CancellationException {
            synchronized (LoaderTask.this) {
                if (mStopped) {
                    throw new CancellationException("Loader stopped");
                }
            }
        }

        public void run() {
            synchronized (mLock) {
                if (mStopped) {
@@ -710,30 +688,51 @@ public class LauncherModel extends BroadcastReceiver
                }
                mIsLoaderTaskRunning = true;
            }
            // Optimize for end-user experience: if the Launcher is up and // running with the
            // All Apps interface in the foreground, load All Apps first. Otherwise, load the
            // workspace first (default).
            keep_running: {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
                loadAndBindWorkspace();

                if (mStopped) {
                    break keep_running;
                }
            try {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
                // Set to false in bindWorkspace()
                mIsLoadingAndBindingWorkspace = true;
                loadWorkspace();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.2: bind workspace workspace");
                bindWorkspace(mPageToBindFirst);

                // Take a break
                if (DEBUG_LOADERS) Log.d(TAG, "step 1 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();

                // second step
                if (DEBUG_LOADERS) Log.d(TAG, "step 2: loading all apps");
                loadAndBindAllApps();
                if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps");
                loadAllApps();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 2.2: Update icon cache");
                updateIconCache();

                // Take a break
                if (DEBUG_LOADERS) Log.d(TAG, "step 2 completed, wait for idle");
                waitForIdle();
                verifyNotStopped();

                // third step
                if (DEBUG_LOADERS) Log.d(TAG, "step 3: loading deep shortcuts");
                loadAndBindDeepShortcuts();
            }
                if (DEBUG_LOADERS) Log.d(TAG, "step 3.1: loading deep shortcuts");
                loadDeepShortcuts();

                verifyNotStopped();
                if (DEBUG_LOADERS) Log.d(TAG, "step 3.2: bind deep shortcuts");
                bindDeepShortcuts();

                synchronized (mLock) {
                    // Everything loaded bind the data.
                    mModelLoaded = true;
                    mHasLoaderCompletedOnce = true;
                }
            } 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;
@@ -744,7 +743,7 @@ public class LauncherModel extends BroadcastReceiver
                        mLoaderTask = null;
                    }
                    mIsLoaderTaskRunning = false;
                mHasLoaderCompletedOnce = true;
                }
            }
        }

@@ -1605,29 +1604,6 @@ public class LauncherModel extends BroadcastReceiver
            }
        }

        private void loadAndBindAllApps() {
            if (DEBUG_LOADERS) {
                Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
            }
            if (!mAllAppsLoaded) {
                loadAllApps();
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return;
                    }
                }
                updateIconCache();
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return;
                    }
                    mAllAppsLoaded = true;
                }
            } else {
                onlyBindAllApps();
            }
        }

        private void updateIconCache() {
            // Ignore packages which have a promise icon.
            HashSet<String> packagesToIgnore = new HashSet<>();
@@ -1768,11 +1744,8 @@ public class LauncherModel extends BroadcastReceiver
            }
        }

        private void loadAndBindDeepShortcuts() {
            if (DEBUG_LOADERS) {
                Log.d(TAG, "loadAndBindDeepShortcuts mDeepShortcutsLoaded=" + mDeepShortcutsLoaded);
            }
            if (!mDeepShortcutsLoaded) {
        private void loadDeepShortcuts() {
            if (!mModelLoaded) {
                sBgDataModel.deepShortcutMap.clear();
                DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(mContext);
                mHasShortcutHostPermission = shortcutManager.hasHostPermission();
@@ -1785,15 +1758,8 @@ public class LauncherModel extends BroadcastReceiver
                        }
                    }
                }
                synchronized (LoaderTask.this) {
                    if (mStopped) {
                        return;
                    }
                    mDeepShortcutsLoaded = true;
            }
        }
            bindDeepShortcuts();
        }
    }

    public void bindDeepShortcuts() {
+2 −2
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ public class LauncherProvider extends ContentProvider {
        if (Utilities.ATLEAST_MARSHMALLOW && Binder.getCallingPid() != Process.myPid()) {
            LauncherAppState app = LauncherAppState.getInstanceNoCreate();
            if (app != null) {
                app.reloadWorkspace();
                app.getModel().forceReload();
            }
        }
    }
@@ -205,7 +205,7 @@ public class LauncherProvider extends ContentProvider {
            // Deprecated behavior to support legacy devices which rely on provider callbacks.
            LauncherAppState app = LauncherAppState.getInstanceNoCreate();
            if (app != null && "true".equals(uri.getQueryParameter("isExternalAdd"))) {
                app.reloadWorkspace();
                app.getModel().forceReload();
            }

            String notify = uri.getQueryParameter("notify");
+1 −2
Original line number Diff line number Diff line
@@ -236,8 +236,7 @@ public class LauncherInstrumentationTestCase extends InstrumentationTestCase {
                @Override
                public void run() {
                    ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mTargetContext);
                    LauncherAppState.getInstance(mTargetContext).getModel()
                            .resetLoadedState(true, true);
                    LauncherAppState.getInstance(mTargetContext).getModel().forceReload();
                }
            });
        } catch (Throwable t) {