From 57d4f748b89b2a07e2b33acdfdbcc3767df0aa41 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 6 Aug 2021 11:52:10 -0700 Subject: [PATCH] Fixing ModelPreload cancelling existing load When a model preload call was made while the loader task is running (eg: on enabling/disabling icon theme, Launcher reloads and then launcher preview start a model-preload), it would cancel the original loader and then start a new loader with empty callbacks. So the model indeed get loaded, but the original callbacks never got notified of it. > Instead we only start preload if an existing task is not running. > Also when preloading, we use existing callbacks, instead of using empty callbacks Bug: 193851085 Bug: 195155924 Test: Verified repro steps Change-Id: I0a96310be8489756f364aa2a12e4345e1418733d --- src/com/android/launcher3/LauncherModel.java | 33 ++++---- .../graphics/PreviewSurfaceRenderer.java | 18 ++--- .../android/launcher3/model/ModelPreload.java | 76 ------------------- 3 files changed, 22 insertions(+), 105 deletions(-) delete mode 100644 src/com/android/launcher3/model/ModelPreload.java diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index eef3980f96..545f4c3999 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -72,6 +72,7 @@ import java.util.HashSet; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.Executor; +import java.util.function.Consumer; import java.util.function.Supplier; /** @@ -376,7 +377,13 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi loaderResults.bindWidgets(); return true; } else { - startLoaderForResults(loaderResults); + stopLoader(); + mLoaderTask = new LoaderTask( + mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults); + + // Always post the loader task, instead of running directly + // (even on same thread) so that we exit any nested synchronized blocks + MODEL_EXECUTOR.post(mLoaderTask); } } } @@ -399,25 +406,17 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi } } - public void startLoaderForResults(LoaderResults results) { + /** + * Loads the model if not loaded + * @param callback called with the data model upon successful load or null on model thread. + */ + public void loadAsync(Consumer callback) { synchronized (mLock) { - stopLoader(); - mLoaderTask = new LoaderTask( - mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, results); - - // Always post the loader task, instead of running directly (even on same thread) so - // that we exit any nested synchronized blocks - MODEL_EXECUTOR.post(mLoaderTask); - } - } - - public void startLoaderForResultsIfNotLoaded(LoaderResults results) { - synchronized (mLock) { - if (!isModelLoaded()) { - Log.d(TAG, "Workspace not loaded, loading now"); - startLoaderForResults(results); + if (!mModelLoaded && !mIsLoaderTaskRunning) { + startLoader(); } } + MODEL_EXECUTOR.post(() -> callback.accept(isModelLoaded() ? mBgDataModel : null)); } @Override diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java index df493599ed..3b140a06bd 100644 --- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java @@ -49,7 +49,6 @@ import com.android.launcher3.model.GridSizeMigrationTask; import com.android.launcher3.model.GridSizeMigrationTaskV2; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.ModelDelegate; -import com.android.launcher3.model.ModelPreload; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.Themes; @@ -174,18 +173,13 @@ public class PreviewSurfaceRenderer { } }.run(); } else { - new ModelPreload() { - - @Override - public void onComplete(boolean isSuccess) { - if (isSuccess) { - MAIN_EXECUTOR.execute(() -> - renderView(inflationContext, getBgDataModel(), null)); - } else { - Log.e(TAG, "Model loading failed"); - } + LauncherAppState.getInstance(inflationContext).getModel().loadAsync(dataModel -> { + if (dataModel != null) { + MAIN_EXECUTOR.execute(() -> renderView(inflationContext, dataModel, null)); + } else { + Log.e(TAG, "Model loading failed"); } - }.start(inflationContext); + }); } } diff --git a/src/com/android/launcher3/model/ModelPreload.java b/src/com/android/launcher3/model/ModelPreload.java deleted file mode 100644 index 756b7da759..0000000000 --- a/src/com/android/launcher3/model/ModelPreload.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.launcher3.model; - -import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; - -import android.content.Context; -import android.util.Log; - -import androidx.annotation.WorkerThread; - -import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel; -import com.android.launcher3.LauncherModel.ModelUpdateTask; -import com.android.launcher3.model.BgDataModel.Callbacks; - -import java.util.concurrent.Executor; - -/** - * Utility class to preload LauncherModel - */ -public class ModelPreload implements ModelUpdateTask { - - private static final String TAG = "ModelPreload"; - - private LauncherAppState mApp; - private LauncherModel mModel; - private BgDataModel mBgDataModel; - private AllAppsList mAllAppsList; - - @Override - public final void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel, - AllAppsList allAppsList, Executor uiExecutor) { - mApp = app; - mModel = model; - mBgDataModel = dataModel; - mAllAppsList = allAppsList; - } - - @Override - public final void run() { - mModel.startLoaderForResultsIfNotLoaded( - new LoaderResults(mApp, mBgDataModel, mAllAppsList, new Callbacks[0])); - MODEL_EXECUTOR.post(() -> { - Log.d(TAG, "Preload completed : " + mModel.isModelLoaded()); - onComplete(mModel.isModelLoaded()); - }); - } - - public BgDataModel getBgDataModel() { - return mBgDataModel; - } - - /** - * Called when the task is complete - */ - @WorkerThread - public void onComplete(boolean isSuccess) { } - - public void start(Context context) { - LauncherAppState.getInstance(context).getModel().enqueueModelUpdateTask(this); - } -} \ No newline at end of file