diff options
23 files changed, 210 insertions, 265 deletions
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LoaderResults.java index b82f36249..26c331318 100644 --- a/go/src/com/android/launcher3/model/LoaderResults.java +++ b/go/src/com/android/launcher3/model/LoaderResults.java @@ -16,9 +16,8 @@ package com.android.launcher3.model; -import com.android.launcher3.AllAppsList; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import java.lang.ref.WeakReference; diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java index cb5cbddd4..623f1ff99 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -279,7 +279,7 @@ public class PredictionRowView extends LinearLayout implements } private List<ItemInfoWithIcon> processPredictedAppComponents(List<ComponentKeyMapper> components) { - if (getAppsStore().getApps().isEmpty()) { + if (getAppsStore().getApps().length == 0) { // Apps have not been bound yet. return Collections.emptyList(); } diff --git a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java index ab3927466..bc936b7b2 100644 --- a/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java +++ b/robolectric_tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java @@ -15,14 +15,13 @@ import android.graphics.Color; import android.os.Process; import android.os.UserHandle; -import com.android.launcher3.AllAppsList; import com.android.launcher3.AppFilter; import com.android.launcher3.AppInfo; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherProvider; import com.android.launcher3.icons.IconCache; diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java index d884049f5..291052517 100644 --- a/src/com/android/launcher3/AppInfo.java +++ b/src/com/android/launcher3/AppInfo.java @@ -29,11 +29,19 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.PackageManagerHelper; +import java.util.Comparator; + /** * Represents an app in AllAppsView. */ public class AppInfo extends ItemInfoWithIcon { + public static AppInfo[] EMPTY_ARRAY = new AppInfo[0]; + public static Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> { + int uc = a.user.hashCode() - b.user.hashCode(); + return uc != 0 ? uc : a.componentName.compareTo(b.componentName); + }; + /** * The intent used to start the application. */ diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 40d76681b..c221a2d67 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -105,6 +105,7 @@ import com.android.launcher3.logging.StatsLogUtils; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher.UserEventDelegate; import com.android.launcher3.model.AppLaunchTracker; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.ModelWriter; import com.android.launcher3.notification.NotificationListener; import com.android.launcher3.popup.PopupContainerWithArrow; @@ -112,7 +113,6 @@ import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.states.InternalStateHandler; import com.android.launcher3.states.RotationHelper; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -163,7 +163,7 @@ import androidx.annotation.Nullable; * Default launcher application. */ public class Launcher extends BaseDraggingActivity implements LauncherExterns, - LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate, + Callbacks, LauncherProviderChangeListener, UserEventDelegate, InvariantDeviceProfile.OnIDPChangeListener { public static final String TAG = "Launcher"; static final boolean LOGD = false; @@ -2335,7 +2335,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, * * Implementation of the method from LauncherModel.Callbacks. */ - public void bindAllApplications(ArrayList<AppInfo> apps) { + public void bindAllApplications(AppInfo[] apps) { mAppsView.getAppsStore().setApps(apps); } @@ -2348,16 +2348,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mPopupDataProvider.setDeepShortcutMap(deepShortcutMapCopy); } - /** - * A package was updated. - * - * Implementation of the method from LauncherModel.Callbacks. - */ - @Override - public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps) { - mAppsView.getAppsStore().addOrUpdateApps(apps); - } - @Override public void bindPromiseAppProgressUpdated(PromiseAppInfo app) { mAppsView.getAppsStore().updatePromiseAppProgress(app); @@ -2405,11 +2395,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } @Override - public void bindAppInfosRemoved(final ArrayList<AppInfo> appInfos) { - mAppsView.getAppsStore().removeApps(appInfos); - } - - @Override public void bindAllWidgets(final ArrayList<WidgetListRowEntry> allWidgets) { mPopupDataProvider.setAllWidgets(allWidgets); } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index d79f5d5a9..eed23770e 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -38,8 +38,10 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AddWorkspaceItemsTask; +import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BaseModelUpdateTask; import com.android.launcher3.model.BgDataModel; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.CacheDataUpdatedTask; import com.android.launcher3.model.LoaderResults; import com.android.launcher3.model.LoaderTask; @@ -49,20 +51,14 @@ import com.android.launcher3.model.PackageUpdatedTask; import com.android.launcher3.model.ShortcutsChangedTask; import com.android.launcher3.model.UserLockStateChangedTask; import com.android.launcher3.shortcuts.DeepShortcutManager; -import com.android.launcher3.util.ComponentKey; -import com.android.launcher3.util.IntArray; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.Thunk; -import com.android.launcher3.util.ViewOnDrawExecutor; -import com.android.launcher3.widget.WidgetListRowEntry; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.concurrent.CancellationException; @@ -133,33 +129,6 @@ public class LauncherModel extends BroadcastReceiver } }; - public interface Callbacks { - public void rebindModel(); - - public int getCurrentWorkspaceScreen(); - public void clearPendingBinds(); - public void startBinding(); - public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons); - public void bindScreens(IntArray orderedScreenIds); - public void finishFirstPageBind(ViewOnDrawExecutor executor); - public void finishBindingItems(int pageBoundFirst); - public void bindAllApplications(ArrayList<AppInfo> apps); - public void bindAppsAddedOrUpdated(ArrayList<AppInfo> apps); - public void preAddApps(); - public void bindAppsAdded(IntArray newScreens, - ArrayList<ItemInfo> addNotAnimated, ArrayList<ItemInfo> addAnimated); - public void bindPromiseAppProgressUpdated(PromiseAppInfo app); - public void bindWorkspaceItemsChanged(ArrayList<WorkspaceItemInfo> updated); - public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets); - public void bindRestoreItemsChange(HashSet<ItemInfo> updates); - public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher); - public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos); - public void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets); - public void onPageBoundSynchronously(int page); - public void executeOnNextDraw(ViewOnDrawExecutor executor); - public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMap); - } - LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) { mApp = app; mBgAllAppsList = new AllAppsList(iconCache, appFilter); @@ -411,16 +380,7 @@ public class LauncherModel extends BroadcastReceiver @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.bindAppsAddedOrUpdated(arrayList); - } - }); - } + bindApplicationsIfNeeded(); } }); } diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java index 160042e69..1ff50296c 100644 --- a/src/com/android/launcher3/allapps/AllAppsStore.java +++ b/src/com/android/launcher3/allapps/AllAppsStore.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.allapps; +import static com.android.launcher3.AppInfo.COMPONENT_KEY_COMPARATOR; +import static com.android.launcher3.AppInfo.EMPTY_ARRAY; + import android.view.View; import android.view.ViewGroup; @@ -26,8 +29,7 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; +import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import java.util.function.Predicate; @@ -45,27 +47,33 @@ public class AllAppsStore { public static final int DEFER_UPDATES_TEST = 1 << 2; private PackageUserKey mTempKey = new PackageUserKey(null, null); - private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>(); + private AppInfo mTempInfo = new AppInfo(); + + private AppInfo[] mApps = EMPTY_ARRAY; + private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>(); private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>(); private int mDeferUpdatesFlags = 0; private boolean mUpdatePending = false; - public Collection<AppInfo> getApps() { - return mComponentToAppMap.values(); + public AppInfo[] getApps() { + return mApps; } /** * Sets the current set of apps. */ - public void setApps(List<AppInfo> apps) { - mComponentToAppMap.clear(); - addOrUpdateApps(apps); + public void setApps(AppInfo[] apps) { + mApps = apps; + notifyUpdate(); } public AppInfo getApp(ComponentKey key) { - return mComponentToAppMap.get(key); + mTempInfo.componentName = key.componentName; + mTempInfo.user = key.user; + int index = Arrays.binarySearch(mApps, mTempInfo, COMPONENT_KEY_COMPARATOR); + return index < 0 ? null : mApps[index]; } public void enableDeferUpdates(int flag) { @@ -84,27 +92,6 @@ public class AllAppsStore { return mDeferUpdatesFlags; } - /** - * Adds or updates existing apps in the list - */ - public void addOrUpdateApps(List<AppInfo> apps) { - for (AppInfo app : apps) { - mComponentToAppMap.put(app.toComponentKey(), app); - } - notifyUpdate(); - } - - /** - * Removes some apps from the list. - */ - public void removeApps(List<AppInfo> apps) { - for (AppInfo app : apps) { - mComponentToAppMap.remove(app.toComponentKey()); - } - notifyUpdate(); - } - - private void notifyUpdate() { if (mDeferUpdatesFlags != 0) { mUpdatePending = true; diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index 8c264c186..935326d75 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -20,7 +20,6 @@ import android.os.UserHandle; import android.util.LongSparseArray; import android.util.Pair; -import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; import com.android.launcher3.InvariantDeviceProfile; @@ -28,7 +27,7 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherModel.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.LauncherSettings; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.util.GridOccupancy; diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index 733f29540..2fddbaaba 100644 --- a/src/com/android/launcher3/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -14,7 +14,10 @@ * limitations under the License. */ -package com.android.launcher3; +package com.android.launcher3.model; + +import static com.android.launcher3.AppInfo.COMPONENT_KEY_COMPARATOR; +import static com.android.launcher3.AppInfo.EMPTY_ARRAY; import android.content.ComponentName; import android.content.Context; @@ -24,15 +27,22 @@ import android.os.Process; import android.os.UserHandle; import android.util.Log; +import com.android.launcher3.AppFilter; +import com.android.launcher3.AppInfo; +import com.android.launcher3.PromiseAppInfo; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat; +import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.icons.IconCache; import com.android.launcher3.util.FlagOp; import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.util.SafeCloseable; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.function.Consumer; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -42,23 +52,22 @@ import androidx.annotation.Nullable; * Stores the list of all applications for the all apps view. */ public class AllAppsList { + private static final String TAG = "AllAppsList"; + private static final Consumer<AppInfo> NO_OP_CONSUMER = a -> { }; + public static final int DEFAULT_APPLICATIONS_NUMBER = 42; /** The list off all apps. */ public final ArrayList<AppInfo> data = new ArrayList<>(DEFAULT_APPLICATIONS_NUMBER); - /** The list of apps that have been added since the last notify() call. */ - public ArrayList<AppInfo> added = new ArrayList<>(DEFAULT_APPLICATIONS_NUMBER); - /** The list of apps that have been removed since the last notify() call. */ - public ArrayList<AppInfo> removed = new ArrayList<>(); - /** The list of apps that have been modified since the last notify() call. */ - public ArrayList<AppInfo> modified = new ArrayList<>(); private IconCache mIconCache; - private AppFilter mAppFilter; + private boolean mDataChanged = false; + private Consumer<AppInfo> mRemoveListener = NO_OP_CONSUMER; + /** * Boring constructor. */ @@ -68,6 +77,15 @@ public class AllAppsList { } /** + * Returns true if there have been any changes since last call. + */ + public boolean getAndResetChangeFlag() { + boolean result = mDataChanged; + mDataChanged = false; + return result; + } + + /** * Add the supplied ApplicationInfo objects to the list, and enqueue it into the * list to broadcast when notify() is called. * @@ -83,7 +101,7 @@ public class AllAppsList { mIconCache.getTitleAndIcon(info, activityInfo, true /* useLowResIcon */); data.add(info); - added.add(info); + mDataChanged = true; } public void addPromiseApp(Context context, @@ -95,30 +113,41 @@ public class AllAppsList { PromiseAppInfo info = new PromiseAppInfo(installInfo); mIconCache.getTitleAndIcon(info, info.usingLowResIcon()); data.add(info); - added.add(info); + mDataChanged = true; } } - public void removePromiseApp(AppInfo appInfo) { - // the <em>removed</em> list is handled by the caller - // so not adding it here - data.remove(appInfo); - } - - public void clear() { - data.clear(); - // TODO: do we clear these too? - added.clear(); - removed.clear(); - modified.clear(); + public PromiseAppInfo updatePromiseInstallInfo(PackageInstallInfo installInfo) { + UserHandle user = Process.myUserHandle(); + for (int i=0; i < data.size(); i++) { + final AppInfo appInfo = data.get(i); + final ComponentName tgtComp = appInfo.getTargetComponent(); + if (tgtComp != null && tgtComp.getPackageName().equals(installInfo.packageName) + && appInfo.user.equals(user) + && appInfo instanceof PromiseAppInfo) { + final PromiseAppInfo promiseAppInfo = (PromiseAppInfo) appInfo; + if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLING) { + promiseAppInfo.level = installInfo.progress; + return promiseAppInfo; + } else if (installInfo.state == PackageInstallerCompat.STATUS_FAILED) { + removeApp(i); + } + } + } + return null; } - public int size() { - return data.size(); + private void removeApp(int index) { + AppInfo removed = data.remove(index); + if (removed != null) { + mDataChanged = true; + mRemoveListener.accept(removed); + } } - public AppInfo get(int index) { - return data.get(index); + public void clear() { + data.clear(); + mDataChanged = false; } /** @@ -142,8 +171,7 @@ public class AllAppsList { for (int i = data.size() - 1; i >= 0; i--) { AppInfo info = data.get(i); if (info.user.equals(user) && packageName.equals(info.componentName.getPackageName())) { - removed.add(info); - data.remove(i); + removeApp(i); } } } @@ -157,17 +185,16 @@ public class AllAppsList { AppInfo info = data.get(i); if (matcher.matches(info, info.componentName)) { info.runtimeStatusFlags = op.apply(info.runtimeStatusFlags); - modified.add(info); + mDataChanged = true; } } } - public void updateIconsAndLabels(HashSet<String> packages, UserHandle user, - ArrayList<AppInfo> outUpdates) { + public void updateIconsAndLabels(HashSet<String> packages, UserHandle user) { for (AppInfo info : data) { if (info.user.equals(user) && packages.contains(info.componentName.getPackageName())) { mIconCache.updateTitleAndIcon(info); - outUpdates.add(info); + mDataChanged = true; } } } @@ -188,8 +215,7 @@ public class AllAppsList { && packageName.equals(applicationInfo.componentName.getPackageName())) { if (!findActivity(matches, applicationInfo.componentName)) { Log.w(TAG, "Changing shortcut target due to app component name change."); - removed.add(applicationInfo); - data.remove(i); + removeApp(i); } } } @@ -202,7 +228,7 @@ public class AllAppsList { add(new AppInfo(context, info, user), info); } else { mIconCache.getTitleAndIcon(applicationInfo, info, true /* useLowResIcon */); - modified.add(applicationInfo); + mDataChanged = true; } } } else { @@ -211,15 +237,13 @@ public class AllAppsList { final AppInfo applicationInfo = data.get(i); if (user.equals(applicationInfo.user) && packageName.equals(applicationInfo.componentName.getPackageName())) { - removed.add(applicationInfo); mIconCache.remove(applicationInfo.componentName, user); - data.remove(i); + removeApp(i); } } } } - /** * Returns whether <em>apps</em> contains <em>component</em>. */ @@ -247,4 +271,16 @@ public class AllAppsList { } return null; } + + public AppInfo[] copyData() { + AppInfo[] result = data.toArray(EMPTY_ARRAY); + Arrays.sort(result, COMPONENT_KEY_COMPARATOR); + return result; + } + + public SafeCloseable trackRemoves(Consumer<AppInfo> removeListener) { + mRemoveListener = removeListener; + + return () -> mRemoveListener = NO_OP_CONSUMER; + } } diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java index 97cf267d3..018f93a5c 100644 --- a/src/com/android/launcher3/model/BaseLoaderResults.java +++ b/src/com/android/launcher3/model/BaseLoaderResults.java @@ -19,14 +19,13 @@ package com.android.launcher3.model; import android.os.Looper; import android.util.Log; -import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; 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.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.LauncherSettings; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.PagedView; @@ -279,9 +278,8 @@ public abstract class BaseLoaderResults { public void bindAllApps() { // shallow copy - @SuppressWarnings("unchecked") - ArrayList<AppInfo> list = (ArrayList<AppInfo>) mBgAllAppsList.data.clone(); - executeCallbacksTask(c -> c.bindAllApplications(list), mUiExecutor); + AppInfo[] apps = mBgAllAppsList.copyData(); + executeCallbacksTask(c -> c.bindAllApplications(apps), mUiExecutor); } public abstract void bindWidgets(); diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java index eea3d8c35..e12633bcd 100644 --- a/src/com/android/launcher3/model/BaseModelUpdateTask.java +++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java @@ -17,12 +17,12 @@ package com.android.launcher3.model; import android.util.Log; -import com.android.launcher3.AllAppsList; +import com.android.launcher3.AppInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.ModelUpdateTask; import com.android.launcher3.LauncherModel.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ItemInfoMatcher; @@ -30,6 +30,7 @@ import com.android.launcher3.widget.WidgetListRowEntry; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.concurrent.Executor; /** @@ -95,12 +96,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { public void bindUpdatedWorkspaceItems(final ArrayList<WorkspaceItemInfo> updatedShortcuts) { if (!updatedShortcuts.isEmpty()) { - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindWorkspaceItemsChanged(updatedShortcuts); - } - }); + scheduleCallbackTask(c -> c.bindWorkspaceItemsChanged(updatedShortcuts)); } } @@ -113,23 +109,20 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { public void bindUpdatedWidgets(BgDataModel dataModel) { final ArrayList<WidgetListRowEntry> widgets = dataModel.widgetsModel.getWidgetsList(mApp.getContext()); - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindAllWidgets(widgets); - } - }); + scheduleCallbackTask(c -> c.bindAllWidgets(widgets)); } public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) { getModelWriter().deleteItemsFromDatabase(matcher); // Call the components-removed callback - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindWorkspaceComponentsRemoved(matcher); - } - }); + scheduleCallbackTask(c -> c.bindWorkspaceComponentsRemoved(matcher)); + } + + public void bindApplicationsIfNeeded() { + if (mAllAppsList.getAndResetChangeFlag()) { + AppInfo[] apps = mAllAppsList.copyData(); + scheduleCallbackTask(c -> c.bindAllApplications(apps)); + } } } diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index 8f0cd08a9..0e2027050 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -22,11 +22,13 @@ import android.text.TextUtils; import android.util.Log; import android.util.MutableInt; +import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; import com.android.launcher3.InstallShortcutReceiver; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherSettings; +import com.android.launcher3.PromiseAppInfo; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.Workspace; import com.android.launcher3.config.FeatureFlags; @@ -40,6 +42,10 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; +import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.launcher3.widget.WidgetListRowEntry; + import com.google.protobuf.nano.MessageNano; import java.io.FileDescriptor; @@ -49,6 +55,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -391,4 +398,30 @@ public class BgDataModel { } } } + + public interface Callbacks { + void rebindModel(); + + int getCurrentWorkspaceScreen(); + void clearPendingBinds(); + void startBinding(); + void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons); + void bindScreens(IntArray orderedScreenIds); + void finishFirstPageBind(ViewOnDrawExecutor executor); + void finishBindingItems(int pageBoundFirst); + void preAddApps(); + void bindAppsAdded(IntArray newScreens, + ArrayList<ItemInfo> addNotAnimated, ArrayList<ItemInfo> addAnimated); + void bindPromiseAppProgressUpdated(PromiseAppInfo app); + void bindWorkspaceItemsChanged(ArrayList<WorkspaceItemInfo> updated); + void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets); + void bindRestoreItemsChange(HashSet<ItemInfo> updates); + void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher); + void bindAllWidgets(ArrayList<WidgetListRowEntry> widgets); + void onPageBoundSynchronously(int page); + void executeOnNextDraw(ViewOnDrawExecutor executor); + void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMap); + + void bindAllApplications(AppInfo[] apps); + } } diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java index 7852444de..c1c8be316 100644 --- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java +++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java @@ -18,14 +18,10 @@ package com.android.launcher3.model; import android.content.ComponentName; import android.os.UserHandle; -import com.android.launcher3.AllAppsList; -import com.android.launcher3.AppInfo; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.icons.IconCache; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; import com.android.launcher3.LauncherSettings; import java.util.ArrayList; @@ -53,9 +49,9 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask { public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) { IconCache iconCache = app.getIconCache(); - final ArrayList<AppInfo> updatedApps = new ArrayList<>(); ArrayList<WorkspaceItemInfo> updatedShortcuts = new ArrayList<>(); + synchronized (dataModel) { for (ItemInfo info : dataModel.itemsIdMap) { if (info instanceof WorkspaceItemInfo && mUser.equals(info.user)) { @@ -69,18 +65,10 @@ public class CacheDataUpdatedTask extends BaseModelUpdateTask { } } } - apps.updateIconsAndLabels(mPackages, mUser, updatedApps); + apps.updateIconsAndLabels(mPackages, mUser); } bindUpdatedWorkspaceItems(updatedShortcuts); - - if (!updatedApps.isEmpty()) { - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindAppsAddedOrUpdated(updatedApps); - } - }); - } + bindApplicationsIfNeeded(); } public boolean isValidShortcut(WorkspaceItemInfo si) { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 6c3394669..19eaadb25 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -40,7 +40,6 @@ import android.util.Log; import android.util.LongSparseArray; import android.util.MutableInt; -import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; import com.android.launcher3.InstallShortcutReceiver; @@ -831,7 +830,7 @@ public class LoaderTask implements Runnable { } } - mBgAllAppsList.added = new ArrayList<>(); + mBgAllAppsList.getAndResetChangeFlag(); return allActivityList; } diff --git a/src/com/android/launcher3/model/ModelPreload.java b/src/com/android/launcher3/model/ModelPreload.java index b353810ef..2bd6cd4db 100644 --- a/src/com/android/launcher3/model/ModelPreload.java +++ b/src/com/android/launcher3/model/ModelPreload.java @@ -18,7 +18,6 @@ package com.android.launcher3.model; import android.content.Context; import android.util.Log; -import com.android.launcher3.AllAppsList; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherModel.ModelUpdateTask; diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 4ce2f4ba9..d7ab0ddae 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -31,7 +31,7 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetHost; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherModel; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.LauncherProvider; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java index 5f6d1281b..e43412d60 100644 --- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java +++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java @@ -20,20 +20,18 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.Process; -import com.android.launcher3.AllAppsList; import com.android.launcher3.AppInfo; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherModel.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.PromiseAppInfo; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.util.InstantAppResolver; -import java.util.ArrayList; import java.util.HashSet; /** @@ -66,41 +64,11 @@ public class PackageInstallStateChangedTask extends BaseModelUpdateTask { } synchronized (apps) { - PromiseAppInfo updated = null; - final ArrayList<AppInfo> removed = new ArrayList<>(); - for (int i=0; i < apps.size(); i++) { - final AppInfo appInfo = apps.get(i); - final ComponentName tgtComp = appInfo.getTargetComponent(); - if (tgtComp != null && tgtComp.getPackageName().equals(mInstallInfo.packageName)) { - if (appInfo instanceof PromiseAppInfo) { - final PromiseAppInfo promiseAppInfo = (PromiseAppInfo) appInfo; - if (mInstallInfo.state == PackageInstallerCompat.STATUS_INSTALLING) { - promiseAppInfo.level = mInstallInfo.progress; - updated = promiseAppInfo; - } else if (mInstallInfo.state == PackageInstallerCompat.STATUS_FAILED) { - apps.removePromiseApp(appInfo); - removed.add(appInfo); - } - } - } - } + PromiseAppInfo updated = apps.updatePromiseInstallInfo(mInstallInfo); if (updated != null) { - final PromiseAppInfo updatedPromiseApp = updated; - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindPromiseAppProgressUpdated(updatedPromiseApp); - } - }); - } - if (!removed.isEmpty()) { - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindAppInfosRemoved(removed); - } - }); + scheduleCallbackTask(c -> c.bindPromiseAppProgressUpdated(updated)); } + bindApplicationsIfNeeded(); } synchronized (dataModel) { diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index c37ed9952..17a9a02d5 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -23,23 +23,19 @@ import android.os.Process; import android.os.UserHandle; import android.util.Log; -import com.android.launcher3.AllAppsList; -import com.android.launcher3.AppInfo; -import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.IconCache; import com.android.launcher3.InstallShortcutReceiver; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetInfo; -import com.android.launcher3.LauncherModel.CallbackTask; -import com.android.launcher3.LauncherModel.Callbacks; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.SessionCommitReceiver; import com.android.launcher3.Utilities; +import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.logging.FileLog; import com.android.launcher3.shortcuts.DeepShortcutManager; @@ -48,6 +44,7 @@ import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; +import com.android.launcher3.util.SafeCloseable; import java.util.ArrayList; import java.util.Arrays; @@ -93,6 +90,8 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { FlagOp flagOp = FlagOp.NO_OP; final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages)); ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(packageSet, mUser); + final HashSet<ComponentName> removedComponents = new HashSet<>(); + switch (mOp) { case OP_ADD: { for (int i = 0; i < N; i++) { @@ -112,11 +111,14 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { break; } case OP_UPDATE: - for (int i = 0; i < N; i++) { - if (DEBUG) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]); - iconCache.updateIconsForPkg(packages[i], mUser); - appsList.updatePackage(context, packages[i], mUser); - app.getWidgetCache().removePackage(packages[i], mUser); + try (SafeCloseable t = + appsList.trackRemoves(a -> removedComponents.add(a.componentName))) { + for (int i = 0; i < N; i++) { + if (DEBUG) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]); + iconCache.updateIconsForPkg(packages[i], mUser); + appsList.updatePackage(context, packages[i], mUser); + app.getWidgetCache().removePackage(packages[i], mUser); + } } // Since package was just updated, the target must be available now. flagOp = FlagOp.removeFlag(WorkspaceItemInfo.FLAG_DISABLED_NOT_AVAILABLE); @@ -153,23 +155,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { break; } - final ArrayList<AppInfo> addedOrModified = new ArrayList<>(); - addedOrModified.addAll(appsList.added); - appsList.added.clear(); - addedOrModified.addAll(appsList.modified); - appsList.modified.clear(); - if (!addedOrModified.isEmpty()) { - scheduleCallbackTask((callbacks) -> callbacks.bindAppsAddedOrUpdated(addedOrModified)); - } - - final ArrayList<AppInfo> removedApps = new ArrayList<>(appsList.removed); - appsList.removed.clear(); - final HashSet<ComponentName> removedComponents = new HashSet<>(); - if (mOp == OP_UPDATE) { - for (AppInfo ai : removedApps) { - removedComponents.add(ai.componentName); - } - } + bindApplicationsIfNeeded(); final IntSparseArrayMap<Boolean> removedShortcuts = new IntSparseArrayMap<>(); @@ -296,12 +282,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if (!widgets.isEmpty()) { - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindWidgetsRestored(widgets); - } - }); + scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets)); } } @@ -332,16 +313,6 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser); } - if (!removedApps.isEmpty()) { - // Remove corresponding apps from All-Apps - scheduleCallbackTask(new CallbackTask() { - @Override - public void execute(Callbacks callbacks) { - callbacks.bindAppInfosRemoved(removedApps); - } - }); - } - if (Utilities.ATLEAST_OREO && mOp == OP_ADD) { // Load widgets for the new package. Changes due to app updates are handled through // AppWidgetHost events, this is just to initialize the long-press options. diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java index 8528228f2..c3cd9d07b 100644 --- a/src/com/android/launcher3/model/ShortcutsChangedTask.java +++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.pm.ShortcutInfo; import android.os.UserHandle; -import com.android.launcher3.AllAppsList; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java index 50fff2653..4b773d720 100644 --- a/src/com/android/launcher3/model/UserLockStateChangedTask.java +++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.pm.ShortcutInfo; import android.os.UserHandle; -import com.android.launcher3.AllAppsList; import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; diff --git a/src/com/android/launcher3/states/InternalStateHandler.java b/src/com/android/launcher3/states/InternalStateHandler.java index c6370c5c5..446d4f8ed 100644 --- a/src/com/android/launcher3/states/InternalStateHandler.java +++ b/src/com/android/launcher3/states/InternalStateHandler.java @@ -22,7 +22,7 @@ import android.os.IBinder; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.MainThreadExecutor; import java.lang.ref.WeakReference; diff --git a/src/com/android/launcher3/util/SafeCloseable.java b/src/com/android/launcher3/util/SafeCloseable.java new file mode 100644 index 000000000..ba8ee04d2 --- /dev/null +++ b/src/com/android/launcher3/util/SafeCloseable.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 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.util; + +/** + * Extension of closeable which does not throw an exception + */ +public interface SafeCloseable extends AutoCloseable { + + @Override + void close(); +} diff --git a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java index 1710aef12..789bfd868 100644 --- a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java +++ b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java @@ -16,9 +16,8 @@ package com.android.launcher3.model; -import com.android.launcher3.AllAppsList; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherModel.Callbacks; +import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.widget.WidgetListRowEntry; |