Merge "Add some gesture logging to track down quickscrub launch issue" into ub-launcher3-master
diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
index 88f2315..54269f09 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java
@@ -220,7 +220,7 @@
}
@Override
- public boolean onDrag(float displacement, float velocity) {
+ public boolean onDrag(float displacement) {
float totalDisplacement = displacement + mDisplacementShift;
boolean isGoingUp =
totalDisplacement == 0 ? mCurrentAnimationIsGoingUp : totalDisplacement < 0;
diff --git a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java
index 8f7dbdd..6557761 100644
--- a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java
+++ b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java
@@ -28,9 +28,9 @@
import android.util.SparseArray;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.graphics.BitmapInfo;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.graphics.DrawableFactory;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.systemui.shared.recents.model.IconLoader;
import com.android.systemui.shared.recents.model.TaskKeyLruCache;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 1a9915c..d9626c4 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -280,7 +280,6 @@
factory.createActivityController(RECENTS_LAUNCH_DURATION, INTERACTION_NORMAL);
mActivity = activity;
mRecentsView = mActivity.getOverviewPanel();
- mRecentsView.setRunningTaskIconScaledDown(true);
if (!mUserEventLogged) {
activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON,
mHelper.getContainerType(), ContainerType.TASKSWITCHER);
@@ -298,6 +297,9 @@
if (mListener != null) {
mListener.unregister();
}
+ if (mRecentsView != null) {
+ mRecentsView.setRunningTaskIconScaledDown(true);
+ }
AnimatorSet anim = new AnimatorSet();
anim.addListener(new AnimationSuccessListener() {
@Override
diff --git a/res/drawable-v26/adaptive_icon_drawable_wrapper.xml b/res/drawable-v26/adaptive_icon_drawable_wrapper.xml
index 2d78b69..9f13cf5 100644
--- a/res/drawable-v26/adaptive_icon_drawable_wrapper.xml
+++ b/res/drawable-v26/adaptive_icon_drawable_wrapper.xml
@@ -17,6 +17,6 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/legacy_icon_background"/>
<foreground>
- <com.android.launcher3.graphics.FixedScaleDrawable />
+ <com.android.launcher3.icons.FixedScaleDrawable />
</foreground>
</adaptive-icon>
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 6b0a90a..4c34071 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -39,7 +39,7 @@
import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 8e6703c..8513d63 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -272,8 +272,8 @@
/**
* Overrides the default long press timeout.
*/
- public void setLongPressTimeout(int longPressTimeout) {
- mLongPressHelper.setLongPressTimeout(longPressTimeout);
+ public void setLongPressTimeoutFactor(float longPressTimeoutFactor) {
+ mLongPressHelper.setLongPressTimeoutFactor(longPressTimeoutFactor);
}
@Override
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index dde733c..639c173 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -17,17 +17,18 @@
package com.android.launcher3;
import android.view.View;
+import android.view.ViewConfiguration;
import com.android.launcher3.util.Thunk;
public class CheckLongPressHelper {
- public static final int DEFAULT_LONG_PRESS_TIMEOUT = 300;
+ public static final float DEFAULT_LONG_PRESS_TIMEOUT_FACTOR = 0.75f;
@Thunk View mView;
@Thunk View.OnLongClickListener mListener;
@Thunk boolean mHasPerformedLongPress;
- private int mLongPressTimeout = DEFAULT_LONG_PRESS_TIMEOUT;
+ private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
private CheckForLongPress mPendingCheckForLongPress;
class CheckForLongPress implements Runnable {
@@ -60,8 +61,8 @@
/**
* Overrides the default long press timeout.
*/
- public void setLongPressTimeout(int longPressTimeout) {
- mLongPressTimeout = longPressTimeout;
+ public void setLongPressTimeoutFactor(float longPressTimeoutFactor) {
+ mLongPressTimeoutFactor = longPressTimeoutFactor;
}
public void postCheckForLongPress() {
@@ -70,7 +71,8 @@
if (mPendingCheckForLongPress == null) {
mPendingCheckForLongPress = new CheckForLongPress();
}
- mView.postDelayed(mPendingCheckForLongPress, mLongPressTimeout);
+ mView.postDelayed(mPendingCheckForLongPress,
+ (long) (ViewConfiguration.getLongPressTimeout() * mLongPressTimeoutFactor));
}
public void cancelLongPress() {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 9839c12..256fd6c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -30,7 +30,7 @@
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.badge.BadgeRenderer;
-import com.android.launcher3.graphics.IconNormalizer;
+import com.android.launcher3.icons.IconNormalizer;
public class DeviceProfile {
@@ -373,7 +373,7 @@
updateFolderCellSize(1f, dm, res);
// Don't let the folder get too close to the edges of the screen.
- int folderMargin = edgeMarginPx;
+ int folderMargin = edgeMarginPx * 2;
Point totalWorkspacePadding = getTotalWorkspacePadding();
// Check if the icons fit within the available height.
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 7efb6ec..daf587a 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -34,7 +34,7 @@
import android.util.Property;
import android.util.SparseArray;
-import com.android.launcher3.graphics.BitmapInfo;
+import com.android.launcher3.icons.BitmapInfo;
public class FastBitmapDrawable extends Drawable {
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index b9d45fb..7190f12 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -40,8 +40,8 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.graphics.BitmapInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
diff --git a/src/com/android/launcher3/ItemInfoWithIcon.java b/src/com/android/launcher3/ItemInfoWithIcon.java
index 2ceb0dd..6d453c9 100644
--- a/src/com/android/launcher3/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/ItemInfoWithIcon.java
@@ -16,7 +16,7 @@
package com.android.launcher3;
-import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON;
+import static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
import android.graphics.Bitmap;
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index df1c693..68abd68 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -38,7 +38,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.LauncherIcons;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.AddWorkspaceItemsTask;
import com.android.launcher3.model.BaseModelUpdateTask;
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index cf497fd..d47dcee 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -31,8 +31,8 @@
import com.android.launcher3.compat.AppWidgetManagerCompat;
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.LauncherIcons;
+import com.android.launcher3.icons.ShadowGenerator;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.ComponentKey;
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 0f13550..69b4bdb 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -22,7 +22,6 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnFocusChangeListener;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;
@@ -252,7 +251,7 @@
R.layout.all_apps_icon, parent, false);
icon.setOnClickListener(ItemClickHandler.INSTANCE);
icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS);
- icon.setLongPressTimeout(ViewConfiguration.getLongPressTimeout());
+ icon.setLongPressTimeoutFactor(1f);
icon.setOnFocusChangeListener(mIconFocusListener);
// Ensure the all apps icon height matches the workspace icons in portrait mode.
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index ab6635e..15cc2ca 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -19,7 +19,7 @@
import static android.view.View.MeasureSpec.getSize;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-import static com.android.launcher3.graphics.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
+import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import android.content.Context;
import android.graphics.Rect;
diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java
index 8998b24..5d38aad 100644
--- a/src/com/android/launcher3/badge/BadgeRenderer.java
+++ b/src/com/android/launcher3/badge/BadgeRenderer.java
@@ -27,7 +27,7 @@
import android.graphics.Rect;
import android.util.Log;
-import com.android.launcher3.graphics.ShadowGenerator;
+import com.android.launcher3.icons.ShadowGenerator;
/**
* Contains parameters necessary to draw a badge for an icon (e.g. the size of the badge).
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
index 386b3b3..fb44660 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVO.java
@@ -33,7 +33,7 @@
import com.android.launcher3.LauncherModel;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.compat.ShortcutConfigActivityInfo.ShortcutConfigActivityInfoVO;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.PackageUserKey;
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 6ac56eb..6d1efd5 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -56,7 +56,7 @@
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 8377adf..ce83a17 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -16,8 +16,6 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON;
-
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
@@ -37,6 +35,7 @@
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -66,7 +65,7 @@
* Returns a FastBitmapDrawable with the icon.
*/
public FastBitmapDrawable newIcon(Context context, ItemInfoWithIcon info) {
- FastBitmapDrawable drawable = info.iconBitmap == LOW_RES_ICON
+ FastBitmapDrawable drawable = info.usingLowResIcon()
? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context)
: new FastBitmapDrawable(info);
drawable.setIsDisabled(info.isDisabled());
@@ -74,7 +73,7 @@
}
public FastBitmapDrawable newIcon(Context context, BitmapInfo info, ActivityInfo target) {
- return info.icon == LOW_RES_ICON
+ return info.isLowRes()
? new PlaceHolderIconDrawable(info, getPreloadProgressPath(), context)
: new FastBitmapDrawable(info);
}
diff --git a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
index 18efd47..5f2fb59 100644
--- a/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PlaceHolderIconDrawable.java
@@ -24,6 +24,7 @@
import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.R;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.util.Themes;
/**
diff --git a/src/com/android/launcher3/icons/BaseIconCache.java b/src/com/android/launcher3/icons/BaseIconCache.java
new file mode 100644
index 0000000..f7e2be1
--- /dev/null
+++ b/src/com/android/launcher3/icons/BaseIconCache.java
@@ -0,0 +1,529 @@
+/*
+ * 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 static com.android.launcher3.icons.BitmapInfo.LOW_RES_ICON;
+
+import android.content.ComponentName;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+import android.os.Build.VERSION;
+import android.os.Handler;
+import android.os.Process;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.IconProvider;
+import com.android.launcher3.ItemInfoWithIcon;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.MainThreadExecutor;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.graphics.BitmapRenderer;
+import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.util.ComponentKey;
+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 java.util.HashMap;
+import java.util.HashSet;
+
+import androidx.annotation.NonNull;
+import androidx.core.graphics.ColorUtils;
+
+public class BaseIconCache {
+
+ private static final String TAG = "BaseIconCache";
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_IGNORE_CACHE = false;
+
+ private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
+
+ // Empty class name is used for storing package default entry.
+ public static final String EMPTY_CLASS_NAME = ".";
+
+ public static class CacheEntry extends BitmapInfo {
+ public CharSequence title = "";
+ public CharSequence contentDescription = "";
+ }
+
+ private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>();
+
+ 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;
+ final int mIconDpi;
+
+ final IconDB mIconDb;
+ final Handler mWorkerHandler;
+
+ private final BitmapFactory.Options mDecodeOptions;
+
+ public BaseIconCache(Context context, int iconDpi, int iconPixelSize) {
+ mContext = context;
+ mPackageManager = context.getPackageManager();
+ mUserManager = UserManagerCompat.getInstance(mContext);
+ mLauncherApps = LauncherAppsCompat.getInstance(mContext);
+ mInstantAppResolver = InstantAppResolver.newInstance(mContext);
+ mIconDpi = iconDpi;
+ mIconDb = new IconDB(context, iconPixelSize);
+
+ mIconProvider = IconProvider.newInstance(context);
+ mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
+
+ if (BitmapRenderer.USE_HARDWARE_BITMAP) {
+ mDecodeOptions = new BitmapFactory.Options();
+ mDecodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
+ } else {
+ mDecodeOptions = null;
+ }
+ }
+
+ private Drawable getFullResDefaultActivityIcon() {
+ return Resources.getSystem().getDrawableForDensity(Utilities.ATLEAST_OREO
+ ? android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon,
+ mIconDpi);
+ }
+
+ private Drawable getFullResIcon(Resources resources, int iconId) {
+ if (resources != null && iconId != 0) {
+ try {
+ return resources.getDrawableForDensity(iconId, mIconDpi);
+ } catch (Resources.NotFoundException e) { }
+ }
+ return getFullResDefaultActivityIcon();
+ }
+
+ public Drawable getFullResIcon(String packageName, int iconId) {
+ try {
+ return getFullResIcon(mPackageManager.getResourcesForApplication(packageName), iconId);
+ } catch (PackageManager.NameNotFoundException e) { }
+ return getFullResDefaultActivityIcon();
+ }
+
+ public Drawable getFullResIcon(ActivityInfo info) {
+ try {
+ return getFullResIcon(mPackageManager.getResourcesForApplication(info.applicationInfo),
+ info.getIconResource());
+ } catch (PackageManager.NameNotFoundException e) { }
+ return getFullResDefaultActivityIcon();
+ }
+
+ public Drawable getFullResIcon(LauncherActivityInfo info) {
+ return getFullResIcon(info, true);
+ }
+
+ public Drawable getFullResIcon(LauncherActivityInfo info, boolean flattenDrawable) {
+ return mIconProvider.getIcon(info, mIconDpi, flattenDrawable);
+ }
+
+ protected BitmapInfo makeDefaultIcon(UserHandle user) {
+ try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
+ return li.createBadgedIconBitmap(
+ getFullResDefaultActivityIcon(), user, VERSION.SDK_INT);
+ }
+ }
+
+ /**
+ * Remove any records for the supplied ComponentName.
+ */
+ public synchronized void remove(ComponentName componentName, UserHandle user) {
+ mCache.remove(new ComponentKey(componentName, user));
+ }
+
+ /**
+ * Remove any records for the supplied package name from memory.
+ */
+ private void removeFromMemCacheLocked(String packageName, UserHandle user) {
+ HashSet<ComponentKey> forDeletion = new HashSet<>();
+ for (ComponentKey key: mCache.keySet()) {
+ if (key.componentName.getPackageName().equals(packageName)
+ && key.user.equals(user)) {
+ forDeletion.add(key);
+ }
+ }
+ for (ComponentKey condemned: forDeletion) {
+ mCache.remove(condemned);
+ }
+ }
+
+ /**
+ * Removes the entries related to the given package in memory and persistent DB.
+ */
+ public synchronized void removeIconsForPkg(String packageName, UserHandle user) {
+ removeFromMemCacheLocked(packageName, user);
+ long userSerial = mUserManager.getSerialNumberForUser(user);
+ mIconDb.delete(
+ IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
+ new String[]{packageName + "/%", Long.toString(userSerial)});
+ }
+
+ public IconCacheUpdateHandler getUpdateHandler() {
+ mIconProvider.updateSystemStateString(mContext);
+ return new IconCacheUpdateHandler(this);
+ }
+
+ /**
+ * Adds an entry into the DB and the in-memory cache.
+ * @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
+ */
+ synchronized <T> void addIconToDBAndMemCache(T object, CachingLogic<T> cachingLogic,
+ PackageInfo info, long userSerial, boolean replaceExisting) {
+ UserHandle user = cachingLogic.getUser(object);
+ ComponentName componentName = cachingLogic.getComponent(object);
+
+ final ComponentKey key = new ComponentKey(componentName, user);
+ CacheEntry entry = null;
+ if (!replaceExisting) {
+ entry = mCache.get(key);
+ // We can't reuse the entry if the high-res icon is not present.
+ if (entry == null || entry.icon == null || entry.isLowRes()) {
+ entry = null;
+ }
+ }
+ if (entry == null) {
+ entry = new CacheEntry();
+ cachingLogic.loadIcon(mContext, this, object, entry);
+ }
+ entry.title = cachingLogic.getLabel(object);
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ mCache.put(key, entry);
+
+ ContentValues values = newContentValues(entry.icon, entry.color,
+ entry.title.toString(), componentName.getPackageName());
+ addIconToDB(values, componentName, info, userSerial);
+ }
+
+ /**
+ * Updates {@param values} to contain versioning information and adds it to the DB.
+ * @param values {@link ContentValues} containing icon & title
+ */
+ private void addIconToDB(ContentValues values, ComponentName key,
+ PackageInfo info, long userSerial) {
+ values.put(IconDB.COLUMN_COMPONENT, key.flattenToString());
+ values.put(IconDB.COLUMN_USER, userSerial);
+ values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime);
+ values.put(IconDB.COLUMN_VERSION, info.versionCode);
+ mIconDb.insertOrReplace(values);
+ }
+
+ /**
+ * Fill in {@param infoInOut} with the corresponding icon and label.
+ */
+ public synchronized void getTitleAndIconForApp(
+ PackageItemInfo infoInOut, boolean useLowResIcon) {
+ CacheEntry entry = getEntryForPackageLocked(
+ infoInOut.packageName, infoInOut.user, useLowResIcon);
+ applyCacheEntry(entry, infoInOut);
+ }
+
+ protected void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
+ info.title = Utilities.trim(entry.title);
+ info.contentDescription = entry.contentDescription;
+ ((entry.icon == null) ? getDefaultIcon(info.user) : entry).applyTo(info);
+ }
+
+ public synchronized BitmapInfo getDefaultIcon(UserHandle user) {
+ if (!mDefaultIcons.containsKey(user)) {
+ mDefaultIcons.put(user, makeDefaultIcon(user));
+ }
+ return mDefaultIcons.get(user);
+ }
+
+ public boolean isDefaultIcon(Bitmap icon, UserHandle user) {
+ return getDefaultIcon(user).icon == icon;
+ }
+
+ /**
+ * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
+ * This method is not thread safe, it must be called from a synchronized method.
+ */
+ protected <T> CacheEntry cacheLocked(
+ @NonNull ComponentName componentName,
+ @NonNull Provider<T> infoProvider,
+ @NonNull CachingLogic<T> cachingLogic,
+ UserHandle user, boolean usePackageIcon, boolean useLowResIcon) {
+ Preconditions.assertWorkerThread();
+ ComponentKey cacheKey = new ComponentKey(componentName, user);
+ CacheEntry entry = mCache.get(cacheKey);
+ if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
+ entry = new CacheEntry();
+ mCache.put(cacheKey, entry);
+
+ // Check the DB first.
+ T object = null;
+ boolean providerFetchedOnce = false;
+
+ if (!getEntryFromDB(cacheKey, entry, useLowResIcon) || DEBUG_IGNORE_CACHE) {
+ object = infoProvider.get();
+ providerFetchedOnce = true;
+
+ if (object != null) {
+ cachingLogic.loadIcon(mContext, this, object, entry);
+ } else {
+ if (usePackageIcon) {
+ CacheEntry packageEntry = getEntryForPackageLocked(
+ componentName.getPackageName(), user, false);
+ if (packageEntry != null) {
+ if (DEBUG) Log.d(TAG, "using package default icon for " +
+ componentName.toShortString());
+ packageEntry.applyTo(entry);
+ entry.title = packageEntry.title;
+ entry.contentDescription = packageEntry.contentDescription;
+ }
+ }
+ if (entry.icon == null) {
+ if (DEBUG) Log.d(TAG, "using default icon for " +
+ componentName.toShortString());
+ getDefaultIcon(user).applyTo(entry);
+ }
+ }
+ }
+
+ if (TextUtils.isEmpty(entry.title)) {
+ if (object == null && !providerFetchedOnce) {
+ object = infoProvider.get();
+ providerFetchedOnce = true;
+ }
+ if (object != null) {
+ entry.title = cachingLogic.getLabel(object);
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ }
+ }
+ }
+ return entry;
+ }
+
+ public synchronized void clear() {
+ Preconditions.assertWorkerThread();
+ mIconDb.clear();
+ }
+
+ /**
+ * Adds a default package entry in the cache. This entry is not persisted and will be removed
+ * when the cache is flushed.
+ */
+ public synchronized void cachePackageInstallInfo(String packageName, UserHandle user,
+ Bitmap icon, CharSequence title) {
+ removeFromMemCacheLocked(packageName, user);
+
+ ComponentKey cacheKey = getPackageKey(packageName, user);
+ CacheEntry entry = mCache.get(cacheKey);
+
+ // For icon caching, do not go through DB. Just update the in-memory entry.
+ if (entry == null) {
+ entry = new CacheEntry();
+ }
+ if (!TextUtils.isEmpty(title)) {
+ entry.title = title;
+ }
+ if (icon != null) {
+ LauncherIcons li = LauncherIcons.obtain(mContext);
+ li.createIconBitmap(icon).applyTo(entry);
+ li.recycle();
+ }
+ if (!TextUtils.isEmpty(title) && entry.icon != null) {
+ mCache.put(cacheKey, entry);
+ }
+ }
+
+ private static ComponentKey getPackageKey(String packageName, UserHandle user) {
+ ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
+ return new ComponentKey(cn, user);
+ }
+
+ /**
+ * Gets an entry for the package, which can be used as a fallback entry for various components.
+ * This method is not thread safe, it must be called from a synchronized method.
+ */
+ private CacheEntry getEntryForPackageLocked(String packageName, UserHandle user,
+ boolean useLowResIcon) {
+ Preconditions.assertWorkerThread();
+ ComponentKey cacheKey = getPackageKey(packageName, user);
+ CacheEntry entry = mCache.get(cacheKey);
+
+ if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
+ entry = new CacheEntry();
+ boolean entryUpdated = true;
+
+ // Check the DB first.
+ if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
+ try {
+ int flags = Process.myUserHandle().equals(user) ? 0 :
+ PackageManager.GET_UNINSTALLED_PACKAGES;
+ PackageInfo info = mPackageManager.getPackageInfo(packageName, flags);
+ ApplicationInfo appInfo = info.applicationInfo;
+ if (appInfo == null) {
+ throw new NameNotFoundException("ApplicationInfo is null");
+ }
+
+ LauncherIcons li = LauncherIcons.obtain(mContext);
+ // Load the full res icon for the application, but if useLowResIcon is set, then
+ // only keep the low resolution icon instead of the larger full-sized icon
+ BitmapInfo iconInfo = li.createBadgedIconBitmap(
+ appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion,
+ mInstantAppResolver.isInstantApp(appInfo));
+ li.recycle();
+
+ entry.title = appInfo.loadLabel(mPackageManager);
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
+ entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon;
+ entry.color = iconInfo.color;
+
+ // Add the icon in the DB here, since these do not get written during
+ // package updates.
+ ContentValues values = newContentValues(iconInfo.icon, entry.color,
+ entry.title.toString(), packageName);
+ addIconToDB(values, cacheKey.componentName, info,
+ mUserManager.getSerialNumberForUser(user));
+
+ } catch (NameNotFoundException e) {
+ if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
+ entryUpdated = false;
+ }
+ }
+
+ // Only add a filled-out entry to the cache
+ if (entryUpdated) {
+ mCache.put(cacheKey, entry);
+ }
+ }
+ return entry;
+ }
+
+ private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
+ Cursor c = null;
+ try {
+ c = mIconDb.query(
+ lowRes ? IconDB.COLUMNS_LOW_RES : IconDB.COLUMNS_HIGH_RES,
+ IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
+ new String[]{
+ cacheKey.componentName.flattenToString(),
+ Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
+ if (c.moveToNext()) {
+ // Set the alpha to be 255, so that we never have a wrong color
+ entry.color = ColorUtils.setAlphaComponent(c.getInt(0), 255);
+ entry.title = c.getString(1);
+ if (entry.title == null) {
+ entry.title = "";
+ entry.contentDescription = "";
+ } else {
+ entry.contentDescription = mUserManager.getBadgedLabelForUser(
+ entry.title, cacheKey.user);
+ }
+
+ if (lowRes) {
+ entry.icon = LOW_RES_ICON;
+ } else {
+ byte[] data = c.getBlob(2);
+ try {
+ entry.icon = BitmapFactory.decodeByteArray(data, 0, data.length,
+ mDecodeOptions);
+ } catch (Exception e) { }
+ }
+ return true;
+ }
+ } catch (SQLiteException e) {
+ Log.d(TAG, "Error reading icon cache", e);
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+ return false;
+ }
+
+ static final class IconDB extends SQLiteCacheHelper {
+ private final static int RELEASE_VERSION = 25;
+
+ 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 };
+ public final static String[] COLUMNS_LOW_RES = new String[] {
+ IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL };
+
+ public IconDB(Context context, int iconPixelSize) {
+ super(context, LauncherFiles.APP_ICONS_DB,
+ (RELEASE_VERSION << 16) + iconPixelSize,
+ TABLE_NAME);
+ }
+
+ @Override
+ protected void onCreateTable(SQLiteDatabase db) {
+ db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
+ COLUMN_COMPONENT + " TEXT NOT NULL, " +
+ COLUMN_USER + " INTEGER NOT NULL, " +
+ COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_ICON + " BLOB, " +
+ COLUMN_ICON_COLOR + " INTEGER NOT NULL DEFAULT 0, " +
+ COLUMN_LABEL + " TEXT, " +
+ COLUMN_SYSTEM_STATE + " TEXT, " +
+ "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " +
+ ");");
+ }
+ }
+
+ private ContentValues newContentValues(Bitmap icon, int iconColor, String label,
+ String packageName) {
+ ContentValues values = new ContentValues();
+ values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon));
+ values.put(IconDB.COLUMN_ICON_COLOR, iconColor);
+
+ values.put(IconDB.COLUMN_LABEL, label);
+ values.put(IconDB.COLUMN_SYSTEM_STATE, mIconProvider.getIconSystemState(packageName));
+
+ return values;
+ }
+}
diff --git a/src/com/android/launcher3/graphics/BitmapInfo.java b/src/com/android/launcher3/icons/BitmapInfo.java
similarity index 92%
rename from src/com/android/launcher3/graphics/BitmapInfo.java
rename to src/com/android/launcher3/icons/BitmapInfo.java
index 69c0684..ebe0511 100644
--- a/src/com/android/launcher3/graphics/BitmapInfo.java
+++ b/src/com/android/launcher3/icons/BitmapInfo.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -37,6 +37,10 @@
info.color = color;
}
+ public final boolean isLowRes() {
+ return LOW_RES_ICON == icon;
+ }
+
public static BitmapInfo fromBitmap(Bitmap bitmap) {
return fromBitmap(bitmap, null);
}
diff --git a/src/com/android/launcher3/icons/CachingLogic.java b/src/com/android/launcher3/icons/CachingLogic.java
new file mode 100644
index 0000000..13fdc6a
--- /dev/null
+++ b/src/com/android/launcher3/icons/CachingLogic.java
@@ -0,0 +1,60 @@
+/*
+ * 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.Context;
+import android.content.pm.LauncherActivityInfo;
+import android.os.UserHandle;
+
+public interface CachingLogic<T> {
+
+ ComponentName getComponent(T object);
+
+ UserHandle getUser(T object);
+
+ CharSequence getLabel(T object);
+
+ void loadIcon(Context context, BaseIconCache cache, T object, BitmapInfo target);
+
+ CachingLogic<LauncherActivityInfo> LAUNCHER_ACTIVITY_INFO =
+ new CachingLogic<LauncherActivityInfo>() {
+
+ @Override
+ public ComponentName getComponent(LauncherActivityInfo object) {
+ return object.getComponentName();
+ }
+
+ @Override
+ public UserHandle getUser(LauncherActivityInfo object) {
+ return object.getUser();
+ }
+
+ @Override
+ public CharSequence getLabel(LauncherActivityInfo object) {
+ return object.getLabel();
+ }
+
+ @Override
+ public void loadIcon(Context context, BaseIconCache cache, LauncherActivityInfo object,
+ BitmapInfo target) {
+ LauncherIcons li = LauncherIcons.obtain(context);
+ li.createBadgedIconBitmap(cache.getFullResIcon(object), object.getUser(),
+ object.getApplicationInfo().targetSdkVersion).applyTo(target);
+ li.recycle();
+ }
+ };
+}
diff --git a/src/com/android/launcher3/graphics/ColorExtractor.java b/src/com/android/launcher3/icons/ColorExtractor.java
similarity index 98%
rename from src/com/android/launcher3/graphics/ColorExtractor.java
rename to src/com/android/launcher3/icons/ColorExtractor.java
index da5da9c..87bda82 100644
--- a/src/com/android/launcher3/graphics/ColorExtractor.java
+++ b/src/com/android/launcher3/icons/ColorExtractor.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.graphics.Bitmap;
import android.graphics.Color;
diff --git a/src/com/android/launcher3/graphics/FixedScaleDrawable.java b/src/com/android/launcher3/icons/FixedScaleDrawable.java
similarity index 97%
rename from src/com/android/launcher3/graphics/FixedScaleDrawable.java
rename to src/com/android/launcher3/icons/FixedScaleDrawable.java
index 0f0e424..e594f47 100644
--- a/src/com/android/launcher3/graphics/FixedScaleDrawable.java
+++ b/src/com/android/launcher3/icons/FixedScaleDrawable.java
@@ -1,4 +1,4 @@
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.annotation.TargetApi;
import android.content.res.Resources;
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 2035d0e..eae6f01 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -16,209 +16,42 @@
package com.android.launcher3.icons;
-import static com.android.launcher3.graphics.BitmapInfo.LOW_RES_ICON;
+import static com.android.launcher3.icons.CachingLogic.LAUNCHER_ACTIVITY_INFO;
-import android.content.ComponentName;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.drawable.Drawable;
-import android.os.Build.VERSION;
import android.os.Handler;
import android.os.Process;
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;
-import com.android.launcher3.graphics.BitmapRenderer;
-import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
-import com.android.launcher3.util.ComponentKey;
-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 java.util.HashMap;
-import java.util.HashSet;
import androidx.annotation.NonNull;
-import androidx.core.graphics.ColorUtils;
/**
* Cache of application icons. Icons can be made from any thread.
*/
-public class IconCache {
+public class IconCache extends BaseIconCache {
private static final String TAG = "Launcher.IconCache";
- private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
-
- // Empty class name is used for storing package default entry.
- public static final String EMPTY_CLASS_NAME = ".";
-
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_IGNORE_CACHE = false;
-
- public static class CacheEntry extends BitmapInfo {
- public CharSequence title = "";
- public CharSequence contentDescription = "";
-
- public boolean isLowRes() {
- return LOW_RES_ICON == icon;
- }
- }
-
- private final HashMap<UserHandle, BitmapInfo> mDefaultIcons = new HashMap<>();
-
- 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;
-
- final IconDB mIconDb;
- final Handler mWorkerHandler;
-
- private final BitmapFactory.Options mDecodeOptions;
-
private int mPendingIconRequestCount = 0;
public IconCache(Context context, InvariantDeviceProfile inv) {
- mContext = context;
- mPackageManager = context.getPackageManager();
- mUserManager = UserManagerCompat.getInstance(mContext);
- mLauncherApps = LauncherAppsCompat.getInstance(mContext);
- mInstantAppResolver = InstantAppResolver.newInstance(mContext);
- mIconDpi = inv.fillResIconDpi;
- mIconDb = new IconDB(context, inv.iconBitmapSize);
-
- mIconProvider = IconProvider.newInstance(context);
- mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
-
- if (BitmapRenderer.USE_HARDWARE_BITMAP) {
- mDecodeOptions = new BitmapFactory.Options();
- mDecodeOptions.inPreferredConfig = Bitmap.Config.HARDWARE;
- } else {
- mDecodeOptions = null;
- }
- }
-
- private Drawable getFullResDefaultActivityIcon() {
- return getFullResIcon(Resources.getSystem(), Utilities.ATLEAST_OREO ?
- android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon);
- }
-
- private Drawable getFullResIcon(Resources resources, int iconId) {
- Drawable d;
- try {
- d = resources.getDrawableForDensity(iconId, mIconDpi);
- } catch (Resources.NotFoundException e) {
- d = null;
- }
-
- return (d != null) ? d : getFullResDefaultActivityIcon();
- }
-
- public Drawable getFullResIcon(String packageName, int iconId) {
- Resources resources;
- try {
- resources = mPackageManager.getResourcesForApplication(packageName);
- } catch (PackageManager.NameNotFoundException e) {
- resources = null;
- }
- if (resources != null) {
- if (iconId != 0) {
- return getFullResIcon(resources, iconId);
- }
- }
- return getFullResDefaultActivityIcon();
- }
-
- public Drawable getFullResIcon(ActivityInfo info) {
- Resources resources;
- try {
- resources = mPackageManager.getResourcesForApplication(
- info.applicationInfo);
- } catch (PackageManager.NameNotFoundException e) {
- resources = null;
- }
- if (resources != null) {
- int iconId = info.getIconResource();
- if (iconId != 0) {
- return getFullResIcon(resources, iconId);
- }
- }
-
- return getFullResDefaultActivityIcon();
- }
-
- public Drawable getFullResIcon(LauncherActivityInfo info) {
- return getFullResIcon(info, true);
- }
-
- public Drawable getFullResIcon(LauncherActivityInfo info, boolean flattenDrawable) {
- return mIconProvider.getIcon(info, mIconDpi, flattenDrawable);
- }
-
- protected BitmapInfo makeDefaultIcon(UserHandle user) {
- try (LauncherIcons li = LauncherIcons.obtain(mContext)) {
- return li.createBadgedIconBitmap(
- getFullResDefaultActivityIcon(), user, VERSION.SDK_INT);
- }
- }
-
- /**
- * Remove any records for the supplied ComponentName.
- */
- public synchronized void remove(ComponentName componentName, UserHandle user) {
- mCache.remove(new ComponentKey(componentName, user));
- }
-
- /**
- * Remove any records for the supplied package name from memory.
- */
- private void removeFromMemCacheLocked(String packageName, UserHandle user) {
- HashSet<ComponentKey> forDeletion = new HashSet<>();
- for (ComponentKey key: mCache.keySet()) {
- if (key.componentName.getPackageName().equals(packageName)
- && key.user.equals(user)) {
- forDeletion.add(key);
- }
- }
- for (ComponentKey condemned: forDeletion) {
- mCache.remove(condemned);
- }
+ super(context, inv.fillResIconDpi, inv.iconBitmapSize);
}
/**
@@ -231,7 +64,8 @@
PackageManager.GET_UNINSTALLED_PACKAGES);
long userSerial = mUserManager.getSerialNumberForUser(user);
for (LauncherActivityInfo app : mLauncherApps.getActivityList(packageName, user)) {
- addIconToDBAndMemCache(app, info, userSerial, false /*replace existing*/);
+ addIconToDBAndMemCache(app, LAUNCHER_ACTIVITY_INFO, info, userSerial,
+ false /*replace existing*/);
}
} catch (NameNotFoundException e) {
Log.d(TAG, "Package not found", e);
@@ -239,69 +73,6 @@
}
/**
- * Removes the entries related to the given package in memory and persistent DB.
- */
- public synchronized void removeIconsForPkg(String packageName, UserHandle user) {
- removeFromMemCacheLocked(packageName, user);
- long userSerial = mUserManager.getSerialNumberForUser(user);
- mIconDb.delete(
- IconDB.COLUMN_COMPONENT + " LIKE ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[]{packageName + "/%", Long.toString(userSerial)});
- }
-
- public IconCacheUpdateHandler getUpdateHandler() {
- mIconProvider.updateSystemStateString(mContext);
- return new IconCacheUpdateHandler(this);
- }
-
- /**
- * Adds an entry into the DB and the in-memory cache.
- * @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
- */
- synchronized void addIconToDBAndMemCache(LauncherActivityInfo app,
- PackageInfo info, long userSerial, boolean replaceExisting) {
- final ComponentKey key = new ComponentKey(app.getComponentName(), app.getUser());
- CacheEntry entry = null;
- if (!replaceExisting) {
- entry = mCache.get(key);
- // We can't reuse the entry if the high-res icon is not present.
- if (entry == null || entry.icon == null || entry.isLowRes()) {
- entry = null;
- }
- }
- if (entry == null) {
- entry = new CacheEntry();
- LauncherIcons li = LauncherIcons.obtain(mContext);
- li.createBadgedIconBitmap(getFullResIcon(app), app.getUser(),
- app.getApplicationInfo().targetSdkVersion).applyTo(entry);
- li.recycle();
- }
- entry.title = app.getLabel();
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, app.getUser());
- mCache.put(key, entry);
-
- ContentValues values = newContentValues(entry.icon, entry.color,
- entry.title.toString(), app.getApplicationInfo().packageName);
- addIconToDB(values, app.getComponentName(), info, userSerial);
- }
-
- /**
- * Updates {@param values} to contain versioning information and adds it to the DB.
- * @param values {@link ContentValues} containing icon & title
- */
- private void addIconToDB(ContentValues values, ComponentName key,
- PackageInfo info, long userSerial) {
- values.put(IconDB.COLUMN_COMPONENT, key.flattenToString());
- values.put(IconDB.COLUMN_USER, userSerial);
- values.put(IconDB.COLUMN_LAST_UPDATED, info.lastUpdateTime);
- values.put(IconDB.COLUMN_VERSION, info.versionCode);
- mIconDb.insertOrReplace(values);
- }
-
- /**
* Fetches high-res icon for the provided ItemInfo and updates the caller when done.
* @return a request ID that can be used to cancel the request.
*/
@@ -343,7 +114,7 @@
*/
public synchronized void updateTitleAndIcon(AppInfo application) {
CacheEntry entry = cacheLocked(application.componentName,
- Provider.<LauncherActivityInfo>of(null),
+ Provider.of(null), LAUNCHER_ACTIVITY_INFO,
application.user, false, application.usingLowResIcon());
if (entry.icon != null && !isDefaultIcon(entry.icon, application.user)) {
applyCacheEntry(entry, application);
@@ -385,238 +156,10 @@
@NonNull Provider<LauncherActivityInfo> activityInfoProvider,
boolean usePkgIcon, boolean useLowResIcon) {
CacheEntry entry = cacheLocked(infoInOut.getTargetComponent(), activityInfoProvider,
- infoInOut.user, usePkgIcon, useLowResIcon);
+ LAUNCHER_ACTIVITY_INFO, infoInOut.user, usePkgIcon, useLowResIcon);
applyCacheEntry(entry, infoInOut);
}
- /**
- * Fill in {@param infoInOut} with the corresponding icon and label.
- */
- public synchronized void getTitleAndIconForApp(
- PackageItemInfo infoInOut, boolean useLowResIcon) {
- CacheEntry entry = getEntryForPackageLocked(
- infoInOut.packageName, infoInOut.user, useLowResIcon);
- applyCacheEntry(entry, infoInOut);
- }
-
- private void applyCacheEntry(CacheEntry entry, ItemInfoWithIcon info) {
- info.title = Utilities.trim(entry.title);
- info.contentDescription = entry.contentDescription;
- ((entry.icon == null) ? getDefaultIcon(info.user) : entry).applyTo(info);
- }
-
- public synchronized BitmapInfo getDefaultIcon(UserHandle user) {
- if (!mDefaultIcons.containsKey(user)) {
- mDefaultIcons.put(user, makeDefaultIcon(user));
- }
- return mDefaultIcons.get(user);
- }
-
- public boolean isDefaultIcon(Bitmap icon, UserHandle user) {
- return getDefaultIcon(user).icon == icon;
- }
-
- /**
- * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
- * This method is not thread safe, it must be called from a synchronized method.
- */
- protected CacheEntry cacheLocked(
- @NonNull ComponentName componentName,
- @NonNull Provider<LauncherActivityInfo> infoProvider,
- UserHandle user, boolean usePackageIcon, boolean useLowResIcon) {
- Preconditions.assertWorkerThread();
- ComponentKey cacheKey = new ComponentKey(componentName, user);
- CacheEntry entry = mCache.get(cacheKey);
- if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
- entry = new CacheEntry();
- mCache.put(cacheKey, entry);
-
- // Check the DB first.
- LauncherActivityInfo info = null;
- boolean providerFetchedOnce = false;
-
- if (!getEntryFromDB(cacheKey, entry, useLowResIcon) || DEBUG_IGNORE_CACHE) {
- info = infoProvider.get();
- providerFetchedOnce = true;
-
- if (info != null) {
- LauncherIcons li = LauncherIcons.obtain(mContext);
- li.createBadgedIconBitmap(getFullResIcon(info), info.getUser(),
- info.getApplicationInfo().targetSdkVersion).applyTo(entry);
- li.recycle();
- } else {
- if (usePackageIcon) {
- CacheEntry packageEntry = getEntryForPackageLocked(
- componentName.getPackageName(), user, false);
- if (packageEntry != null) {
- if (DEBUG) Log.d(TAG, "using package default icon for " +
- componentName.toShortString());
- packageEntry.applyTo(entry);
- entry.title = packageEntry.title;
- entry.contentDescription = packageEntry.contentDescription;
- }
- }
- if (entry.icon == null) {
- if (DEBUG) Log.d(TAG, "using default icon for " +
- componentName.toShortString());
- getDefaultIcon(user).applyTo(entry);
- }
- }
- }
-
- if (TextUtils.isEmpty(entry.title)) {
- if (info == null && !providerFetchedOnce) {
- info = infoProvider.get();
- providerFetchedOnce = true;
- }
- if (info != null) {
- entry.title = info.getLabel();
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
- }
- }
- }
- return entry;
- }
-
- public synchronized void clear() {
- Preconditions.assertWorkerThread();
- mIconDb.clear();
- }
-
- /**
- * Adds a default package entry in the cache. This entry is not persisted and will be removed
- * when the cache is flushed.
- */
- public synchronized void cachePackageInstallInfo(String packageName, UserHandle user,
- Bitmap icon, CharSequence title) {
- removeFromMemCacheLocked(packageName, user);
-
- ComponentKey cacheKey = getPackageKey(packageName, user);
- CacheEntry entry = mCache.get(cacheKey);
-
- // For icon caching, do not go through DB. Just update the in-memory entry.
- if (entry == null) {
- entry = new CacheEntry();
- }
- if (!TextUtils.isEmpty(title)) {
- entry.title = title;
- }
- if (icon != null) {
- LauncherIcons li = LauncherIcons.obtain(mContext);
- li.createIconBitmap(icon).applyTo(entry);
- li.recycle();
- }
- if (!TextUtils.isEmpty(title) && entry.icon != null) {
- mCache.put(cacheKey, entry);
- }
- }
-
- private static ComponentKey getPackageKey(String packageName, UserHandle user) {
- ComponentName cn = new ComponentName(packageName, packageName + EMPTY_CLASS_NAME);
- return new ComponentKey(cn, user);
- }
-
- /**
- * Gets an entry for the package, which can be used as a fallback entry for various components.
- * This method is not thread safe, it must be called from a synchronized method.
- */
- private CacheEntry getEntryForPackageLocked(String packageName, UserHandle user,
- boolean useLowResIcon) {
- Preconditions.assertWorkerThread();
- ComponentKey cacheKey = getPackageKey(packageName, user);
- CacheEntry entry = mCache.get(cacheKey);
-
- if (entry == null || (entry.isLowRes() && !useLowResIcon)) {
- entry = new CacheEntry();
- boolean entryUpdated = true;
-
- // Check the DB first.
- if (!getEntryFromDB(cacheKey, entry, useLowResIcon)) {
- try {
- int flags = Process.myUserHandle().equals(user) ? 0 :
- PackageManager.GET_UNINSTALLED_PACKAGES;
- PackageInfo info = mPackageManager.getPackageInfo(packageName, flags);
- ApplicationInfo appInfo = info.applicationInfo;
- if (appInfo == null) {
- throw new NameNotFoundException("ApplicationInfo is null");
- }
-
- LauncherIcons li = LauncherIcons.obtain(mContext);
- // Load the full res icon for the application, but if useLowResIcon is set, then
- // only keep the low resolution icon instead of the larger full-sized icon
- BitmapInfo iconInfo = li.createBadgedIconBitmap(
- appInfo.loadIcon(mPackageManager), user, appInfo.targetSdkVersion,
- mInstantAppResolver.isInstantApp(appInfo));
- li.recycle();
-
- entry.title = appInfo.loadLabel(mPackageManager);
- entry.contentDescription = mUserManager.getBadgedLabelForUser(entry.title, user);
- entry.icon = useLowResIcon ? LOW_RES_ICON : iconInfo.icon;
- entry.color = iconInfo.color;
-
- // Add the icon in the DB here, since these do not get written during
- // package updates.
- ContentValues values = newContentValues(iconInfo.icon, entry.color,
- entry.title.toString(), packageName);
- addIconToDB(values, cacheKey.componentName, info,
- mUserManager.getSerialNumberForUser(user));
-
- } catch (NameNotFoundException e) {
- if (DEBUG) Log.d(TAG, "Application not installed " + packageName);
- entryUpdated = false;
- }
- }
-
- // Only add a filled-out entry to the cache
- if (entryUpdated) {
- mCache.put(cacheKey, entry);
- }
- }
- return entry;
- }
-
- private boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
- Cursor c = null;
- try {
- c = mIconDb.query(
- lowRes ? IconDB.COLUMNS_LOW_RES : IconDB.COLUMNS_HIGH_RES,
- IconDB.COLUMN_COMPONENT + " = ? AND " + IconDB.COLUMN_USER + " = ?",
- new String[]{
- cacheKey.componentName.flattenToString(),
- Long.toString(mUserManager.getSerialNumberForUser(cacheKey.user))});
- if (c.moveToNext()) {
- // Set the alpha to be 255, so that we never have a wrong color
- entry.color = ColorUtils.setAlphaComponent(c.getInt(0), 255);
- entry.title = c.getString(1);
- if (entry.title == null) {
- entry.title = "";
- entry.contentDescription = "";
- } else {
- entry.contentDescription = mUserManager.getBadgedLabelForUser(
- entry.title, cacheKey.user);
- }
-
- if (lowRes) {
- entry.icon = LOW_RES_ICON;
- } else {
- byte[] data = c.getBlob(2);
- try {
- entry.icon = BitmapFactory.decodeByteArray(data, 0, data.length,
- mDecodeOptions);
- } catch (Exception e) { }
- }
- return true;
- }
- } catch (SQLiteException e) {
- Log.d(TAG, "Error reading icon cache", e);
- } finally {
- if (c != null) {
- c.close();
- }
- }
- return false;
- }
-
public static abstract class IconLoadRequest implements Runnable {
private final Handler mHandler;
private final Runnable mEndRunnable;
@@ -641,59 +184,6 @@
}
}
- static final class IconDB extends SQLiteCacheHelper {
- private final static int RELEASE_VERSION = 25;
-
- 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 };
- public final static String[] COLUMNS_LOW_RES = new String[] {
- IconDB.COLUMN_ICON_COLOR, IconDB.COLUMN_LABEL };
-
- public IconDB(Context context, int iconPixelSize) {
- super(context, LauncherFiles.APP_ICONS_DB,
- (RELEASE_VERSION << 16) + iconPixelSize,
- TABLE_NAME);
- }
-
- @Override
- protected void onCreateTable(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + " (" +
- COLUMN_COMPONENT + " TEXT NOT NULL, " +
- COLUMN_USER + " INTEGER NOT NULL, " +
- COLUMN_LAST_UPDATED + " INTEGER NOT NULL DEFAULT 0, " +
- COLUMN_VERSION + " INTEGER NOT NULL DEFAULT 0, " +
- COLUMN_ICON + " BLOB, " +
- COLUMN_ICON_COLOR + " INTEGER NOT NULL DEFAULT 0, " +
- COLUMN_LABEL + " TEXT, " +
- COLUMN_SYSTEM_STATE + " TEXT, " +
- "PRIMARY KEY (" + COLUMN_COMPONENT + ", " + COLUMN_USER + ") " +
- ");");
- }
- }
-
- private ContentValues newContentValues(Bitmap icon, int iconColor, String label,
- String packageName) {
- ContentValues values = new ContentValues();
- values.put(IconDB.COLUMN_ICON, Utilities.flattenBitmap(icon));
- values.put(IconDB.COLUMN_ICON_COLOR, iconColor);
-
- values.put(IconDB.COLUMN_LABEL, label);
- values.put(IconDB.COLUMN_SYSTEM_STATE, mIconProvider.getIconSystemState(packageName));
-
- return values;
- }
-
/**
* Interface for receiving itemInfo with high-res icon.
*/
diff --git a/src/com/android/launcher3/icons/IconCacheUpdateHandler.java b/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
index 04e2901..64e3fbf 100644
--- a/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
+++ b/src/com/android/launcher3/icons/IconCacheUpdateHandler.java
@@ -17,7 +17,6 @@
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;
@@ -29,7 +28,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
-import com.android.launcher3.icons.IconCache.IconDB;
+import com.android.launcher3.icons.BaseIconCache.IconDB;
import java.util.Collections;
import java.util.HashMap;
@@ -48,10 +47,10 @@
private static final Object ICON_UPDATE_TOKEN = new Object();
private final HashMap<String, PackageInfo> mPkgInfoMap;
- private final IconCache mIconCache;
+ private final BaseIconCache mIconCache;
private final HashMap<UserHandle, Set<String>> mPackagesToIgnore = new HashMap<>();
- IconCacheUpdateHandler(IconCache cache) {
+ IconCacheUpdateHandler(BaseIconCache cache) {
mIconCache = cache;
mPkgInfoMap = new HashMap<>();
@@ -68,9 +67,8 @@
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);
+ mPkgInfoMap.put(info.packageName, info);
}
}
@@ -79,11 +77,11 @@
* the DB and are updated.
* @return The set of packages for which icons have updated.
*/
- public void updateIcons(List<LauncherActivityInfo> apps) {
+ public <T> void updateIcons(List<T> apps, CachingLogic<T> cachingLogic) {
if (apps.isEmpty()) {
return;
}
- UserHandle user = apps.get(0).getUser();
+ UserHandle user = cachingLogic.getUser(apps.get(0));
Set<String> ignorePackages = mPackagesToIgnore.get(user);
if (ignorePackages == null) {
@@ -91,13 +89,13 @@
}
long userSerial = mIconCache.mUserManager.getSerialNumberForUser(user);
- HashMap<ComponentName, LauncherActivityInfo> componentMap = new HashMap<>();
- for (LauncherActivityInfo app : apps) {
- componentMap.put(app.getComponentName(), app);
+ HashMap<ComponentName, T> componentMap = new HashMap<>();
+ for (T app : apps) {
+ componentMap.put(cachingLogic.getComponent(app), app);
}
HashSet<Integer> itemsToRemove = new HashSet<>();
- Stack<LauncherActivityInfo> appsToUpdate = new Stack<>();
+ Stack<T> appsToUpdate = new Stack<>();
try (Cursor c = mIconCache.mIconDb.query(
new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
@@ -130,7 +128,7 @@
long updateTime = c.getLong(indexLastUpdate);
int version = c.getInt(indexVersion);
- LauncherActivityInfo app = componentMap.remove(component);
+ T app = componentMap.remove(component);
if (version == info.versionCode && updateTime == info.lastUpdateTime &&
TextUtils.equals(c.getString(systemStateIndex),
mIconCache.mIconProvider.getIconSystemState(info.packageName))) {
@@ -154,9 +152,10 @@
// Insert remaining apps.
if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
- Stack<LauncherActivityInfo> appsToAdd = new Stack<>();
+ Stack<T> appsToAdd = new Stack<>();
appsToAdd.addAll(componentMap.values());
- new SerializedIconUpdateTask(userSerial, user, appsToAdd, appsToUpdate).scheduleNext();
+ new SerializedIconUpdateTask(userSerial, user, appsToAdd, appsToUpdate, cachingLogic)
+ .scheduleNext();
}
}
@@ -166,29 +165,31 @@
* 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 class SerializedIconUpdateTask<T> implements Runnable {
private final long mUserSerial;
private final UserHandle mUserHandle;
- private final Stack<LauncherActivityInfo> mAppsToAdd;
- private final Stack<LauncherActivityInfo> mAppsToUpdate;
+ private final Stack<T> mAppsToAdd;
+ private final Stack<T> mAppsToUpdate;
+ private final CachingLogic<T> mCachingLogic;
private final HashSet<String> mUpdatedPackages = new HashSet<>();
SerializedIconUpdateTask(long userSerial, UserHandle userHandle,
- Stack<LauncherActivityInfo> appsToAdd, Stack<LauncherActivityInfo> appsToUpdate) {
+ Stack<T> appsToAdd, Stack<T> appsToUpdate, CachingLogic<T> cachingLogic) {
mUserHandle = userHandle;
mUserSerial = userSerial;
mAppsToAdd = appsToAdd;
mAppsToUpdate = appsToUpdate;
+ mCachingLogic = cachingLogic;
}
@Override
public void run() {
if (!mAppsToUpdate.isEmpty()) {
- LauncherActivityInfo app = mAppsToUpdate.pop();
- String pkg = app.getComponentName().getPackageName();
+ T app = mAppsToUpdate.pop();
+ String pkg = mCachingLogic.getComponent(app).getPackageName();
PackageInfo info = mPkgInfoMap.get(pkg);
mIconCache.addIconToDBAndMemCache(
- app, info, mUserSerial, true /*replace existing*/);
+ app, mCachingLogic, info, mUserSerial, true /*replace existing*/);
mUpdatedPackages.add(pkg);
if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
@@ -200,13 +201,13 @@
// Let it run one more time.
scheduleNext();
} else if (!mAppsToAdd.isEmpty()) {
- LauncherActivityInfo app = mAppsToAdd.pop();
- PackageInfo info = mPkgInfoMap.get(app.getComponentName().getPackageName());
+ T app = mAppsToAdd.pop();
+ PackageInfo info = mPkgInfoMap.get(mCachingLogic.getComponent(app).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*/);
+ mIconCache.addIconToDBAndMemCache(app, mCachingLogic, info,
+ mUserSerial, false /*replace existing*/);
}
if (!mAppsToAdd.isEmpty()) {
diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/icons/IconNormalizer.java
similarity index 99%
rename from src/com/android/launcher3/graphics/IconNormalizer.java
rename to src/com/android/launcher3/icons/IconNormalizer.java
index df00815..7317782 100644
--- a/src/com/android/launcher3/graphics/IconNormalizer.java
+++ b/src/com/android/launcher3/icons/IconNormalizer.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
similarity index 98%
rename from src/com/android/launcher3/graphics/LauncherIcons.java
rename to src/com/android/launcher3/icons/LauncherIcons.java
index 7db67c9..b4cbf65 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import static android.graphics.Paint.DITHER_FLAG;
import static android.graphics.Paint.FILTER_BITMAP_FLAG;
-import static com.android.launcher3.graphics.ShadowGenerator.BLUR_FACTOR;
+import static com.android.launcher3.icons.ShadowGenerator.BLUR_FACTOR;
import android.content.ComponentName;
import android.content.Context;
@@ -44,7 +44,7 @@
import com.android.launcher3.AppInfo;
import com.android.launcher3.FastBitmapDrawable;
-import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.LauncherAppState;
diff --git a/src/com/android/launcher3/graphics/ShadowGenerator.java b/src/com/android/launcher3/icons/ShadowGenerator.java
similarity index 99%
rename from src/com/android/launcher3/graphics/ShadowGenerator.java
rename to src/com/android/launcher3/icons/ShadowGenerator.java
index d2d1699..57d463a 100644
--- a/src/com/android/launcher3/graphics/ShadowGenerator.java
+++ b/src/com/android/launcher3/icons/ShadowGenerator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.launcher3.graphics;
+package com.android.launcher3.icons;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 77e9721..87aef02 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -43,8 +43,8 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.graphics.BitmapInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.ContentWriter;
import com.android.launcher3.util.GridOccupancy;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 4ccb8d8..d6b7b0f 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SAFEMODE;
import static com.android.launcher3.ItemInfoWithIcon.FLAG_DISABLED_SUSPENDED;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
+import static com.android.launcher3.icons.CachingLogic.LAUNCHER_ACTIVITY_INFO;
import static com.android.launcher3.model.LoaderResults.filterCurrentWorkspaceItems;
import android.appwidget.AppWidgetProviderInfo;
@@ -60,7 +61,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.ImportDataTask;
import com.android.launcher3.shortcuts.DeepShortcutManager;
@@ -802,7 +803,7 @@
List<List<LauncherActivityInfo>> activityListPerUser) {
int userCount = activityListPerUser.size();
for (int i = 0; i < userCount; i++) {
- updateHandler.updateIcons(activityListPerUser.get(i));
+ updateHandler.updateIcons(activityListPerUser.get(i), LAUNCHER_ACTIVITY_INFO);
}
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 0af5311..c004e21 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -38,8 +38,8 @@
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.graphics.BitmapInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 59f3d1c..020bc41 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -23,7 +23,7 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 9521a9e..9f02d4f 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -26,7 +26,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 5c0e259..78627ec 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -179,7 +179,7 @@
@Override
- public boolean onDrag(float displacement, float velocity) {
+ public boolean onDrag(float displacement) {
setContentTranslation(canChildBeDismissed()
? displacement : OverScroll.dampedScroll(displacement, getWidth()));
mContentTranslateAnimator.cancel();
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 4500629..c14c00e 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -24,7 +24,7 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.ShortcutInfo;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.notification.NotificationInfo;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutManager;
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 7b09bcc..ce1cc89 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -256,7 +256,7 @@
}
@Override
- public boolean onDrag(float displacement, float velocity) {
+ public boolean onDrag(float displacement) {
float deltaProgress = mProgressMultiplier * (displacement - mDisplacementShift);
float progress = deltaProgress + mStartProgress;
updateProgress(progress);
diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java
index 6ffc0ef..a0a410e 100644
--- a/src/com/android/launcher3/touch/SwipeDetector.java
+++ b/src/com/android/launcher3/touch/SwipeDetector.java
@@ -21,6 +21,7 @@
import android.graphics.PointF;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import androidx.annotation.NonNull;
@@ -52,12 +53,6 @@
*/
public static final float RELEASE_VELOCITY_PX_MS = 1.0f;
- /**
- * The time constant used to calculate dampening in the low-pass filter of scroll velocity.
- * Cutoff frequency is set at 10 Hz.
- */
- public static final float SCROLL_VELOCITY_DAMPENING_RC = 1000f / (2f * (float) Math.PI * 10);
-
/* Scroll state, this is set to true during dragging and animation. */
private ScrollState mState = ScrollState.IDLE;
@@ -75,6 +70,8 @@
* Distance in pixels a touch can wander before we think the user is scrolling.
*/
abstract float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos);
+
+ abstract float getVelocity(VelocityTracker tracker);
}
public static final Direction VERTICAL = new Direction() {
@@ -88,6 +85,11 @@
float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos) {
return Math.abs(ev.getX(pointerIndex) - downPos.x);
}
+
+ @Override
+ float getVelocity(VelocityTracker tracker) {
+ return tracker.getYVelocity();
+ }
};
public static final Direction HORIZONTAL = new Direction() {
@@ -101,6 +103,11 @@
float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos) {
return Math.abs(ev.getY(pointerIndex) - downPos.y);
}
+
+ @Override
+ float getVelocity(VelocityTracker tracker) {
+ return tracker.getXVelocity();
+ }
};
//------------------- ScrollState transition diagram -----------------------------------
@@ -151,16 +158,16 @@
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
- private Direction mDir;
+ private final Direction mDir;
private final float mTouchSlop;
+ private final float mMaxVelocity;
/* Client of this gesture detector can register a callback. */
private final Listener mListener;
- private long mCurrentMillis;
+ private VelocityTracker mVelocityTracker;
- private float mVelocity;
private float mLastDisplacement;
private float mDisplacement;
@@ -170,24 +177,22 @@
public interface Listener {
void onDragStart(boolean start);
- boolean onDrag(float displacement, float velocity);
+ boolean onDrag(float displacement);
void onDragEnd(float velocity, boolean fling);
}
public SwipeDetector(@NonNull Context context, @NonNull Listener l, @NonNull Direction dir) {
- this(ViewConfiguration.get(context).getScaledTouchSlop(), l, dir);
+ this(ViewConfiguration.get(context), l, dir);
}
@VisibleForTesting
- protected SwipeDetector(float touchSlope, @NonNull Listener l, @NonNull Direction dir) {
- mTouchSlop = touchSlope;
+ protected SwipeDetector(@NonNull ViewConfiguration config, @NonNull Listener l,
+ @NonNull Direction dir) {
mListener = l;
mDir = dir;
- }
-
- public void updateDirection(Direction dir) {
- mDir = dir;
+ mTouchSlop = config.getScaledTouchSlop();
+ mMaxVelocity = config.getScaledMaximumFlingVelocity();
}
public void setDetectableScrollConditions(int scrollDirectionFlags, boolean ignoreSlop) {
@@ -215,14 +220,22 @@
}
public boolean onTouchEvent(MotionEvent ev) {
- switch (ev.getActionMasked()) {
+ int actionMasked = ev.getActionMasked();
+ if (actionMasked == MotionEvent.ACTION_DOWN && mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+
+ switch (actionMasked) {
case MotionEvent.ACTION_DOWN:
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
mLastDisplacement = 0;
mDisplacement = 0;
- mVelocity = 0;
if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) {
setState(ScrollState.DRAGGING);
@@ -247,8 +260,6 @@
break;
}
mDisplacement = mDir.getDisplacement(ev, pointerIndex, mDownPos);
- computeVelocity(mDir.getDisplacement(ev, pointerIndex, mLastPos),
- ev.getEventTime());
// handle state and listener calls.
if (mState != ScrollState.DRAGGING && shouldScrollStart(ev, pointerIndex)) {
@@ -265,6 +276,8 @@
if (mState == ScrollState.DRAGGING) {
setState(ScrollState.SETTLING);
}
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
break;
default:
break;
@@ -308,55 +321,24 @@
private boolean reportDragging() {
if (mDisplacement != mLastDisplacement) {
if (DBG) {
- Log.d(TAG, String.format("onDrag disp=%.1f, velocity=%.1f",
- mDisplacement, mVelocity));
+ Log.d(TAG, String.format("onDrag disp=%.1f", mDisplacement));
}
mLastDisplacement = mDisplacement;
- return mListener.onDrag(mDisplacement - mSubtractDisplacement, mVelocity);
+ return mListener.onDrag(mDisplacement - mSubtractDisplacement);
}
return true;
}
private void reportDragEnd() {
+ mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
+ float velocity = mDir.getVelocity(mVelocityTracker) / 1000;
if (DBG) {
Log.d(TAG, String.format("onScrollEnd disp=%.1f, velocity=%.1f",
- mDisplacement, mVelocity));
+ mDisplacement, velocity));
}
- mListener.onDragEnd(mVelocity, Math.abs(mVelocity) > RELEASE_VELOCITY_PX_MS);
- }
-
- /**
- * Computes the damped velocity.
- */
- public float computeVelocity(float delta, long currentMillis) {
- long previousMillis = mCurrentMillis;
- mCurrentMillis = currentMillis;
-
- float deltaTimeMillis = mCurrentMillis - previousMillis;
- float velocity = (deltaTimeMillis > 0) ? (delta / deltaTimeMillis) : 0;
- if (Math.abs(mVelocity) < 0.001f) {
- mVelocity = velocity;
- } else {
- float alpha = computeDampeningFactor(deltaTimeMillis);
- mVelocity = interpolate(mVelocity, velocity, alpha);
- }
- return mVelocity;
- }
-
- /**
- * Returns a time-dependent dampening factor using delta time.
- */
- private static float computeDampeningFactor(float deltaTime) {
- return deltaTime / (SCROLL_VELOCITY_DAMPENING_RC + deltaTime);
- }
-
- /**
- * Returns the linear interpolation between two values
- */
- public static float interpolate(float from, float to, float alpha) {
- return (1.0f - alpha) * from + alpha * to;
+ mListener.onDragEnd(velocity, Math.abs(velocity) > RELEASE_VELOCITY_PX_MS);
}
public static long calculateDuration(float velocity, float progressNeeded) {
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 26c8f24..f948beb 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -128,7 +128,7 @@
public void onDragStart(boolean start) { }
@Override
- public boolean onDrag(float displacement, float velocity) {
+ public boolean onDrag(float displacement) {
float range = mContent.getHeight();
displacement = Utilities.boundToRange(displacement, 0, range);
setTranslationShift(displacement / range);
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index f0d6de2..883cbee 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -175,6 +175,7 @@
if (mThumbOffsetY == y) {
return;
}
+ updatePopupY((int) y);
mThumbOffsetY = y;
invalidate();
}
@@ -281,7 +282,6 @@
mPopupView.setText(sectionName);
}
animatePopupVisibility(!sectionName.isEmpty());
- updatePopupY(lastY);
mLastTouchY = boundedY;
setThumbOffsetY((int) mLastTouchY);
}
@@ -299,11 +299,14 @@
canvas.translate(0, mThumbOffsetY);
halfW += mThumbPadding;
- float r = mWidth + mThumbPadding + mThumbPadding;
+ float r = getScrollThumbRadius();
canvas.drawRoundRect(-halfW, 0, halfW, mThumbHeight, r, r, mThumbPaint);
canvas.restoreToCount(saveCount);
}
+ private float getScrollThumbRadius() {
+ return mWidth + mThumbPadding + mThumbPadding;
+ }
/**
* Animates the width of the scrollbar.
@@ -352,11 +355,15 @@
}
private void updatePopupY(int lastTouchY) {
+ if (!mPopupVisible) {
+ return;
+ }
int height = mPopupView.getHeight();
- float top = lastTouchY - (FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR * height)
- + mRv.getScrollBarTop();
- top = Utilities.boundToRange(top,
- mMaxWidth, mRv.getScrollbarTrackHeight() - mMaxWidth - height);
+ // Aligns the rounded corner of the pop up with the top of the thumb.
+ float top = mRv.getScrollBarTop() + lastTouchY + (getScrollThumbRadius() / 2f)
+ - (height / 2f);
+ top = Utilities.boundToRange(top, 0,
+ getTop() + mRv.getScrollBarTop() + mRv.getScrollbarTrackHeight() - height);
mPopupView.setTranslationY(top);
}
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 74ab14f..8ea9bd4 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -34,7 +34,7 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.LivePreviewWidgetCell;
import com.android.launcher3.graphics.DragPreviewProvider;
-import com.android.launcher3.graphics.LauncherIcons;
+import com.android.launcher3.icons.LauncherIcons;
/**
* Extension of {@link DragPreviewProvider} with logic specific to pending widgets/shortcuts
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java
index 7883442..6808859 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java
@@ -45,7 +45,7 @@
import android.util.Pair;
import com.android.launcher3.Utilities;
-import com.android.launcher3.graphics.ColorExtractor;
+import com.android.launcher3.icons.ColorExtractor;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index 59b2da0..1e56439 100644
--- a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -11,7 +11,6 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
-import android.content.pm.LauncherActivityInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -24,6 +23,7 @@
import com.android.launcher3.AllAppsList;
import com.android.launcher3.AppFilter;
import com.android.launcher3.AppInfo;
+import com.android.launcher3.icons.CachingLogic;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.ItemInfo;
@@ -32,7 +32,7 @@
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.graphics.BitmapInfo;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.TestLauncherProvider;
@@ -203,9 +203,10 @@
}
@Override
- protected CacheEntry cacheLocked(
+ protected <T> CacheEntry cacheLocked(
@NonNull ComponentName componentName,
- @NonNull Provider<LauncherActivityInfo> infoProvider,
+ @NonNull Provider<T> infoProvider,
+ @NonNull CachingLogic<T> cachingLogic,
UserHandle user, boolean usePackageIcon, boolean useLowResIcon) {
CacheEntry entry = mCache.get(new ComponentKey(componentName, user));
if (entry == null) {
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 42a2764..a21f861 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -17,7 +17,7 @@
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.graphics.BitmapInfo;
+import com.android.launcher3.icons.BitmapInfo;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
index 73b6daf..b600473 100644
--- a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
+++ b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
@@ -19,7 +19,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import android.util.Log;
-import android.view.MotionEvent;
import android.view.ViewConfiguration;
import com.android.launcher3.testcomponent.TouchEventGenerator;
@@ -32,6 +31,7 @@
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -51,25 +51,28 @@
@Mock
private SwipeDetector.Listener mMockListener;
+ @Mock
+ private ViewConfiguration mMockConfig;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mGenerator = new TouchEventGenerator(new TouchEventGenerator.Listener() {
- @Override
- public void onTouchEvent(MotionEvent event) {
- mDetector.onTouchEvent(event);
- }
- });
+ mGenerator = new TouchEventGenerator((ev) -> mDetector.onTouchEvent(ev));
+ ViewConfiguration orgConfig = ViewConfiguration
+ .get(InstrumentationRegistry.getTargetContext());
+ doReturn(orgConfig.getScaledMaximumFlingVelocity()).when(mMockConfig)
+ .getScaledMaximumFlingVelocity();
- mDetector = new SwipeDetector(mTouchSlop, mMockListener, SwipeDetector.VERTICAL);
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.VERTICAL);
mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_BOTH, false);
- mTouchSlop = ViewConfiguration.get(InstrumentationRegistry.getTargetContext())
- .getScaledTouchSlop();
+ mTouchSlop = orgConfig.getScaledTouchSlop();
+ doReturn(mTouchSlop).when(mMockConfig).getScaledTouchSlop();
+
L("mTouchSlop=", mTouchSlop);
}
@Test
- public void testDragStart_vertical() throws Exception {
+ public void testDragStart_vertical() {
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100, 100 + mTouchSlop);
// TODO: actually calculate the following parameters and do exact value checks.
@@ -77,7 +80,7 @@
}
@Test
- public void testDragStart_failed() throws Exception {
+ public void testDragStart_failed() {
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100 + mTouchSlop, 100);
// TODO: actually calculate the following parameters and do exact value checks.
@@ -85,8 +88,8 @@
}
@Test
- public void testDragStart_horizontal() throws Exception {
- mDetector = new SwipeDetector(mTouchSlop, mMockListener, SwipeDetector.HORIZONTAL);
+ public void testDragStart_horizontal() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL);
mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_BOTH, false);
mGenerator.put(0, 100, 100);
@@ -96,15 +99,15 @@
}
@Test
- public void testDrag() throws Exception {
+ public void testDrag() {
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100, 100 + mTouchSlop);
// TODO: actually calculate the following parameters and do exact value checks.
- verify(mMockListener).onDrag(anyFloat(), anyFloat());
+ verify(mMockListener).onDrag(anyFloat());
}
@Test
- public void testDragEnd() throws Exception {
+ public void testDragEnd() {
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100, 100 + mTouchSlop);
mGenerator.move(0, 100, 100 + mTouchSlop * 2);
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index ba7d9c5..75efea4 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -82,12 +82,17 @@
protected final LauncherInstrumentation mLauncher;
protected Context mTargetContext;
protected String mTargetPackage;
+ protected final boolean mIsInLauncherProcess;
private static final String TAG = "AbstractLauncherUiTest";
protected AbstractLauncherUiTest() {
- mDevice = UiDevice.getInstance(getInstrumentation());
- mLauncher = new LauncherInstrumentation(getInstrumentation());
+ final Instrumentation instrumentation = getInstrumentation();
+ mDevice = UiDevice.getInstance(instrumentation);
+ mLauncher = new LauncherInstrumentation(instrumentation);
+
+ mIsInLauncherProcess = instrumentation.getTargetContext().getPackageName().equals(
+ mDevice.getLauncherPackageName());
}
@Rule
@@ -261,6 +266,7 @@
}
protected <T> T getFromLauncher(Function<Launcher, T> f) {
+ if (!mIsInLauncherProcess) return null;
return getOnUiThread(() -> f.apply(mActivityMonitor.getActivity()));
}
@@ -287,6 +293,7 @@
// flakiness.
protected boolean waitForLauncherCondition(
Function<Launcher, Boolean> condition, long timeout) {
+ if (!mIsInLauncherProcess) return true;
return Wait.atMost(() -> getFromLauncher(condition), timeout);
}
diff --git a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
index 23560e8..a50a8b1 100644
--- a/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
+++ b/tests/src/com/android/launcher3/ui/AllAppsIconToHomeTest.java
@@ -42,7 +42,8 @@
LauncherActivityInfo settingsApp = getSettingsApp();
clearHomescreen();
- mActivityMonitor.startLauncher();
+ mDevice.pressHome();
+ mDevice.waitForIdle();
// Open all apps and wait for load complete.
final UiObject2 appsContainer = openAllApps();