1 package com.android.launcher3.model;
2 
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotSame;
6 import static org.junit.Assert.assertTrue;
7 
8 import android.content.ComponentName;
9 import android.content.Context;
10 import android.content.pm.PackageInfo;
11 import android.graphics.Bitmap;
12 import android.graphics.Bitmap.Config;
13 import android.graphics.Color;
14 import android.os.Process;
15 import android.os.UserHandle;
16 import android.os.UserManager;
17 
18 import androidx.annotation.NonNull;
19 
20 import com.android.launcher3.LauncherAppState;
21 import com.android.launcher3.icons.BitmapInfo;
22 import com.android.launcher3.icons.IconCache;
23 import com.android.launcher3.icons.cache.CachingLogic;
24 import com.android.launcher3.model.data.AppInfo;
25 import com.android.launcher3.model.data.ItemInfo;
26 import com.android.launcher3.model.data.WorkspaceItemInfo;
27 import com.android.launcher3.util.LauncherModelHelper;
28 
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.robolectric.RobolectricTestRunner;
33 import org.robolectric.RuntimeEnvironment;
34 import org.robolectric.annotation.LooperMode;
35 import org.robolectric.annotation.LooperMode.Mode;
36 
37 import java.util.Arrays;
38 import java.util.HashSet;
39 
40 /**
41  * Tests for {@link CacheDataUpdatedTask}
42  */
43 @RunWith(RobolectricTestRunner.class)
44 @LooperMode(Mode.PAUSED)
45 public class CacheDataUpdatedTaskTest {
46 
47     private static final String NEW_LABEL_PREFIX = "new-label-";
48 
49     private LauncherModelHelper mModelHelper;
50 
51     @Before
setup()52     public void setup() throws Exception {
53         mModelHelper = new LauncherModelHelper();
54         mModelHelper.initializeData("/cache_data_updated_task_data.txt");
55 
56         // Add dummy entries in the cache to simulate update
57         Context context = RuntimeEnvironment.application;
58         IconCache iconCache = LauncherAppState.getInstance(context).getIconCache();
59         CachingLogic<ItemInfo> dummyLogic = new CachingLogic<ItemInfo>() {
60             @Override
61             public ComponentName getComponent(ItemInfo info) {
62                 return info.getTargetComponent();
63             }
64 
65             @Override
66             public UserHandle getUser(ItemInfo info) {
67                 return info.user;
68             }
69 
70             @Override
71             public CharSequence getLabel(ItemInfo info) {
72                 return NEW_LABEL_PREFIX + info.id;
73             }
74 
75             @NonNull
76             @Override
77             public BitmapInfo loadIcon(Context context, ItemInfo info) {
78                 return BitmapInfo.of(Bitmap.createBitmap(1, 1, Config.ARGB_8888), Color.RED);
79             }
80         };
81 
82         UserManager um = context.getSystemService(UserManager.class);
83         for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
84             iconCache.addIconToDBAndMemCache(info, dummyLogic, new PackageInfo(),
85                     um.getSerialNumberForUser(info.user), true);
86         }
87     }
88 
newTask(int op, String... pkg)89     private CacheDataUpdatedTask newTask(int op, String... pkg) {
90         return new CacheDataUpdatedTask(op, Process.myUserHandle(),
91                 new HashSet<>(Arrays.asList(pkg)));
92     }
93 
94     @Test
testCacheUpdate_update_apps()95     public void testCacheUpdate_update_apps() throws Exception {
96         // Clear all icons from apps list so that its easy to check what was updated
97         for (AppInfo info : mModelHelper.getAllAppsList().data) {
98             info.bitmap = BitmapInfo.LOW_RES_INFO;
99         }
100 
101         mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
102 
103         // Verify that only the app icons of app1 (id 1 & 2) are updated. Custom shortcut (id 7)
104         // is not updated
105         verifyUpdate(1, 2);
106 
107         // Verify that only app1 var updated in allAppsList
108         assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
109         for (AppInfo info : mModelHelper.getAllAppsList().data) {
110             if (info.componentName.getPackageName().equals("app1")) {
111                 assertFalse(info.bitmap.isNullOrLowRes());
112             } else {
113                 assertTrue(info.bitmap.isNullOrLowRes());
114             }
115         }
116     }
117 
118     @Test
testSessionUpdate_ignores_normal_apps()119     public void testSessionUpdate_ignores_normal_apps() throws Exception {
120         mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
121 
122         // app1 has no restored shortcuts. Verify that nothing was updated.
123         verifyUpdate();
124     }
125 
126     @Test
testSessionUpdate_updates_pending_apps()127     public void testSessionUpdate_updates_pending_apps() throws Exception {
128         mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
129 
130         // app3 has only restored apps (id 5, 6) and shortcuts (id 9). Verify that only apps were
131         // were updated
132         verifyUpdate(5, 6);
133     }
134 
verifyUpdate(Integer... idsUpdated)135     private void verifyUpdate(Integer... idsUpdated) {
136         HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
137         for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
138             if (updates.contains(info.id)) {
139                 assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
140                 assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
141             } else {
142                 assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
143                 assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
144             }
145         }
146     }
147 }
148