summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2018-09-21 14:41:05 -0700
committerSunny Goyal <sunnygoyal@google.com>2018-09-21 15:27:03 -0700
commitf840f10d500d3e11f8512a878c57f07bca635587 (patch)
treecb6fcc99833817503e22ed67df000a61a0ac9b8a /src/com/android/launcher3
parent1473b8e1025d17578b08e062427c3af46764efa6 (diff)
downloadandroid_packages_apps_Trebuchet-f840f10d500d3e11f8512a878c57f07bca635587.tar.gz
android_packages_apps_Trebuchet-f840f10d500d3e11f8512a878c57f07bca635587.tar.bz2
android_packages_apps_Trebuchet-f840f10d500d3e11f8512a878c57f07bca635587.zip
Removing additional rpc due to icon cache update
When launcher loads, it fetches the list of apps twice, once for loading all-apps and again for updating icons. Instead reusing the previously fetched apps list. Also moving the icon loading in a separate package for further generalization Change-Id: Ibd2dae56e6027a31b633da030bc6b43a90b27e1b
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/AllAppsList.java1
-rw-r--r--src/com/android/launcher3/BubbleTextView.java4
-rw-r--r--src/com/android/launcher3/Launcher.java1
-rw-r--r--src/com/android/launcher3/LauncherAppState.java1
-rw-r--r--src/com/android/launcher3/LauncherModel.java1
-rw-r--r--src/com/android/launcher3/ShortcutInfo.java1
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java1
-rw-r--r--src/com/android/launcher3/compat/PackageInstallerCompatVL.java2
-rw-r--r--src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java2
-rw-r--r--src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java2
-rw-r--r--src/com/android/launcher3/graphics/LauncherIcons.java2
-rw-r--r--src/com/android/launcher3/icons/IconCache.java (renamed from src/com/android/launcher3/IconCache.java)235
-rw-r--r--src/com/android/launcher3/icons/IconCacheUpdateHandler.java223
-rw-r--r--src/com/android/launcher3/model/CacheDataUpdatedTask.java2
-rw-r--r--src/com/android/launcher3/model/LoaderCursor.java2
-rw-r--r--src/com/android/launcher3/model/LoaderTask.java29
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java2
-rw-r--r--src/com/android/launcher3/model/WidgetsModel.java2
-rw-r--r--src/com/android/launcher3/widget/PendingAppWidgetHostView.java4
-rw-r--r--src/com/android/launcher3/widget/WidgetsDiffReporter.java2
-rw-r--r--src/com/android/launcher3/widget/WidgetsListAdapter.java2
21 files changed, 301 insertions, 220 deletions
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index 3d6060545..733f29540 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -26,6 +26,7 @@ import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.ItemInfoMatcher;
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 5d401433b..8e6703cc5 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -40,8 +40,8 @@ import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.widget.TextView;
-import com.android.launcher3.IconCache.IconLoadRequest;
-import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.icons.IconCache.IconLoadRequest;
+import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.Launcher.OnResumeCallback;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.badge.BadgeRenderer;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 55074f813..b5bbb9c68 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -87,6 +87,7 @@ import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.keyboard.CustomActionsPopup;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.logging.FileLog;
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 5159de17a..b02182c57 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -29,6 +29,7 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 7a90a55d4..df1c69338 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -39,6 +39,7 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.AddWorkspaceItemsTask;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
diff --git a/src/com/android/launcher3/ShortcutInfo.java b/src/com/android/launcher3/ShortcutInfo.java
index a84bfd54e..7717d9188 100644
--- a/src/com/android/launcher3/ShortcutInfo.java
+++ b/src/com/android/launcher3/ShortcutInfo.java
@@ -25,6 +25,7 @@ import android.text.TextUtils;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.ContentWriter;
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 84bad0858..cf497fd87 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -33,6 +33,7 @@ import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.graphics.ShadowGenerator;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
diff --git a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
index dd17916f0..fe7b4e5d0 100644
--- a/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
+++ b/src/com/android/launcher3/compat/PackageInstallerCompatVL.java
@@ -27,7 +27,7 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.SparseArray;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.config.FeatureFlags;
diff --git a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
index 31c0087cb..d260e24e7 100644
--- a/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/compat/ShortcutConfigActivityInfo.java
@@ -32,7 +32,7 @@ import android.os.UserHandle;
import android.util.Log;
import android.widget.Toast;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutInfo;
diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
index 52167bb8b..bd919bcbc 100644
--- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
+++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java
@@ -28,7 +28,7 @@ import android.os.Build;
import android.os.Process;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 087362cd4..7db67c982 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -44,7 +44,7 @@ import android.os.UserHandle;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 61fb3e38b..2035d0e57 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3;
+package com.android.launcher3.icons;
import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON;
@@ -38,11 +38,19 @@ import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.Process;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.IconProvider;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.ItemInfoWithIcon;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.graphics.BitmapInfo;
@@ -54,14 +62,9 @@ import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
-import com.android.launcher3.util.Thunk;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.Stack;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
@@ -81,8 +84,6 @@ public class IconCache {
private static final boolean DEBUG = false;
private static final boolean DEBUG_IGNORE_CACHE = false;
- @Thunk static final Object ICON_UPDATE_TOKEN = new Object();
-
public static class CacheEntry extends BitmapInfo {
public CharSequence title = "";
public CharSequence contentDescription = "";
@@ -93,20 +94,21 @@ public class IconCache {
}
private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>();
- @Thunk final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
- private final Context mContext;
- private final PackageManager mPackageManager;
- private final IconProvider mIconProvider;
- @Thunk final UserManagerCompat mUserManager;
- private final LauncherAppsCompat mLauncherApps;
+ final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
+ final Context mContext;
+ final PackageManager mPackageManager;
+ final IconProvider mIconProvider;
+ final UserManagerCompat mUserManager;
+ final LauncherAppsCompat mLauncherApps;
+
private final HashMap<ComponentKey, CacheEntry> mCache =
new HashMap<>(INITIAL_ICON_CACHE_CAPACITY);
private final InstantAppResolver mInstantAppResolver;
private final int mIconDpi;
- @Thunk final IconDB mIconDb;
- @Thunk final Handler mWorkerHandler;
+ final IconDB mIconDb;
+ final Handler mWorkerHandler;
private final BitmapFactory.Options mDecodeOptions;
@@ -247,115 +249,9 @@ public class IconCache {
new String[]{packageName + "/%", Long.toString(userSerial)});
}
- public void updateDbIcons(Set<String> ignorePackagesForMainUser) {
- // Remove all active icon update tasks.
- mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
-
+ public IconCacheUpdateHandler getUpdateHandler() {
mIconProvider.updateSystemStateString(mContext);
- for (UserHandle user : mUserManager.getUserProfiles()) {
- // Query for the set of apps
- final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
- // Fail if we don't have any apps
- // TODO: Fix this. Only fail for the current user.
- if (apps == null || apps.isEmpty()) {
- return;
- }
-
- // Update icon cache. This happens in segments and {@link #onPackageIconsUpdated}
- // is called by the icon cache when the job is complete.
- updateDBIcons(user, apps, Process.myUserHandle().equals(user)
- ? ignorePackagesForMainUser : Collections.<String>emptySet());
- }
- }
-
- /**
- * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
- * the DB and are updated.
- * @return The set of packages for which icons have updated.
- */
- private void updateDBIcons(UserHandle user, List<LauncherActivityInfo> apps,
- Set<String> ignorePackages) {
- long userSerial = mUserManager.getSerialNumberForUser(user);
- PackageManager pm = mContext.getPackageManager();
- HashMap<String, PackageInfo> pkgInfoMap = new HashMap<>();
- for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
- pkgInfoMap.put(info.packageName, info);
- }
-
- HashMap<ComponentName, LauncherActivityInfo> componentMap = new HashMap<>();
- for (LauncherActivityInfo app : apps) {
- componentMap.put(app.getComponentName(), app);
- }
-
- HashSet<Integer> itemsToRemove = new HashSet<>();
- Stack<LauncherActivityInfo> appsToUpdate = new Stack<>();
-
- Cursor c = null;
- try {
- c = mIconDb.query(
- new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
- IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
- IconDB.COLUMN_SYSTEM_STATE},
- IconDB.COLUMN_USER + " = ? ",
- new String[]{Long.toString(userSerial)});
-
- final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
- final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
- final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
- final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
- final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
-
- while (c.moveToNext()) {
- String cn = c.getString(indexComponent);
- ComponentName component = ComponentName.unflattenFromString(cn);
- PackageInfo info = pkgInfoMap.get(component.getPackageName());
- if (info == null) {
- if (!ignorePackages.contains(component.getPackageName())) {
- remove(component, user);
- itemsToRemove.add(c.getInt(rowIndex));
- }
- continue;
- }
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
- // Application is not present
- continue;
- }
-
- long updateTime = c.getLong(indexLastUpdate);
- int version = c.getInt(indexVersion);
- LauncherActivityInfo app = componentMap.remove(component);
- if (version == info.versionCode && updateTime == info.lastUpdateTime &&
- TextUtils.equals(c.getString(systemStateIndex),
- mIconProvider.getIconSystemState(info.packageName))) {
- continue;
- }
- if (app == null) {
- remove(component, user);
- itemsToRemove.add(c.getInt(rowIndex));
- } else {
- appsToUpdate.add(app);
- }
- }
- } catch (SQLiteException e) {
- Log.d(TAG, "Error reading icon cache", e);
- // Continue updating whatever we have read so far
- } finally {
- if (c != null) {
- c.close();
- }
- }
- if (!itemsToRemove.isEmpty()) {
- mIconDb.delete(
- Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null);
- }
-
- // Insert remaining apps.
- if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
- Stack<LauncherActivityInfo> appsToAdd = new Stack<>();
- appsToAdd.addAll(componentMap.values());
- new SerializedIconUpdateTask(userSerial, pkgInfoMap,
- appsToAdd, appsToUpdate).scheduleNext();
- }
+ return new IconCacheUpdateHandler(this);
}
/**
@@ -363,8 +259,9 @@ public class IconCache {
* @param replaceExisting if true, it will recreate the bitmap even if it already exists in
* the memory. This is useful then the previous bitmap was created using
* old data.
+ * package private
*/
- @Thunk synchronized void addIconToDBAndMemCache(LauncherActivityInfo app,
+ synchronized void addIconToDBAndMemCache(LauncherActivityInfo app,
PackageInfo info, long userSerial, boolean replaceExisting) {
final ComponentKey key = new ComponentKey(app.getComponentName(), app.getUser());
CacheEntry entry = null;
@@ -744,81 +641,23 @@ public class IconCache {
}
}
- /**
- * A runnable that updates invalid icons and adds missing icons in the DB for the provided
- * LauncherActivityInfo list. Items are updated/added one at a time, so that the
- * worker thread doesn't get blocked.
- */
- @Thunk class SerializedIconUpdateTask implements Runnable {
- private final long mUserSerial;
- private final HashMap<String, PackageInfo> mPkgInfoMap;
- private final Stack<LauncherActivityInfo> mAppsToAdd;
- private final Stack<LauncherActivityInfo> mAppsToUpdate;
- private final HashSet<String> mUpdatedPackages = new HashSet<>();
-
- @Thunk SerializedIconUpdateTask(long userSerial, HashMap<String, PackageInfo> pkgInfoMap,
- Stack<LauncherActivityInfo> appsToAdd,
- Stack<LauncherActivityInfo> appsToUpdate) {
- mUserSerial = userSerial;
- mPkgInfoMap = pkgInfoMap;
- mAppsToAdd = appsToAdd;
- mAppsToUpdate = appsToUpdate;
- }
-
- @Override
- public void run() {
- if (!mAppsToUpdate.isEmpty()) {
- LauncherActivityInfo app = mAppsToUpdate.pop();
- String pkg = app.getComponentName().getPackageName();
- PackageInfo info = mPkgInfoMap.get(pkg);
- addIconToDBAndMemCache(app, info, mUserSerial, true /*replace existing*/);
- mUpdatedPackages.add(pkg);
-
- if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
- // No more app to update. Notify model.
- LauncherAppState.getInstance(mContext).getModel().onPackageIconsUpdated(
- mUpdatedPackages, mUserManager.getUserForSerialNumber(mUserSerial));
- }
-
- // Let it run one more time.
- scheduleNext();
- } else if (!mAppsToAdd.isEmpty()) {
- LauncherActivityInfo app = mAppsToAdd.pop();
- PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName());
- // We do not check the mPkgInfoMap when generating the mAppsToAdd. Although every
- // app should have package info, this is not guaranteed by the api
- if (info != null) {
- addIconToDBAndMemCache(app, info, mUserSerial, false /*replace existing*/);
- }
-
- if (!mAppsToAdd.isEmpty()) {
- scheduleNext();
- }
- }
- }
-
- public void scheduleNext() {
- mWorkerHandler.postAtTime(this, ICON_UPDATE_TOKEN, SystemClock.uptimeMillis() + 1);
- }
- }
-
- private static final class IconDB extends SQLiteCacheHelper {
+ static final class IconDB extends SQLiteCacheHelper {
private final static int RELEASE_VERSION = 25;
- private final static String TABLE_NAME = "icons";
- private final static String COLUMN_ROWID = "rowid";
- private final static String COLUMN_COMPONENT = "componentName";
- private final static String COLUMN_USER = "profileId";
- private final static String COLUMN_LAST_UPDATED = "lastUpdated";
- private final static String COLUMN_VERSION = "version";
- private final static String COLUMN_ICON = "icon";
- private final static String COLUMN_ICON_COLOR = "icon_color";
- private final static String COLUMN_LABEL = "label";
- private final static String COLUMN_SYSTEM_STATE = "system_state";
-
- private final static String[] COLUMNS_HIGH_RES = new String[] {
+ public final static String TABLE_NAME = "icons";
+ public final static String COLUMN_ROWID = "rowid";
+ public final static String COLUMN_COMPONENT = "componentName";
+ public final static String COLUMN_USER = "profileId";
+ public final static String COLUMN_LAST_UPDATED = "lastUpdated";
+ public final static String COLUMN_VERSION = "version";
+ public final static String COLUMN_ICON = "icon";
+ public final static String COLUMN_ICON_COLOR = "icon_color";
+ public final static String COLUMN_LABEL = "label";
+ public final static String COLUMN_SYSTEM_STATE = "system_state";
+
+ public final static String[] COLUMNS_HIGH_RES = new String[] {
IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL, IconDB.COLUMN_ICON };
- private final static String[] COLUMNS_LOW_RES = new String[] {
+ public final static String[] COLUMNS_LOW_RES = new String[] {
IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL };
public IconDB(Context context, int iconPixelSize) {
diff --git a/src/com/android/launcher3/icons/IconCacheUpdateHandler.java b/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
new file mode 100644
index 000000000..04e29013a
--- /dev/null
+++ b/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
@@ -0,0 +1,223 @@
+/*
+ * 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.icons;
+
+import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.icons.IconCache.IconDB;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+
+/**
+ * Utility class to handle updating the Icon cache
+ */
+public class IconCacheUpdateHandler {
+
+ private static final String TAG = "IconCacheUpdateHandler";
+
+ private static final Object ICON_UPDATE_TOKEN = new Object();
+
+ private final HashMap<String, PackageInfo> mPkgInfoMap;
+ private final IconCache mIconCache;
+ private final HashMap<UserHandle, Set<String>> mPackagesToIgnore = new HashMap<>();
+
+ IconCacheUpdateHandler(IconCache cache) {
+ mIconCache = cache;
+
+ mPkgInfoMap = new HashMap<>();
+
+ // Remove all active icon update tasks.
+ mIconCache.mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
+
+ createPackageInfoMap();
+ }
+
+ public void setPackagesToIgnore(UserHandle userHandle, Set<String> packages) {
+ mPackagesToIgnore.put(userHandle, packages);
+ }
+
+ private void createPackageInfoMap() {
+ PackageManager pm = mIconCache.mPackageManager;
+ HashMap<String, PackageInfo> pkgInfoMap = new HashMap<>();
+ for (PackageInfo info : pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
+ pkgInfoMap.put(info.packageName, info);
+ }
+ }
+
+ /**
+ * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
+ * the DB and are updated.
+ * @return The set of packages for which icons have updated.
+ */
+ public void updateIcons(List<LauncherActivityInfo> apps) {
+ if (apps.isEmpty()) {
+ return;
+ }
+ UserHandle user = apps.get(0).getUser();
+
+ Set<String> ignorePackages = mPackagesToIgnore.get(user);
+ if (ignorePackages == null) {
+ ignorePackages = Collections.emptySet();
+ }
+
+ long userSerial = mIconCache.mUserManager.getSerialNumberForUser(user);
+ HashMap<ComponentName, LauncherActivityInfo> componentMap = new HashMap<>();
+ for (LauncherActivityInfo app : apps) {
+ componentMap.put(app.getComponentName(), app);
+ }
+
+ HashSet<Integer> itemsToRemove = new HashSet<>();
+ Stack<LauncherActivityInfo> appsToUpdate = new Stack<>();
+
+ try (Cursor c = mIconCache.mIconDb.query(
+ new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
+ IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
+ IconDB.COLUMN_SYSTEM_STATE},
+ IconDB.COLUMN_USER + " = ? ",
+ new String[]{Long.toString(userSerial)})) {
+
+ final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
+ final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
+ final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
+ final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
+ final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
+
+ while (c.moveToNext()) {
+ String cn = c.getString(indexComponent);
+ ComponentName component = ComponentName.unflattenFromString(cn);
+ PackageInfo info = mPkgInfoMap.get(component.getPackageName());
+ if (info == null) {
+ if (!ignorePackages.contains(component.getPackageName())) {
+ mIconCache.remove(component, user);
+ itemsToRemove.add(c.getInt(rowIndex));
+ }
+ continue;
+ }
+ if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
+ // Application is not present
+ continue;
+ }
+
+ long updateTime = c.getLong(indexLastUpdate);
+ int version = c.getInt(indexVersion);
+ LauncherActivityInfo app = componentMap.remove(component);
+ if (version == info.versionCode && updateTime == info.lastUpdateTime &&
+ TextUtils.equals(c.getString(systemStateIndex),
+ mIconCache.mIconProvider.getIconSystemState(info.packageName))) {
+ continue;
+ }
+ if (app == null) {
+ mIconCache.remove(component, user);
+ itemsToRemove.add(c.getInt(rowIndex));
+ } else {
+ appsToUpdate.add(app);
+ }
+ }
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Error reading icon cache", e);
+ // Continue updating whatever we have read so far
+ }
+ if (!itemsToRemove.isEmpty()) {
+ mIconCache.mIconDb.delete(
+ Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null);
+ }
+
+ // Insert remaining apps.
+ if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
+ Stack<LauncherActivityInfo> appsToAdd = new Stack<>();
+ appsToAdd.addAll(componentMap.values());
+ new SerializedIconUpdateTask(userSerial, user, appsToAdd, appsToUpdate).scheduleNext();
+ }
+ }
+
+
+ /**
+ * A runnable that updates invalid icons and adds missing icons in the DB for the provided
+ * LauncherActivityInfo list. Items are updated/added one at a time, so that the
+ * worker thread doesn't get blocked.
+ */
+ private class SerializedIconUpdateTask implements Runnable {
+ private final long mUserSerial;
+ private final UserHandle mUserHandle;
+ private final Stack<LauncherActivityInfo> mAppsToAdd;
+ private final Stack<LauncherActivityInfo> mAppsToUpdate;
+ private final HashSet<String> mUpdatedPackages = new HashSet<>();
+
+ SerializedIconUpdateTask(long userSerial, UserHandle userHandle,
+ Stack<LauncherActivityInfo> appsToAdd, Stack<LauncherActivityInfo> appsToUpdate) {
+ mUserHandle = userHandle;
+ mUserSerial = userSerial;
+ mAppsToAdd = appsToAdd;
+ mAppsToUpdate = appsToUpdate;
+ }
+
+ @Override
+ public void run() {
+ if (!mAppsToUpdate.isEmpty()) {
+ LauncherActivityInfo app = mAppsToUpdate.pop();
+ String pkg = app.getComponentName().getPackageName();
+ PackageInfo info = mPkgInfoMap.get(pkg);
+ mIconCache.addIconToDBAndMemCache(
+ app, info, mUserSerial, true /*replace existing*/);
+ mUpdatedPackages.add(pkg);
+
+ if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
+ // No more app to update. Notify model.
+ LauncherAppState.getInstance(mIconCache.mContext).getModel()
+ .onPackageIconsUpdated(mUpdatedPackages, mUserHandle);
+ }
+
+ // Let it run one more time.
+ scheduleNext();
+ } else if (!mAppsToAdd.isEmpty()) {
+ LauncherActivityInfo app = mAppsToAdd.pop();
+ PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName());
+ // We do not check the mPkgInfoMap when generating the mAppsToAdd. Although every
+ // app should have package info, this is not guaranteed by the api
+ if (info != null) {
+ mIconCache.addIconToDBAndMemCache(
+ app, info, mUserSerial, false /*replace existing*/);
+ }
+
+ if (!mAppsToAdd.isEmpty()) {
+ scheduleNext();
+ }
+ }
+ }
+
+ public void scheduleNext() {
+ mIconCache.mWorkerHandler.postAtTime(this, ICON_UPDATE_TOKEN,
+ SystemClock.uptimeMillis() + 1);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index 54c054276..be83d3692 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -20,7 +20,7 @@ import android.os.UserHandle;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel.CallbackTask;
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 744e98aea..77e9721bc 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -32,7 +32,7 @@ import android.util.Log;
import android.util.LongSparseArray;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 8f8bc09f3..4ccb8d8d6 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -43,7 +43,8 @@ import android.util.MutableInt;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCacheUpdateHandler;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
@@ -182,7 +183,7 @@ public class LoaderTask implements Runnable {
// second step
TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
- loadAllApps();
+ List<List<LauncherActivityInfo>> activityListPerUser = loadAllApps();
TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
verifyNotStopped();
@@ -190,7 +191,9 @@ public class LoaderTask implements Runnable {
verifyNotStopped();
TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");
- updateIconCache();
+ IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
+ setIgnorePackages(updateHandler);
+ updateIconCacheForApps(updateHandler, activityListPerUser);
// Take a break
TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle");
@@ -774,7 +777,7 @@ public class LoaderTask implements Runnable {
}
}
- private void updateIconCache() {
+ private void setIgnorePackages(IconCacheUpdateHandler updateHandler) {
// Ignore packages which have a promise icon.
HashSet<String> packagesToIgnore = new HashSet<>();
synchronized (mBgDataModel) {
@@ -792,12 +795,20 @@ public class LoaderTask implements Runnable {
}
}
}
- mIconCache.updateDbIcons(packagesToIgnore);
+ updateHandler.setPackagesToIgnore(Process.myUserHandle(), packagesToIgnore);
}
- private void loadAllApps() {
- final List<UserHandle> profiles = mUserManager.getUserProfiles();
+ private void updateIconCacheForApps(IconCacheUpdateHandler updateHandler,
+ List<List<LauncherActivityInfo>> activityListPerUser) {
+ int userCount = activityListPerUser.size();
+ for (int i = 0; i < userCount; i++) {
+ updateHandler.updateIcons(activityListPerUser.get(i));
+ }
+ }
+ private List<List<LauncherActivityInfo>> loadAllApps() {
+ final List<UserHandle> profiles = mUserManager.getUserProfiles();
+ List<List<LauncherActivityInfo>> activityListPerUser = new ArrayList<>();
// Clear the list of apps
mBgAllAppsList.clear();
for (UserHandle user : profiles) {
@@ -806,7 +817,7 @@ public class LoaderTask implements Runnable {
// Fail if we don't have any apps
// TODO: Fix this. Only fail for the current user.
if (apps == null || apps.isEmpty()) {
- return;
+ return activityListPerUser;
}
boolean quietMode = mUserManager.isQuietModeEnabled(user);
// Create the ApplicationInfos
@@ -815,6 +826,7 @@ public class LoaderTask implements Runnable {
// This builds the icon bitmaps.
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
}
+ activityListPerUser.add(apps);
}
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
@@ -827,6 +839,7 @@ public class LoaderTask implements Runnable {
}
mBgAllAppsList.added = new ArrayList<>();
+ return activityListPerUser;
}
private void loadDeepShortcuts() {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index c55608310..0af53118d 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -24,7 +24,7 @@ import android.util.Log;
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
index 448ff6c92..82f4fe189 100644
--- a/src/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -11,7 +11,7 @@ import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.AppFilter;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 29b4b0ba2..50db40fde 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -33,8 +33,8 @@ import android.view.View.OnClickListener;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.IconCache;
-import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.R;
diff --git a/src/com/android/launcher3/widget/WidgetsDiffReporter.java b/src/com/android/launcher3/widget/WidgetsDiffReporter.java
index 2ba672d7a..435125bd8 100644
--- a/src/com/android/launcher3/widget/WidgetsDiffReporter.java
+++ b/src/com/android/launcher3/widget/WidgetsDiffReporter.java
@@ -18,7 +18,7 @@ package com.android.launcher3.widget;
import android.util.Log;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.widget.WidgetsListAdapter.WidgetListRowEntryComparator;
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index 1016d0400..a45521dee 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -23,7 +23,7 @@ import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.model.WidgetItem;