Converting some caching logic booleans to lookup flags
Bug: 366237794 Test: atest IconCacheTest Flag: EXEMPT refactor Change-Id: I0d25996181954df22e1cb61596be0a2694ee7068
This commit is contained in:
@@ -110,8 +110,6 @@ object CacheableShortcutCachingLogic : CachingLogic<CacheableShortcutInfo> {
|
||||
info?.let { max(info.shortcutInfo.lastChangedTimestamp, packageInfo.lastUpdateTime) }
|
||||
?: packageInfo.lastUpdateTime
|
||||
|
||||
override fun addToMemCache() = false
|
||||
|
||||
override fun getApplicationInfo(info: CacheableShortcutInfo) = info.appInfo.getInfo()
|
||||
|
||||
override fun loadIcon(context: Context, cache: BaseIconCache, info: CacheableShortcutInfo) =
|
||||
|
||||
@@ -110,8 +110,7 @@ public class IconCache extends BaseIconCache {
|
||||
IconProvider iconProvider) {
|
||||
super(context, dbFileName, MODEL_EXECUTOR.getLooper(),
|
||||
idp.fillResIconDpi, idp.iconBitmapSize, true /* inMemoryCache */, iconProvider);
|
||||
mComponentWithLabelCachingLogic = new CachedObjectCachingLogic(
|
||||
context, false /* loadIcons */, false /* addToMemCache */);
|
||||
mComponentWithLabelCachingLogic = new CachedObjectCachingLogic(context);
|
||||
mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.INSTANCE;
|
||||
mLauncherApps = mContext.getSystemService(LauncherApps.class);
|
||||
mUserManager = UserCache.INSTANCE.get(mContext);
|
||||
@@ -149,8 +148,7 @@ public class IconCache extends BaseIconCache {
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES);
|
||||
long userSerial = mUserManager.getSerialNumberForUser(user);
|
||||
for (LauncherActivityInfo app : mLauncherApps.getActivityList(packageName, user)) {
|
||||
addIconToDBAndMemCache(app, mLauncherActivityInfoCachingLogic, info, userSerial,
|
||||
false /*replace existing*/);
|
||||
addIconToDBAndMemCache(app, mLauncherActivityInfoCachingLogic, info, userSerial);
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.d(TAG, "Package not found", e);
|
||||
@@ -205,7 +203,7 @@ public class IconCache extends BaseIconCache {
|
||||
|
||||
CancellableTask<ItemInfoWithIcon> request = new CancellableTask<>(
|
||||
task, MAIN_EXECUTOR, caller::reapplyItemInfo, endRunnable);
|
||||
Utilities.postAsyncCallback(mWorkerHandler, request);
|
||||
Utilities.postAsyncCallback(workerHandler, request);
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -257,6 +255,7 @@ public class IconCache extends BaseIconCache {
|
||||
/**
|
||||
* Fill in {@code info} with the icon and label for {@code si}. If the icon is not
|
||||
* available, and fallback check returns true, it keeps the old icon.
|
||||
* Shortcut entries are not kept in memory since they are not frequently used
|
||||
*/
|
||||
public <T extends ItemInfoWithIcon> void getShortcutIcon(T info, CacheableShortcutInfo si,
|
||||
@NonNull Predicate<T> fallbackIconCheck) {
|
||||
@@ -266,7 +265,7 @@ public class IconCache extends BaseIconCache {
|
||||
user,
|
||||
() -> si,
|
||||
CacheableShortcutCachingLogic.INSTANCE,
|
||||
LookupFlag.DEFAULT).bitmap;
|
||||
LookupFlag.SKIP_ADD_TO_MEM_CACHE).bitmap;
|
||||
if (bitmapInfo.isNullOrLowRes()) {
|
||||
bitmapInfo = getDefaultIcon(user);
|
||||
}
|
||||
@@ -337,7 +336,8 @@ public class IconCache extends BaseIconCache {
|
||||
*/
|
||||
public synchronized String getTitleNoCache(ComponentWithLabel info) {
|
||||
CacheEntry entry = cacheLocked(info.getComponent(), info.getUser(), () -> info,
|
||||
mComponentWithLabelCachingLogic, LookupFlag.USE_LOW_RES);
|
||||
mComponentWithLabelCachingLogic,
|
||||
LookupFlag.USE_LOW_RES | LookupFlag.SKIP_ADD_TO_MEM_CACHE);
|
||||
return Utilities.trim(entry.title);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,21 +15,39 @@
|
||||
*/
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import static android.os.Process.myUserHandle;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.launcher3.icons.IconCache.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE;
|
||||
import static com.android.launcher3.icons.IconCacheUpdateHandlerTestKt.waitForUpdateHandlerToFinish;
|
||||
import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
|
||||
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
|
||||
import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.LauncherActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutInfo.Builder;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -37,15 +55,30 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.icons.cache.CachingLogic;
|
||||
import com.android.launcher3.icons.cache.IconCacheUpdateHandler;
|
||||
import com.android.launcher3.icons.cache.LauncherActivityCachingLogic;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.settings.SettingsActivity;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.util.ApplicationInfoWrapper;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.RoboApiWrapper;
|
||||
|
||||
import com.google.common.truth.Truth;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class IconCacheTest {
|
||||
@@ -112,6 +145,102 @@ public class IconCacheTest {
|
||||
assertEquals(((PackageItemInfo) item).packageName, otherPackage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launcherActivityInfo_cached_in_memory() {
|
||||
RoboApiWrapper.INSTANCE.initialize();
|
||||
ComponentName cn = new ComponentName(TEST_PACKAGE, TEST_ACTIVITY);
|
||||
UserHandle user = myUserHandle();
|
||||
ComponentKey cacheKey = new ComponentKey(cn, user);
|
||||
|
||||
LauncherActivityInfo lai = mContext.getSystemService(LauncherApps.class)
|
||||
.resolveActivity(makeLaunchIntent(cn), user);
|
||||
assertNotNull(lai);
|
||||
|
||||
WorkspaceItemInfo info = new WorkspaceItemInfo();
|
||||
info.intent = makeLaunchIntent(cn);
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> mIconCache.getTitleAndIcon(info, lai, false));
|
||||
assertNotNull(info.bitmap);
|
||||
assertFalse(info.bitmap.isLowRes());
|
||||
|
||||
// Verify that icon is in memory cache
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> assertNotNull(mIconCache.getInMemoryEntryLocked(cacheKey)));
|
||||
|
||||
// Schedule async update and wait for it to complete
|
||||
Set<PackageUserKey> updates =
|
||||
executeIconUpdate(lai, LauncherActivityCachingLogic.INSTANCE);
|
||||
|
||||
// Verify that the icon was not updated and is still in memory cache
|
||||
Truth.assertThat(updates).isEmpty();
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> assertNotNull(mIconCache.getInMemoryEntryLocked(cacheKey)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shortcutInfo_not_cached_in_memory() {
|
||||
CacheableShortcutInfo si = mockShortcutInfo(0);
|
||||
ShortcutKey cacheKey = ShortcutKey.fromInfo(si.getShortcutInfo());
|
||||
|
||||
WorkspaceItemInfo info = new WorkspaceItemInfo();
|
||||
runOnExecutorSync(MODEL_EXECUTOR, () -> mIconCache.getShortcutIcon(info, si));
|
||||
assertNotNull(info.bitmap);
|
||||
assertFalse(info.bitmap.isLowRes());
|
||||
|
||||
// Verify that icon is in memory cache
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> assertNull(mIconCache.getInMemoryEntryLocked(cacheKey)));
|
||||
|
||||
Set<PackageUserKey> updates =
|
||||
executeIconUpdate(si, CacheableShortcutCachingLogic.INSTANCE);
|
||||
// Verify that the icon was not updated and is still in memory cache
|
||||
Truth.assertThat(updates).isEmpty();
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> assertNull(mIconCache.getInMemoryEntryLocked(cacheKey)));
|
||||
|
||||
// Now update the shortcut with a newer version
|
||||
updates = executeIconUpdate(
|
||||
mockShortcutInfo(System.currentTimeMillis() + 2000),
|
||||
CacheableShortcutCachingLogic.INSTANCE);
|
||||
|
||||
// Verify that icon was updated but it is still not in mem-cache
|
||||
Truth.assertThat(updates).containsExactly(
|
||||
new PackageUserKey(cacheKey.getPackageName(), cacheKey.user));
|
||||
runOnExecutorSync(MODEL_EXECUTOR,
|
||||
() -> assertNull(mIconCache.getInMemoryEntryLocked(cacheKey)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the icon update for the provided entry and returns the updated packages
|
||||
*/
|
||||
private <T> Set<PackageUserKey> executeIconUpdate(T object, CachingLogic<T> cachingLogic) {
|
||||
HashSet<PackageUserKey> updates = new HashSet<>();
|
||||
|
||||
runOnExecutorSync(MODEL_EXECUTOR, () -> {
|
||||
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
|
||||
updateHandler.updateIcons(
|
||||
Collections.singletonList(object),
|
||||
cachingLogic,
|
||||
(a, b) -> a.forEach(p -> updates.add(new PackageUserKey(p, b))));
|
||||
updateHandler.finish();
|
||||
});
|
||||
waitForUpdateHandlerToFinish(mIconCache);
|
||||
return updates;
|
||||
}
|
||||
|
||||
private CacheableShortcutInfo mockShortcutInfo(long updateTime) {
|
||||
ShortcutInfo info = new ShortcutInfo.Builder(
|
||||
getInstrumentation().getContext(), "test-shortcut")
|
||||
.setIntent(new Intent(Intent.ACTION_VIEW))
|
||||
.setShortLabel("Test")
|
||||
.setIcon(Icon.createWithBitmap(Bitmap.createBitmap(200, 200, Config.ARGB_8888)))
|
||||
.build();
|
||||
ShortcutInfo spied = spy(info);
|
||||
doReturn(updateTime).when(spied).getLastChangedTimestamp();
|
||||
return new CacheableShortcutInfo(spied,
|
||||
new ApplicationInfoWrapper(getInstrumentation().getContext().getApplicationInfo()));
|
||||
}
|
||||
|
||||
private ItemInfoWithIcon getBadgingInfo(Context context,
|
||||
@Nullable ComponentName cn, @Nullable String badgeOverride) throws Exception {
|
||||
Builder builder = new Builder(context, "test-shortcut")
|
||||
|
||||
+20
-3
@@ -25,6 +25,8 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.icons.cache.BaseIconCache
|
||||
import com.android.launcher3.icons.cache.CachingLogic
|
||||
import com.android.launcher3.icons.cache.IconCacheUpdateHandler
|
||||
import com.android.launcher3.util.RoboApiWrapper
|
||||
import java.util.concurrent.FutureTask
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -51,7 +53,7 @@ class IconCacheUpdateHandlerTest {
|
||||
System.currentTimeMillis(),
|
||||
1,
|
||||
1.0.toLong(),
|
||||
"stateOfConfusion"
|
||||
"stateOfConfusion",
|
||||
)
|
||||
|
||||
@Before
|
||||
@@ -81,17 +83,32 @@ class IconCacheUpdateHandlerTest {
|
||||
componentMap,
|
||||
ignorePackages,
|
||||
user,
|
||||
cachingLogic
|
||||
cachingLogic,
|
||||
)
|
||||
|
||||
assert(result == null)
|
||||
}
|
||||
}
|
||||
|
||||
/** Utility method to wait for the icon update handler to finish */
|
||||
fun IconCache.waitForUpdateHandlerToFinish() {
|
||||
var cacheUpdateInProgress = true
|
||||
while (cacheUpdateInProgress) {
|
||||
val cacheCheck = FutureTask {
|
||||
// Check for pending message on the worker thread itself as some task may be
|
||||
// running currently
|
||||
workerHandler.hasMessages(0, iconUpdateToken)
|
||||
}
|
||||
workerHandler.postDelayed(cacheCheck, 10)
|
||||
RoboApiWrapper.waitForLooperSync(workerHandler.looper)
|
||||
cacheUpdateInProgress = cacheCheck.get()
|
||||
}
|
||||
}
|
||||
|
||||
data class IconCacheRowData(
|
||||
val component: String,
|
||||
val lastUpdated: Long,
|
||||
val version: Int,
|
||||
val row: Long,
|
||||
val systemState: String
|
||||
val systemState: String,
|
||||
)
|
||||
|
||||
@@ -19,16 +19,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.launcher3.LauncherAppState
|
||||
import com.android.launcher3.icons.BitmapInfo
|
||||
import com.android.launcher3.icons.waitForUpdateHandlerToFinish
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
import com.android.launcher3.util.Executors
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder
|
||||
import com.android.launcher3.util.LauncherModelHelper
|
||||
import com.android.launcher3.util.LauncherModelHelper.*
|
||||
import com.android.launcher3.util.RoboApiWrapper
|
||||
import com.android.launcher3.util.TestUtil
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import com.google.common.truth.Truth.assertWithMessage
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@@ -147,14 +146,9 @@ class FolderIconLoadTest {
|
||||
// The first load initializes the DB, load again so that icons are now used from the DB
|
||||
// Wait for the icon cache to be updated and then reload
|
||||
val app = LauncherAppState.getInstance(modelHelper.sandboxContext)
|
||||
val cache = app.iconCache
|
||||
while (cache.isIconUpdateInProgress) {
|
||||
val wait = CountDownLatch(1)
|
||||
Executors.MODEL_EXECUTOR.handler.postDelayed({ wait.countDown() }, 10)
|
||||
RoboApiWrapper.waitForLooperSync(Executors.MODEL_EXECUTOR.handler.looper)
|
||||
wait.await()
|
||||
}
|
||||
TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { cache.clearMemoryCache() }
|
||||
app.iconCache.waitForUpdateHandlerToFinish()
|
||||
|
||||
TestUtil.runOnExecutorSync(Executors.MODEL_EXECUTOR) { app.iconCache.clearMemoryCache() }
|
||||
// Reload again with correct icon state
|
||||
app.model.forceReload()
|
||||
modelHelper.loadModelSync()
|
||||
|
||||
Reference in New Issue
Block a user