2010-02-08 13:44:00 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2008 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.
|
|
|
|
|
*/
|
|
|
|
|
|
2018-09-21 14:41:05 -07:00
|
|
|
package com.android.launcher3.icons;
|
2010-02-08 13:44:00 -08:00
|
|
|
|
2019-08-15 14:53:41 -07:00
|
|
|
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
|
|
|
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
|
|
|
|
|
2012-02-13 14:27:42 -08:00
|
|
|
import android.content.Context;
|
2010-02-08 13:44:00 -08:00
|
|
|
import android.content.Intent;
|
2018-11-06 10:28:37 -08:00
|
|
|
import android.content.pm.ApplicationInfo;
|
2017-01-05 15:22:41 -08:00
|
|
|
import android.content.pm.LauncherActivityInfo;
|
2019-10-02 16:13:34 -07:00
|
|
|
import android.content.pm.LauncherApps;
|
2015-02-18 16:46:50 -08:00
|
|
|
import android.content.pm.PackageInfo;
|
2019-09-20 12:51:37 -07:00
|
|
|
import android.content.pm.PackageInstaller;
|
2010-02-08 13:44:00 -08:00
|
|
|
import android.content.pm.PackageManager;
|
2014-08-11 17:05:23 -07:00
|
|
|
import android.content.pm.PackageManager.NameNotFoundException;
|
2019-10-23 17:47:28 +00:00
|
|
|
import android.content.pm.ShortcutInfo;
|
2018-11-05 17:05:35 -08:00
|
|
|
import android.graphics.drawable.Drawable;
|
2015-03-11 16:56:52 -07:00
|
|
|
import android.os.Handler;
|
2016-12-15 15:53:17 -08:00
|
|
|
import android.os.Process;
|
|
|
|
|
import android.os.UserHandle;
|
2014-02-10 12:16:54 -05:00
|
|
|
import android.util.Log;
|
2017-11-08 16:52:34 -08:00
|
|
|
|
2019-08-06 09:48:36 -07:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
|
|
2018-09-21 14:41:05 -07:00
|
|
|
import com.android.launcher3.AppInfo;
|
|
|
|
|
import com.android.launcher3.InvariantDeviceProfile;
|
|
|
|
|
import com.android.launcher3.ItemInfoWithIcon;
|
2018-11-06 10:28:37 -08:00
|
|
|
import com.android.launcher3.LauncherFiles;
|
2018-09-21 14:41:05 -07:00
|
|
|
import com.android.launcher3.Utilities;
|
2019-08-06 09:48:36 -07:00
|
|
|
import com.android.launcher3.WorkspaceItemInfo;
|
2018-11-06 10:28:37 -08:00
|
|
|
import com.android.launcher3.compat.UserManagerCompat;
|
2019-09-09 23:32:17 -07:00
|
|
|
import com.android.launcher3.config.FeatureFlags;
|
2018-11-05 17:05:35 -08:00
|
|
|
import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic;
|
2018-11-08 10:51:05 -08:00
|
|
|
import com.android.launcher3.icons.cache.BaseIconCache;
|
|
|
|
|
import com.android.launcher3.icons.cache.CachingLogic;
|
|
|
|
|
import com.android.launcher3.icons.cache.HandlerRunnable;
|
2015-05-21 13:04:53 -07:00
|
|
|
import com.android.launcher3.model.PackageItemInfo;
|
2019-10-23 17:47:28 +00:00
|
|
|
import com.android.launcher3.shortcuts.ShortcutKey;
|
2019-10-24 15:59:49 -07:00
|
|
|
import com.android.launcher3.util.ComponentKey;
|
2018-11-06 10:28:37 -08:00
|
|
|
import com.android.launcher3.util.InstantAppResolver;
|
2019-09-20 12:51:37 -07:00
|
|
|
import com.android.launcher3.util.PackageUserKey;
|
2017-01-06 16:32:57 -08:00
|
|
|
import com.android.launcher3.util.Preconditions;
|
2019-01-25 15:10:18 -08:00
|
|
|
|
|
|
|
|
import java.util.function.Supplier;
|
2010-02-08 13:44:00 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Cache of application icons. Icons can be made from any thread.
|
|
|
|
|
*/
|
2018-09-24 10:51:52 -07:00
|
|
|
public class IconCache extends BaseIconCache {
|
2014-08-11 17:05:23 -07:00
|
|
|
|
2010-02-08 13:44:00 -08:00
|
|
|
private static final String TAG = "Launcher.IconCache";
|
|
|
|
|
|
2018-11-05 17:05:35 -08:00
|
|
|
private final CachingLogic<ComponentWithLabel> mComponentWithLabelCachingLogic;
|
|
|
|
|
private final CachingLogic<LauncherActivityInfo> mLauncherActivityInfoCachingLogic;
|
2019-10-23 17:47:28 +00:00
|
|
|
private final CachingLogic<ShortcutInfo> mShortcutCachingLogic;
|
2018-11-05 17:05:35 -08:00
|
|
|
|
2019-10-02 16:13:34 -07:00
|
|
|
private final LauncherApps mLauncherApps;
|
2018-11-06 10:28:37 -08:00
|
|
|
private final UserManagerCompat mUserManager;
|
|
|
|
|
private final InstantAppResolver mInstantAppResolver;
|
2018-11-08 10:51:05 -08:00
|
|
|
private final IconProvider mIconProvider;
|
2018-11-05 17:05:35 -08:00
|
|
|
|
2018-05-11 09:18:50 -07:00
|
|
|
private int mPendingIconRequestCount = 0;
|
|
|
|
|
|
2015-05-06 11:42:25 -07:00
|
|
|
public IconCache(Context context, InvariantDeviceProfile inv) {
|
2019-08-15 14:53:41 -07:00
|
|
|
super(context, LauncherFiles.APP_ICONS_DB, MODEL_EXECUTOR.getLooper(),
|
2018-11-09 11:13:10 -08:00
|
|
|
inv.fillResIconDpi, inv.iconBitmapSize, true /* inMemoryCache */);
|
2019-09-17 23:34:50 -07:00
|
|
|
mComponentWithLabelCachingLogic = new ComponentCachingLogic(context, false);
|
2019-08-06 09:48:36 -07:00
|
|
|
mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.newInstance(context);
|
2019-10-23 17:47:28 +00:00
|
|
|
mShortcutCachingLogic = new ShortcutCachingLogic();
|
2019-10-02 16:13:34 -07:00
|
|
|
mLauncherApps = mContext.getSystemService(LauncherApps.class);
|
2018-11-06 10:28:37 -08:00
|
|
|
mUserManager = UserManagerCompat.getInstance(mContext);
|
|
|
|
|
mInstantAppResolver = InstantAppResolver.newInstance(mContext);
|
2019-10-24 15:59:49 -07:00
|
|
|
mIconProvider = new IconProvider(context);
|
2018-11-06 10:28:37 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected long getSerialNumberForUser(UserHandle user) {
|
|
|
|
|
return mUserManager.getSerialNumberForUser(user);
|
|
|
|
|
}
|
2018-11-05 17:05:35 -08:00
|
|
|
|
2018-11-06 10:28:37 -08:00
|
|
|
@Override
|
|
|
|
|
protected boolean isInstantApp(ApplicationInfo info) {
|
|
|
|
|
return mInstantAppResolver.isInstantApp(info);
|
2014-02-10 12:16:54 -05:00
|
|
|
}
|
|
|
|
|
|
2018-11-08 10:51:05 -08:00
|
|
|
@Override
|
|
|
|
|
protected BaseIconFactory getIconFactory() {
|
|
|
|
|
return LauncherIcons.obtain(mContext);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 16:46:50 -08:00
|
|
|
/**
|
|
|
|
|
* Updates the entries related to the given package in memory and persistent DB.
|
|
|
|
|
*/
|
2016-12-15 15:53:17 -08:00
|
|
|
public synchronized void updateIconsForPkg(String packageName, UserHandle user) {
|
2015-02-18 16:46:50 -08:00
|
|
|
removeIconsForPkg(packageName, user);
|
|
|
|
|
try {
|
|
|
|
|
PackageInfo info = mPackageManager.getPackageInfo(packageName,
|
|
|
|
|
PackageManager.GET_UNINSTALLED_PACKAGES);
|
|
|
|
|
long userSerial = mUserManager.getSerialNumberForUser(user);
|
2017-01-05 15:22:41 -08:00
|
|
|
for (LauncherActivityInfo app : mLauncherApps.getActivityList(packageName, user)) {
|
2018-11-05 17:05:35 -08:00
|
|
|
addIconToDBAndMemCache(app, mLauncherActivityInfoCachingLogic, info, userSerial,
|
2018-09-24 10:51:52 -07:00
|
|
|
false /*replace existing*/);
|
2015-02-18 16:46:50 -08:00
|
|
|
}
|
|
|
|
|
} catch (NameNotFoundException e) {
|
|
|
|
|
Log.d(TAG, "Package not found", e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-08 13:44:00 -08:00
|
|
|
/**
|
2015-03-11 16:56:52 -07:00
|
|
|
* 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.
|
2010-02-08 13:44:00 -08:00
|
|
|
*/
|
2017-01-03 16:52:43 -08:00
|
|
|
public IconLoadRequest updateIconInBackground(final ItemInfoUpdateReceiver caller,
|
|
|
|
|
final ItemInfoWithIcon info) {
|
2018-05-11 09:18:50 -07:00
|
|
|
Preconditions.assertUIThread();
|
|
|
|
|
if (mPendingIconRequestCount <= 0) {
|
2019-08-15 14:53:41 -07:00
|
|
|
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
|
2018-05-11 09:18:50 -07:00
|
|
|
}
|
|
|
|
|
mPendingIconRequestCount ++;
|
2015-03-11 16:56:52 -07:00
|
|
|
|
2018-05-11 09:18:50 -07:00
|
|
|
IconLoadRequest request = new IconLoadRequest(mWorkerHandler, this::onIconRequestEnd) {
|
2015-03-11 16:56:52 -07:00
|
|
|
@Override
|
|
|
|
|
public void run() {
|
2019-03-27 16:03:06 -07:00
|
|
|
if (info instanceof AppInfo || info instanceof WorkspaceItemInfo) {
|
2017-01-03 16:52:43 -08:00
|
|
|
getTitleAndIcon(info, false);
|
2015-05-12 11:32:39 -07:00
|
|
|
} else if (info instanceof PackageItemInfo) {
|
2016-12-15 17:40:07 -08:00
|
|
|
getTitleAndIconForApp((PackageItemInfo) info, false);
|
2015-03-11 16:56:52 -07:00
|
|
|
}
|
2019-08-15 14:53:41 -07:00
|
|
|
MAIN_EXECUTOR.execute(() -> {
|
2018-05-11 09:18:50 -07:00
|
|
|
caller.reapplyItemInfo(info);
|
|
|
|
|
onEnd();
|
2015-03-11 16:56:52 -07:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-05-11 09:18:50 -07:00
|
|
|
Utilities.postAsyncCallback(mWorkerHandler, request);
|
|
|
|
|
return request;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void onIconRequestEnd() {
|
|
|
|
|
mPendingIconRequestCount --;
|
|
|
|
|
if (mPendingIconRequestCount <= 0) {
|
2019-08-15 14:53:41 -07:00
|
|
|
MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
|
2018-05-11 09:18:50 -07:00
|
|
|
}
|
2015-03-11 16:56:52 -07:00
|
|
|
}
|
2010-02-08 13:44:00 -08:00
|
|
|
|
2015-05-06 16:53:21 -07:00
|
|
|
/**
|
|
|
|
|
* Updates {@param application} only if a valid entry is found.
|
|
|
|
|
*/
|
|
|
|
|
public synchronized void updateTitleAndIcon(AppInfo application) {
|
2016-12-15 17:40:07 -08:00
|
|
|
CacheEntry entry = cacheLocked(application.componentName,
|
2019-01-25 15:10:18 -08:00
|
|
|
application.user, () -> null, mLauncherActivityInfoCachingLogic,
|
2018-09-26 12:00:30 -07:00
|
|
|
false, application.usingLowResIcon());
|
2019-10-25 13:41:28 -07:00
|
|
|
if (entry.bitmap != null && !isDefaultIcon(entry.bitmap, application.user)) {
|
2016-12-15 17:40:07 -08:00
|
|
|
applyCacheEntry(entry, application);
|
2015-05-06 16:53:21 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-11 16:56:52 -07:00
|
|
|
/**
|
2016-12-15 17:40:07 -08:00
|
|
|
* Fill in {@param info} with the icon and label for {@param activityInfo}
|
2015-03-11 16:56:52 -07:00
|
|
|
*/
|
2016-12-15 17:40:07 -08:00
|
|
|
public synchronized void getTitleAndIcon(ItemInfoWithIcon info,
|
2017-01-05 15:22:41 -08:00
|
|
|
LauncherActivityInfo activityInfo, boolean useLowResIcon) {
|
2016-12-15 17:40:07 -08:00
|
|
|
// If we already have activity info, no need to use package icon
|
2019-01-25 15:10:18 -08:00
|
|
|
getTitleAndIcon(info, () -> activityInfo, false, useLowResIcon);
|
2010-02-08 13:44:00 -08:00
|
|
|
}
|
|
|
|
|
|
2019-10-23 17:47:28 +00:00
|
|
|
/**
|
|
|
|
|
* Fill in info with the icon and label for deep shortcut.
|
|
|
|
|
*/
|
|
|
|
|
public synchronized CacheEntry getDeepShortcutTitleAndIcon(ShortcutInfo info) {
|
|
|
|
|
return cacheLocked(ShortcutKey.fromInfo(info).componentName, info.getUserHandle(),
|
|
|
|
|
() -> info, mShortcutCachingLogic, false, false);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-29 17:20:55 -07:00
|
|
|
/**
|
2016-12-15 17:40:07 -08:00
|
|
|
* Fill in {@param info} with the icon and label. If the
|
2015-02-18 16:46:50 -08:00
|
|
|
* corresponding activity is not found, it reverts to the package icon.
|
2014-08-29 17:20:55 -07:00
|
|
|
*/
|
2016-12-15 17:40:07 -08:00
|
|
|
public synchronized void getTitleAndIcon(ItemInfoWithIcon info, boolean useLowResIcon) {
|
2014-10-16 14:07:29 -07:00
|
|
|
// null info means not installed, but if we have a component from the intent then
|
|
|
|
|
// we should still look in the cache for restored app icons.
|
2016-12-15 17:40:07 -08:00
|
|
|
if (info.getTargetComponent() == null) {
|
2019-10-25 13:41:28 -07:00
|
|
|
info.bitmap = getDefaultIcon(info.user);
|
2016-12-15 17:40:07 -08:00
|
|
|
info.title = "";
|
|
|
|
|
info.contentDescription = "";
|
2014-10-16 14:07:29 -07:00
|
|
|
} else {
|
2018-07-09 16:47:01 -07:00
|
|
|
Intent intent = info.getIntent();
|
|
|
|
|
getTitleAndIcon(info, () -> mLauncherApps.resolveActivity(intent, info.user),
|
2016-12-15 17:40:07 -08:00
|
|
|
true, useLowResIcon);
|
2014-08-29 17:20:55 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-26 12:00:30 -07:00
|
|
|
public synchronized String getTitleNoCache(ComponentWithLabel info) {
|
2019-01-25 15:10:18 -08:00
|
|
|
CacheEntry entry = cacheLocked(info.getComponent(), info.getUser(), () -> info,
|
2018-11-05 17:05:35 -08:00
|
|
|
mComponentWithLabelCachingLogic, false /* usePackageIcon */,
|
2019-09-17 23:34:50 -07:00
|
|
|
true /* useLowResIcon */);
|
2018-09-26 12:00:30 -07:00
|
|
|
return Utilities.trim(entry.title);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-18 16:46:50 -08:00
|
|
|
/**
|
2019-03-27 16:03:06 -07:00
|
|
|
* Fill in {@param mWorkspaceItemInfo} with the icon and label for {@param info}
|
2015-02-18 16:46:50 -08:00
|
|
|
*/
|
2016-12-15 17:40:07 -08:00
|
|
|
private synchronized void getTitleAndIcon(
|
|
|
|
|
@NonNull ItemInfoWithIcon infoInOut,
|
2019-01-25 15:10:18 -08:00
|
|
|
@NonNull Supplier<LauncherActivityInfo> activityInfoProvider,
|
2016-12-15 17:40:07 -08:00
|
|
|
boolean usePkgIcon, boolean useLowResIcon) {
|
2018-09-26 12:00:30 -07:00
|
|
|
CacheEntry entry = cacheLocked(infoInOut.getTargetComponent(), infoInOut.user,
|
2018-11-05 17:05:35 -08:00
|
|
|
activityInfoProvider, mLauncherActivityInfoCachingLogic, usePkgIcon, useLowResIcon);
|
2016-12-15 17:40:07 -08:00
|
|
|
applyCacheEntry(entry, infoInOut);
|
2015-02-18 16:46:50 -08:00
|
|
|
}
|
2014-08-29 17:20:55 -07:00
|
|
|
|
2018-11-05 17:05:35 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 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;
|
2019-10-25 13:41:28 -07:00
|
|
|
info.bitmap = (entry.bitmap == null) ? getDefaultIcon(info.user) : entry.bitmap;
|
2018-11-05 17:05:35 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Drawable getFullResIcon(LauncherActivityInfo info) {
|
2019-10-24 15:59:49 -07:00
|
|
|
return mIconProvider.getIcon(info, mIconDpi);
|
2018-11-05 17:05:35 -08:00
|
|
|
}
|
|
|
|
|
|
2019-09-20 12:51:37 -07:00
|
|
|
public void updateSessionCache(PackageUserKey key, PackageInstaller.SessionInfo info) {
|
|
|
|
|
cachePackageInstallInfo(key.mPackageName, key.mUser, info.getAppIcon(), info.getAppLabel());
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-08 10:51:05 -08:00
|
|
|
@Override
|
|
|
|
|
protected String getIconSystemState(String packageName) {
|
2019-09-09 23:32:17 -07:00
|
|
|
return mIconProvider.getSystemStateForPackage(mSystemState, packageName)
|
|
|
|
|
+ ",flags_asi:" + FeatureFlags.APP_SEARCH_IMPROVEMENTS.get();
|
2018-11-08 10:51:05 -08:00
|
|
|
}
|
|
|
|
|
|
2019-10-24 15:59:49 -07:00
|
|
|
@Override
|
|
|
|
|
protected boolean getEntryFromDB(ComponentKey cacheKey, CacheEntry entry, boolean lowRes) {
|
|
|
|
|
if (mIconProvider.isClockIcon(cacheKey)) {
|
|
|
|
|
// For clock icon, we always load the dynamic icon
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return super.getEntryFromDB(cacheKey, entry, lowRes);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-16 15:59:24 -07:00
|
|
|
public static abstract class IconLoadRequest extends HandlerRunnable {
|
2018-05-11 09:18:50 -07:00
|
|
|
IconLoadRequest(Handler handler, Runnable endRunnable) {
|
2018-10-16 15:59:24 -07:00
|
|
|
super(handler, endRunnable);
|
2015-03-11 16:56:52 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-03 16:52:43 -08:00
|
|
|
/**
|
|
|
|
|
* Interface for receiving itemInfo with high-res icon.
|
|
|
|
|
*/
|
|
|
|
|
public interface ItemInfoUpdateReceiver {
|
|
|
|
|
|
|
|
|
|
void reapplyItemInfo(ItemInfoWithIcon info);
|
|
|
|
|
}
|
2010-02-08 13:44:00 -08:00
|
|
|
}
|