Converting some caching logic booleans to lookup flags
Bug: 366237794 Test: atest IconCacheTest Flag: EXEMPT refactor Change-Id: I0d25996181954df22e1cb61596be0a2694ee7068
This commit is contained in:
@@ -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