blob: ed53b7782e46d813e7d798ab4da5a2eb32af6066 [file] [log] [blame]
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.pm;
17
18import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.cloneShortcutList;
19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.hashSet;
20import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
21import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
22import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
23
24import static org.mockito.Matchers.any;
25import static org.mockito.Matchers.eq;
26import static org.mockito.Mockito.doAnswer;
27import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.reset;
29import static org.mockito.Mockito.spy;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
33import android.annotation.NonNull;
34import android.annotation.Nullable;
35import android.annotation.RequiresPermission;
36import android.annotation.UserIdInt;
37import android.app.Activity;
38import android.app.IUidObserver;
Makoto Onukiac042502016-05-20 16:39:42 -070039import android.app.usage.UsageStatsManagerInternal;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070040import android.content.BroadcastReceiver;
41import android.content.ComponentName;
42import android.content.Context;
43import android.content.Intent;
44import android.content.IntentFilter;
45import android.content.pm.ActivityInfo;
46import android.content.pm.ApplicationInfo;
47import android.content.pm.ILauncherApps;
48import android.content.pm.LauncherApps;
49import android.content.pm.LauncherApps.ShortcutQuery;
50import android.content.pm.PackageInfo;
51import android.content.pm.PackageManager;
52import android.content.pm.PackageManagerInternal;
53import android.content.pm.ShortcutInfo;
54import android.content.pm.ShortcutManager;
55import android.content.pm.ShortcutServiceInternal;
56import android.content.pm.Signature;
57import android.content.pm.UserInfo;
58import android.content.res.Resources;
59import android.content.res.XmlResourceParser;
60import android.graphics.drawable.Icon;
61import android.net.Uri;
62import android.os.Bundle;
63import android.os.FileUtils;
64import android.os.Handler;
65import android.os.Looper;
66import android.os.Process;
67import android.os.UserHandle;
68import android.os.UserManager;
69import android.test.InstrumentationTestCase;
70import android.test.mock.MockContext;
71import android.util.Log;
72import android.util.Pair;
73
74import com.android.internal.util.Preconditions;
75import com.android.server.LocalServices;
76import com.android.server.SystemService;
77import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
78import com.android.server.pm.ShortcutUser.PackageWithUser;
79
80import org.junit.Assert;
81import org.mockito.ArgumentCaptor;
82import org.mockito.invocation.InvocationOnMock;
83import org.mockito.stubbing.Answer;
84
85import java.io.BufferedReader;
86import java.io.ByteArrayOutputStream;
87import java.io.File;
88import java.io.FileReader;
89import java.io.PrintWriter;
90import java.util.ArrayList;
91import java.util.HashMap;
92import java.util.HashSet;
93import java.util.LinkedHashMap;
94import java.util.List;
95import java.util.Map;
96import java.util.Set;
97import java.util.function.BiPredicate;
98import java.util.function.Consumer;
99
100public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
101 protected static final String TAG = "ShortcutManagerTest";
102
103 /**
104 * Whether to enable dump or not. Should be only true when debugging to avoid bugs where
105 * dump affecting the behavior.
106 */
107 protected static final boolean ENABLE_DUMP = false; // DO NOT SUBMIT WITH true
108
109 protected static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
110
111 protected static final String[] EMPTY_STRINGS = new String[0]; // Just for readability.
112
113 // public for mockito
114 public class BaseContext extends MockContext {
115 @Override
116 public Object getSystemService(String name) {
117 switch (name) {
118 case Context.USER_SERVICE:
119 return mMockUserManager;
120 }
121 throw new UnsupportedOperationException();
122 }
123
124 @Override
125 public String getSystemServiceName(Class<?> serviceClass) {
126 return getTestContext().getSystemServiceName(serviceClass);
127 }
128
129 @Override
130 public PackageManager getPackageManager() {
131 return mMockPackageManager;
132 }
133
134 @Override
135 public Resources getResources() {
136 return getTestContext().getResources();
137 }
138
139 @Override
140 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
141 IntentFilter filter, String broadcastPermission, Handler scheduler) {
142 // ignore.
143 return null;
144 }
145 }
146
147 /** Context used in the client side */
148 public class ClientContext extends BaseContext {
149 @Override
150 public String getPackageName() {
151 return mInjectedClientPackage;
152 }
153
154 @Override
155 public int getUserId() {
156 return getCallingUserId();
157 }
158 }
159
160 /** Context used in the service side */
161 public class ServiceContext extends BaseContext {
162 long injectClearCallingIdentity() {
163 final int prevCallingUid = mInjectedCallingUid;
164 mInjectedCallingUid = Process.SYSTEM_UID;
165 return prevCallingUid;
166 }
167
168 void injectRestoreCallingIdentity(long token) {
169 mInjectedCallingUid = (int) token;
170 }
171
172 @Override
173 public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
174 UserHandle userId) {
175 }
176
177 @Override
178 public int getUserId() {
179 return UserHandle.USER_SYSTEM;
180 }
181
182 public PackageInfo injectGetActivitiesWithMetadata(
183 String packageName, @UserIdInt int userId) {
184 return BaseShortcutManagerTest.this.injectGetActivitiesWithMetadata(packageName, userId);
185 }
186
187 public XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
188 return BaseShortcutManagerTest.this.injectXmlMetaData(activityInfo, key);
189 }
190 }
191
192 /** ShortcutService with injection override methods. */
193 protected final class ShortcutServiceTestable extends ShortcutService {
194 final ServiceContext mContext;
195 IUidObserver mUidObserver;
196
197 public ShortcutServiceTestable(ServiceContext context, Looper looper) {
198 super(context, looper);
199 mContext = context;
200 }
201
202 @Override
203 boolean injectShouldPerformVerification() {
204 return true; // Always verify during unit tests.
205 }
206
207 @Override
208 String injectShortcutManagerConstants() {
209 return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + ","
210 + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + ","
211 + ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "="
212 + MAX_UPDATES_PER_INTERVAL + ","
213 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + ","
214 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "="
215 + MAX_ICON_DIMENSION_LOWRAM + ","
216 + ConfigConstants.KEY_ICON_FORMAT + "=PNG,"
217 + ConfigConstants.KEY_ICON_QUALITY + "=100";
218 }
219
220 @Override
221 long injectClearCallingIdentity() {
222 return mContext.injectClearCallingIdentity();
223 }
224
225 @Override
226 void injectRestoreCallingIdentity(long token) {
227 mContext.injectRestoreCallingIdentity(token);
228 }
229
230 @Override
231 int injectDipToPixel(int dip) {
232 return dip;
233 }
234
235 @Override
236 long injectCurrentTimeMillis() {
237 return mInjectedCurrentTimeMillis;
238 }
239
240 @Override
241 long injectElapsedRealtime() {
242 // TODO This should be kept separately from mInjectedCurrentTimeMillis, since
243 // this should increase even if we rewind mInjectedCurrentTimeMillis in some tests.
244 return mInjectedCurrentTimeMillis - START_TIME;
245 }
246
247 @Override
248 int injectBinderCallingUid() {
249 return mInjectedCallingUid;
250 }
251
252 @Override
253 int injectGetPackageUid(String packageName, int userId) {
254 return getInjectedPackageInfo(packageName, userId, false).applicationInfo.uid;
255 }
256
257 @Override
258 File injectSystemDataPath() {
259 return new File(mInjectedFilePathRoot, "system");
260 }
261
262 @Override
263 File injectUserDataPath(@UserIdInt int userId) {
264 return new File(mInjectedFilePathRoot, "user-" + userId);
265 }
266
267 @Override
268 void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
269 // Can't check
270 }
271
272 @Override
273 boolean injectIsLowRamDevice() {
274 return mInjectedIsLowRamDevice;
275 }
276
277 @Override
278 void injectRegisterUidObserver(IUidObserver observer, int which) {
279 mUidObserver = observer;
280 }
281
282 @Override
283 PackageManagerInternal injectPackageManagerInternal() {
284 return mMockPackageManagerInternal;
285 }
286
287 @Override
288 boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
289 return mDefaultLauncherChecker.test(callingPackage, userId);
290 }
291
292 @Override
293 PackageInfo injectPackageInfo(String packageName, @UserIdInt int userId,
294 boolean getSignatures) {
295 return getInjectedPackageInfo(packageName, userId, getSignatures);
296 }
297
298 @Override
299 ApplicationInfo injectApplicationInfo(String packageName, @UserIdInt int userId) {
300 PackageInfo pi = injectPackageInfo(packageName, userId, /* getSignatures= */ false);
301 return pi != null ? pi.applicationInfo : null;
302 }
303
304 @Override
305 List<ApplicationInfo> injectInstalledApplications(@UserIdInt int userId) {
306 return getInstalledApplications(userId);
307 }
308
309 @Override
310 PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) {
311 return mContext.injectGetActivitiesWithMetadata(packageName, userId);
312 }
313
314 @Override
315 XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
316 return mContext.injectXmlMetaData(activityInfo, key);
317 }
318
319 @Override
320 void postToHandler(Runnable r) {
321 final long token = mContext.injectClearCallingIdentity();
322 r.run();
323 mContext.injectRestoreCallingIdentity(token);
324 }
325
326 @Override
327 void injectEnforceCallingPermission(String permission, String message) {
328 if (!mCallerPermissions.contains(permission)) {
329 throw new SecurityException("Missing permission: " + permission);
330 }
331 }
332
333 @Override
334 void wtf(String message, Exception e) {
335 // During tests, WTF is fatal.
336 fail(message + " exception: " + e);
337 }
338 }
339
340 /** ShortcutManager with injection override methods. */
341 protected class ShortcutManagerTestable extends ShortcutManager {
342 public ShortcutManagerTestable(Context context, ShortcutServiceTestable service) {
343 super(context, service);
344 }
345
346 @Override
347 protected int injectMyUserId() {
348 return UserHandle.getUserId(mInjectedCallingUid);
349 }
350
351 @Override
352 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
353 // Note to simulate the binder RPC, we need to clone the incoming arguments.
354 // Otherwise bad things will happen because they're mutable.
355 return super.setDynamicShortcuts(cloneShortcutList(shortcutInfoList));
356 }
357
358 @Override
359 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
360 // Note to simulate the binder RPC, we need to clone the incoming arguments.
361 return super.addDynamicShortcuts(cloneShortcutList(shortcutInfoList));
362 }
363
364 @Override
365 public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
366 // Note to simulate the binder RPC, we need to clone the incoming arguments.
367 return super.updateShortcuts(cloneShortcutList(shortcutInfoList));
368 }
369 }
370
371 protected class LauncherAppImplTestable extends LauncherAppsImpl {
372 final ServiceContext mContext;
373
374 public LauncherAppImplTestable(ServiceContext context) {
375 super(context);
376 mContext = context;
377 }
378
379 @Override
380 public void verifyCallingPackage(String callingPackage) {
381 // SKIP
382 }
383
384 @Override
385 void postToPackageMonitorHandler(Runnable r) {
386 final long token = mContext.injectClearCallingIdentity();
387 r.run();
388 mContext.injectRestoreCallingIdentity(token);
389 }
390
391 @Override
392 int injectBinderCallingUid() {
393 return mInjectedCallingUid;
394 }
395
396 @Override
397 long injectClearCallingIdentity() {
398 final int prevCallingUid = mInjectedCallingUid;
399 mInjectedCallingUid = Process.SYSTEM_UID;
400 return prevCallingUid;
401 }
402
403 @Override
404 void injectRestoreCallingIdentity(long token) {
405 mInjectedCallingUid = (int) token;
406 }
407 }
408
409 protected class LauncherAppsTestable extends LauncherApps {
410 public LauncherAppsTestable(Context context, ILauncherApps service) {
411 super(context, service);
412 }
413 }
414
415 public static class ShortcutActivity extends Activity {
416 }
417
418 public static class ShortcutActivity2 extends Activity {
419 }
420
421 public static class ShortcutActivity3 extends Activity {
422 }
423
424 protected ServiceContext mServiceContext;
425 protected ClientContext mClientContext;
426
427 protected ShortcutServiceTestable mService;
428 protected ShortcutManagerTestable mManager;
429 protected ShortcutServiceInternal mInternal;
430
431 protected LauncherAppImplTestable mLauncherAppImpl;
432
433 // LauncherApps has per-instace state, so we need a differnt instance for each launcher.
434 protected final Map<Pair<Integer, String>, LauncherAppsTestable>
435 mLauncherAppsMap = new HashMap<>();
436 protected LauncherAppsTestable mLauncherApps; // Current one
437
438 protected File mInjectedFilePathRoot;
439
440 protected long mInjectedCurrentTimeMillis;
441
442 protected boolean mInjectedIsLowRamDevice;
443
444 protected int mInjectedCallingUid;
445 protected String mInjectedClientPackage;
446
447 protected Map<String, PackageInfo> mInjectedPackages;
448
449 protected Set<PackageWithUser> mUninstalledPackages;
450
451 protected PackageManager mMockPackageManager;
452 protected PackageManagerInternal mMockPackageManagerInternal;
453 protected UserManager mMockUserManager;
Makoto Onukiac042502016-05-20 16:39:42 -0700454 protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700455
456 protected static final String CALLING_PACKAGE_1 = "com.android.test.1";
457 protected static final int CALLING_UID_1 = 10001;
458
459 protected static final String CALLING_PACKAGE_2 = "com.android.test.2";
460 protected static final int CALLING_UID_2 = 10002;
461
462 protected static final String CALLING_PACKAGE_3 = "com.android.test.3";
463 protected static final int CALLING_UID_3 = 10003;
464
465 protected static final String CALLING_PACKAGE_4 = "com.android.test.4";
466 protected static final int CALLING_UID_4 = 10004;
467
468 protected static final String LAUNCHER_1 = "com.android.launcher.1";
469 protected static final int LAUNCHER_UID_1 = 10011;
470
471 protected static final String LAUNCHER_2 = "com.android.launcher.2";
472 protected static final int LAUNCHER_UID_2 = 10012;
473
474 protected static final String LAUNCHER_3 = "com.android.launcher.3";
475 protected static final int LAUNCHER_UID_3 = 10013;
476
477 protected static final String LAUNCHER_4 = "com.android.launcher.4";
478 protected static final int LAUNCHER_UID_4 = 10014;
479
480 protected static final int USER_0 = UserHandle.USER_SYSTEM;
481 protected static final int USER_10 = 10;
482 protected static final int USER_11 = 11;
483 protected static final int USER_P0 = 20; // profile of user 0
484
485 protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0);
486 protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10);
487 protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
488 protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
489
490 protected static final UserInfo USER_INFO_0 = withProfileGroupId(
491 new UserInfo(USER_0, "user0",
492 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 10);
493
494 protected static final UserInfo USER_INFO_10 =
495 new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED);
496
497 protected static final UserInfo USER_INFO_11 =
498 new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED);
499
500 protected static final UserInfo USER_INFO_P0 = withProfileGroupId(
501 new UserInfo(USER_P0, "userP0",
502 UserInfo.FLAG_MANAGED_PROFILE), 10);
503
504 protected BiPredicate<String, Integer> mDefaultLauncherChecker =
505 (callingPackage, userId) ->
506 LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
507 || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
508
509 protected static final long START_TIME = 1440000000101L;
510
511 protected static final long INTERVAL = 10000;
512
513 protected static final int MAX_SHORTCUTS = 10;
514
515 protected static final int MAX_UPDATES_PER_INTERVAL = 3;
516
517 protected static final int MAX_ICON_DIMENSION = 128;
518
519 protected static final int MAX_ICON_DIMENSION_LOWRAM = 32;
520
521 protected static final ShortcutQuery QUERY_ALL = new ShortcutQuery();
522
523 protected final ArrayList<String> mCallerPermissions = new ArrayList<>();
524
525 protected final HashMap<String, LinkedHashMap<ComponentName, Integer>> mActivityMetadataResId
526 = new HashMap<>();
527
528 static {
529 QUERY_ALL.setQueryFlags(
530 ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
531 }
532
533 @Override
534 protected void setUp() throws Exception {
535 super.setUp();
536
537 mServiceContext = spy(new ServiceContext());
538 mClientContext = new ClientContext();
539
540 mMockPackageManager = mock(PackageManager.class);
541 mMockPackageManagerInternal = mock(PackageManagerInternal.class);
542 mMockUserManager = mock(UserManager.class);
Makoto Onukiac042502016-05-20 16:39:42 -0700543 mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
544
545 LocalServices.removeServiceForTest(PackageManagerInternal.class);
546 LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
547 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
548 LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700549
550 // Prepare injection values.
551
552 mInjectedCurrentTimeMillis = START_TIME;
553
554 mInjectedPackages = new HashMap<>();
555 addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1);
556 addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 2);
557 addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 3);
558 addPackage(CALLING_PACKAGE_4, CALLING_UID_4, 10);
559 addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4);
560 addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5);
561 addPackage(LAUNCHER_3, LAUNCHER_UID_3, 6);
562 addPackage(LAUNCHER_4, LAUNCHER_UID_4, 10);
563
564 // CALLING_PACKAGE_3 / LAUNCHER_3 are not backup target.
565 updatePackageInfo(CALLING_PACKAGE_3,
566 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
567 updatePackageInfo(LAUNCHER_3,
568 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
569
570 mUninstalledPackages = new HashSet<>();
571
572 mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
573
574 deleteAllSavedFiles();
575
576 // Set up users.
577 doAnswer(inv -> {
578 assertSystem();
579 return USER_INFO_0;
580 }).when(mMockUserManager).getUserInfo(eq(USER_0));
581
582 doAnswer(inv -> {
583 assertSystem();
584 return USER_INFO_10;
585 }).when(mMockUserManager).getUserInfo(eq(USER_10));
586
587 doAnswer(inv -> {
588 assertSystem();
589 return USER_INFO_11;
590 }).when(mMockUserManager).getUserInfo(eq(USER_11));
591
592 doAnswer(inv -> {
593 assertSystem();
594 return USER_INFO_P0;
595 }).when(mMockUserManager).getUserInfo(eq(USER_P0));
596
597 // User 0 is always running.
598 when(mMockUserManager.isUserRunning(eq(USER_0))).thenAnswer(new AnswerIsUserRunning(true));
599
600 initService();
601 setCaller(CALLING_PACKAGE_1);
602
603 // In order to complicate the situation, we set mLocaleChangeSequenceNumber to 1 by
604 // calling this. Running test with mLocaleChangeSequenceNumber == 0 might make us miss
605 // some edge cases.
606 mInternal.onSystemLocaleChangedNoLock();
607 }
608
609 /**
610 * Returns a boolean but also checks if the current UID is SYSTEM_UID.
611 */
612 protected class AnswerIsUserRunning implements Answer<Boolean> {
613 protected final boolean mAnswer;
614
615 protected AnswerIsUserRunning(boolean answer) {
616 mAnswer = answer;
617 }
618
619 @Override
620 public Boolean answer(InvocationOnMock invocation) throws Throwable {
621 assertEquals("isUserRunning() must be called on SYSTEM UID.",
622 Process.SYSTEM_UID, mInjectedCallingUid);
623 return mAnswer;
624 }
625 }
626
627 protected static UserInfo withProfileGroupId(UserInfo in, int groupId) {
628 in.profileGroupId = groupId;
629 return in;
630 }
631
632 @Override
633 protected void tearDown() throws Exception {
634 if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown");
635
636 shutdownServices();
637
638 super.tearDown();
639 }
640
641 protected Context getTestContext() {
642 return getInstrumentation().getContext();
643 }
644
645 protected void deleteAllSavedFiles() {
646 // Empty the data directory.
647 if (mInjectedFilePathRoot.exists()) {
648 Assert.assertTrue("failed to delete dir",
649 FileUtils.deleteContents(mInjectedFilePathRoot));
650 }
651 mInjectedFilePathRoot.mkdirs();
652 }
653
654 /** (Re-) init the manager and the service. */
655 protected void initService() {
656 shutdownServices();
657
658 LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
659
660 // Instantiate targets.
661 mService = new ShortcutServiceTestable(mServiceContext, Looper.getMainLooper());
662 mManager = new ShortcutManagerTestable(mClientContext, mService);
663
664 mInternal = LocalServices.getService(ShortcutServiceInternal.class);
665
666 mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
667 mLauncherApps = null;
668 mLauncherAppsMap.clear();
669
670 // Load the setting file.
671 mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
672 }
673
674 protected void shutdownServices() {
675 if (mService != null) {
676 // Flush all the unsaved data from the previous instance.
677 mService.saveDirtyInfo();
678 }
679 LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
680
681 mService = null;
682 mManager = null;
683 mInternal = null;
684 mLauncherAppImpl = null;
685 mLauncherApps = null;
686 mLauncherAppsMap.clear();
687 }
688
689 protected void addPackage(String packageName, int uid, int version) {
690 addPackage(packageName, uid, version, packageName);
691 }
692
693 protected Signature[] genSignatures(String... signatures) {
694 final Signature[] sigs = new Signature[signatures.length];
695 for (int i = 0; i < signatures.length; i++){
696 sigs[i] = new Signature(signatures[i].getBytes());
697 }
698 return sigs;
699 }
700
701 protected PackageInfo genPackage(String packageName, int uid, int version, String... signatures) {
702 final PackageInfo pi = new PackageInfo();
703 pi.packageName = packageName;
704 pi.applicationInfo = new ApplicationInfo();
705 pi.applicationInfo.uid = uid;
706 pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED
707 | ApplicationInfo.FLAG_ALLOW_BACKUP;
708 pi.versionCode = version;
709 pi.applicationInfo.versionCode = version;
710 pi.signatures = genSignatures(signatures);
711
712 return pi;
713 }
714
715 protected void addPackage(String packageName, int uid, int version, String... signatures) {
716 mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures));
717 }
718
719 protected void updatePackageInfo(String packageName, Consumer<PackageInfo> c) {
720 c.accept(mInjectedPackages.get(packageName));
721 }
722
723 protected void updatePackageVersion(String packageName, int increment) {
724 updatePackageInfo(packageName, pi -> {
725 pi.versionCode += increment;
726 pi.applicationInfo.versionCode += increment;
727 });
728 }
729
730 protected void updatePackageLastUpdateTime(String packageName, long increment) {
731 updatePackageInfo(packageName, pi -> {
732 pi.lastUpdateTime += increment;
733 });
734 }
735
736 protected void uninstallPackage(int userId, String packageName) {
737 if (ENABLE_DUMP) {
738 Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
739 }
740 mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
741 }
742
743 protected void installPackage(int userId, String packageName) {
744 if (ENABLE_DUMP) {
745 Log.v(TAG, "Install package " + packageName + " / " + userId);
746 }
747 mUninstalledPackages.remove(PackageWithUser.of(userId, packageName));
748 }
749
750 PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
751 boolean getSignatures) {
752 final PackageInfo pi = mInjectedPackages.get(packageName);
753 if (pi == null) return null;
754
755 final PackageInfo ret = new PackageInfo();
756 ret.packageName = pi.packageName;
757 ret.versionCode = pi.versionCode;
758 ret.lastUpdateTime = pi.lastUpdateTime;
759
760 ret.applicationInfo = new ApplicationInfo(pi.applicationInfo);
761 ret.applicationInfo.uid = UserHandle.getUid(userId, pi.applicationInfo.uid);
762 ret.applicationInfo.packageName = pi.packageName;
763
764 if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) {
765 ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
766 }
767
768 if (getSignatures) {
769 ret.signatures = pi.signatures;
770 }
771
772 return ret;
773 }
774
775 protected void addApplicationInfo(PackageInfo pi, List<ApplicationInfo> list) {
776 if (pi != null && pi.applicationInfo != null) {
777 list.add(pi.applicationInfo);
778 }
779 }
780
781 protected List<ApplicationInfo> getInstalledApplications(int userId) {
782 final ArrayList<ApplicationInfo> ret = new ArrayList<>();
783
784 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret);
785 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret);
786 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret);
787 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret);
788 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret);
789 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret);
790 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret);
791 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret);
792
793 return ret;
794 }
795
796 protected void addManifestShortcutResource(ComponentName activity, int resId) {
797 final String packageName = activity.getPackageName();
798 LinkedHashMap<ComponentName, Integer> map = mActivityMetadataResId.get(packageName);
799 if (map == null) {
800 map = new LinkedHashMap<>();
801 mActivityMetadataResId.put(packageName, map);
802 }
803 map.put(activity, resId);
804 }
805
806 protected PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) {
807 final PackageInfo ret = getInjectedPackageInfo(packageName, userId,
808 /* getSignatures=*/ false);
809
810 final HashMap<ComponentName, Integer> activities = mActivityMetadataResId.get(packageName);
811 if (activities != null) {
812 final ArrayList<ActivityInfo> list = new ArrayList<>();
813
814 for (ComponentName cn : activities.keySet()) {
815 ActivityInfo ai = new ActivityInfo();
816 ai.packageName = cn.getPackageName();
817 ai.name = cn.getClassName();
818 ai.metaData = new Bundle();
819 ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn));
820 list.add(ai);
821 }
822 ret.activities = list.toArray(new ActivityInfo[list.size()]);
823 }
824 return ret;
825 }
826
827 protected XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
828 if (!ShortcutParser.METADATA_KEY.equals(key) || activityInfo.metaData == null) {
829 return null;
830 }
831 final int resId = activityInfo.metaData.getInt(key);
832 return getTestContext().getResources().getXml(resId);
833 }
834
835 /** Replace the current calling package */
836 protected void setCaller(String packageName, int userId) {
837 mInjectedClientPackage = packageName;
838 mInjectedCallingUid =
839 Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
840 "Unknown package").applicationInfo.uid;
841
842 // Set up LauncherApps for this caller.
843 final Pair<Integer, String> key = Pair.create(userId, packageName);
844 if (!mLauncherAppsMap.containsKey(key)) {
845 mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl));
846 }
847 mLauncherApps = mLauncherAppsMap.get(key);
848 }
849
850 protected void setCaller(String packageName) {
851 setCaller(packageName, UserHandle.USER_SYSTEM);
852 }
853
854 protected String getCallingPackage() {
855 return mInjectedClientPackage;
856 }
857
858 protected void setDefaultLauncherChecker(BiPredicate<String, Integer> p) {
859 mDefaultLauncherChecker = p;
860 }
861
862 protected void runWithCaller(String packageName, int userId, Runnable r) {
863 final String previousPackage = mInjectedClientPackage;
864 final int previousUserId = UserHandle.getUserId(mInjectedCallingUid);
865
866 setCaller(packageName, userId);
867
868 r.run();
869
870 setCaller(previousPackage, previousUserId);
871 }
872
873 protected int getCallingUserId() {
874 return UserHandle.getUserId(mInjectedCallingUid);
875 }
876
877 protected UserHandle getCallingUser() {
878 return UserHandle.of(getCallingUserId());
879 }
880
881 /** For debugging */
882 protected void dumpsysOnLogcat() {
883 dumpsysOnLogcat("");
884 }
885
886 protected void dumpsysOnLogcat(String message) {
887 dumpsysOnLogcat(message, false);
888 }
889
890 protected void dumpsysOnLogcat(String message, boolean force) {
891 if (force || !ENABLE_DUMP) return;
892
893 final ByteArrayOutputStream out = new ByteArrayOutputStream();
894 final PrintWriter pw = new PrintWriter(out);
895 mService.dumpInner(pw, null);
896 pw.close();
897
898 Log.v(TAG, "Dumping ShortcutService: " + message);
899 for (String line : out.toString().split("\n")) {
900 Log.v(TAG, line);
901 }
902 }
903
904 /**
905 * For debugging, dump arbitrary file on logcat.
906 */
907 protected void dumpFileOnLogcat(String path) {
908 dumpFileOnLogcat(path, "");
909 }
910
911 protected void dumpFileOnLogcat(String path, String message) {
912 if (!ENABLE_DUMP) return;
913
914 Log.v(TAG, "Dumping file: " + path + " " + message);
915 final StringBuilder sb = new StringBuilder();
916 try (BufferedReader br = new BufferedReader(new FileReader(path))) {
917 String line;
918 while ((line = br.readLine()) != null) {
919 Log.v(TAG, line);
920 }
921 } catch (Exception e) {
922 Log.e(TAG, "Couldn't read file", e);
923 fail("Exception " + e);
924 }
925 }
926
927 /**
928 * For debugging, dump the main state file on logcat.
929 */
930 protected void dumpBaseStateFile() {
931 mService.saveDirtyInfo();
932 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
933 + "/system/" + ShortcutService.FILENAME_BASE_STATE);
934 }
935
936 /**
937 * For debugging, dump per-user state file on logcat.
938 */
939 protected void dumpUserFile(int userId) {
940 dumpUserFile(userId, "");
941 }
942
943 protected void dumpUserFile(int userId, String message) {
944 mService.saveDirtyInfo();
945 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
946 + "/user-" + userId
947 + "/" + ShortcutService.FILENAME_USER_PACKAGES, message);
948 }
949
950 protected void waitOnMainThread() throws Throwable {
951 runTestOnUiThread(() -> {});
952 }
953
954 /**
955 * Make a shortcut with an ID.
956 */
957 protected ShortcutInfo makeShortcut(String id) {
958 return makeShortcut(
959 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
960 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
961 }
962
963 protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
964 return makeShortcut(
965 id, title, /* activity =*/ null, /* icon =*/ null,
966 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
967 }
968
969 /**
970 * Make a shortcut with an ID and timestamp.
971 */
972 protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
973 final ShortcutInfo s = makeShortcut(
974 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
975 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
976 s.setTimestamp(timestamp);
977 return s;
978 }
979
980 /**
981 * Make a shortcut with an ID, a timestamp and an activity component
982 */
983 protected ShortcutInfo makeShortcutWithTimestampWithActivity(String id, long timestamp,
984 ComponentName activity) {
985 final ShortcutInfo s = makeShortcut(
986 id, "Title-" + id, activity, /* icon =*/ null,
987 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
988 s.setTimestamp(timestamp);
989 return s;
990 }
991
992 /**
993 * Make a shortcut with an ID and icon.
994 */
995 protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
996 return makeShortcut(
997 id, "Title-" + id, /* activity =*/ null, icon,
998 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
999 }
1000
1001 protected ShortcutInfo makePackageShortcut(String packageName, String id) {
1002 String origCaller = getCallingPackage();
1003
1004 setCaller(packageName);
1005 ShortcutInfo s = makeShortcut(
1006 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1007 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1008 setCaller(origCaller); // restore the caller
1009
1010 return s;
1011 }
1012
1013 /**
1014 * Make multiple shortcuts with IDs.
1015 */
1016 protected List<ShortcutInfo> makeShortcuts(String... ids) {
1017 final ArrayList<ShortcutInfo> ret = new ArrayList();
1018 for (String id : ids) {
1019 ret.add(makeShortcut(id));
1020 }
1021 return ret;
1022 }
1023
1024 protected ShortcutInfo.Builder makeShortcutBuilder() {
1025 return new ShortcutInfo.Builder(mClientContext);
1026 }
1027
1028 protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
1029 return makeShortcut(
1030 id, "Title-" + id, activity, /* icon =*/ null,
1031 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1032 }
1033
1034 protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
1035 String title) {
1036 return makeShortcut(
1037 id, title, activity, /* icon =*/ null,
1038 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1039 }
1040
1041 protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
1042 int rank) {
1043 return makeShortcut(
1044 id, "Title-" + id, activity, /* icon =*/ null,
1045 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
1046 }
1047
1048 /**
1049 * Make a shortcut with details.
1050 */
1051 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
1052 Icon icon, Intent intent, int rank) {
1053 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext)
1054 .setId(id)
1055 .setActivity(new ComponentName(mClientContext.getPackageName(), "dummy"))
1056 .setTitle(title)
1057 .setRank(rank)
1058 .setIntent(intent);
1059 if (icon != null) {
1060 b.setIcon(icon);
1061 }
1062 if (activity != null) {
1063 b.setActivity(activity);
1064 }
1065 final ShortcutInfo s = b.build();
1066
1067 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
1068
1069 return s;
1070 }
1071
1072 /**
1073 * Make an intent.
1074 */
1075 protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
1076 final Intent intent = new Intent(action);
1077 intent.setComponent(makeComponent(clazz));
1078 intent.replaceExtras(makeBundle(bundleKeysAndValues));
1079 return intent;
1080 }
1081
1082 /**
1083 * Make an component name, with the client context.
1084 */
1085 @NonNull
1086 protected ComponentName makeComponent(Class<?> clazz) {
1087 return new ComponentName(mClientContext, clazz);
1088 }
1089
1090 @NonNull
1091 protected ShortcutInfo findById(List<ShortcutInfo> list, String id) {
1092 for (ShortcutInfo s : list) {
1093 if (s.getId().equals(id)) {
1094 return s;
1095 }
1096 }
1097 fail("Shortcut with id " + id + " not found");
1098 return null;
1099 }
1100
1101 protected void assertSystem() {
1102 assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid);
1103 }
1104
1105 protected void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) {
1106 assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked());
1107 assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
1108 }
1109
1110 public static List<ShortcutInfo> assertAllNotHaveIcon(
1111 List<ShortcutInfo> actualShortcuts) {
1112 for (ShortcutInfo s : actualShortcuts) {
1113 assertNull("ID " + s.getId(), s.getIcon());
1114 }
1115 return actualShortcuts;
1116 }
1117
1118 @NonNull
1119 protected List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
1120 int shortcutFlags) {
1121 for (ShortcutInfo s : actualShortcuts) {
1122 assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags,
1123 s.hasFlags(shortcutFlags));
1124 }
1125 return actualShortcuts;
1126 }
1127
1128 protected ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
1129 return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
1130 }
1131
1132 protected void assertShortcutExists(String packageName, String shortcutId, int userId) {
1133 assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null);
1134 }
1135
1136 protected void assertShortcutNotExists(String packageName, String shortcutId, int userId) {
1137 assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null);
1138 }
1139
1140 protected Intent launchShortcutAndGetIntent(
1141 @NonNull String packageName, @NonNull String shortcutId, int userId) {
1142 reset(mServiceContext);
1143 assertTrue(mLauncherApps.startShortcut(packageName, shortcutId, null, null,
1144 UserHandle.of(userId)));
1145
1146 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
1147 verify(mServiceContext).startActivityAsUser(
1148 intentCaptor.capture(),
1149 any(Bundle.class),
1150 eq(UserHandle.of(userId)));
1151 return intentCaptor.getValue();
1152 }
1153
1154 protected Intent launchShortcutAndGetIntent_withShortcutInfo(
1155 @NonNull String packageName, @NonNull String shortcutId, int userId) {
1156 reset(mServiceContext);
1157
1158 assertTrue(mLauncherApps.startShortcut(
1159 getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null));
1160
1161 final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
1162 verify(mServiceContext).startActivityAsUser(
1163 intentCaptor.capture(),
1164 any(Bundle.class),
1165 eq(UserHandle.of(userId)));
1166 return intentCaptor.getValue();
1167 }
1168
1169 protected void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
1170 int userId) {
1171 assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
1172 assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId));
1173 }
1174
1175 protected void assertShortcutNotLaunchable(@NonNull String packageName,
1176 @NonNull String shortcutId, int userId) {
1177 try {
1178 final boolean ok = mLauncherApps.startShortcut(packageName, shortcutId, null, null,
1179 UserHandle.of(userId));
1180 if (!ok) {
1181 return; // didn't launch, okay.
1182 }
1183 fail();
1184 } catch (SecurityException expected) {
1185 // security exception is okay too.
1186 }
1187 }
1188
1189 protected void assertBitmapDirectories(int userId, String... expectedDirectories) {
1190 final Set<String> expected = hashSet(set(expectedDirectories));
1191
1192 final Set<String> actual = new HashSet<>();
1193
1194 final File[] files = mService.getUserBitmapFilePath(userId).listFiles();
1195 if (files != null) {
1196 for (File child : files) {
1197 if (child.isDirectory()) {
1198 actual.add(child.getName());
1199 }
1200 }
1201 }
1202
1203 assertEquals(expected, actual);
1204 }
1205
1206 protected void assertBitmapFiles(int userId, String packageName, String... expectedFiles) {
1207 final Set<String> expected = hashSet(set(expectedFiles));
1208
1209 final Set<String> actual = new HashSet<>();
1210
1211 final File[] files = new File(mService.getUserBitmapFilePath(userId), packageName)
1212 .listFiles();
1213 if (files != null) {
1214 for (File child : files) {
1215 if (child.isFile()) {
1216 actual.add(child.getName());
1217 }
1218 }
1219 }
1220
1221 assertEquals(expected, actual);
1222 }
1223
1224 protected String getBitmapFilename(int userId, String packageName, String shortcutId) {
1225 final ShortcutInfo si = mService.getPackageShortcutForTest(packageName, shortcutId, userId);
1226 if (si == null) {
1227 return null;
1228 }
1229 return new File(si.getBitmapPath()).getName();
1230 }
1231
1232 protected List<ShortcutInfo> getCallerShortcuts() {
1233 final ShortcutPackage p = mService.getPackageShortcutForTest(
1234 getCallingPackage(), getCallingUserId());
1235 return p == null ? null : p.getAllShortcutsForTest();
1236 }
1237
1238 protected ShortcutInfo getCallerShortcut(String shortcutId) {
1239 return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
1240 }
1241
1242 protected List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) {
1243 final List<ShortcutInfo>[] ret = new List[1];
1244 runWithCaller(launcher, userId, () -> {
1245 final ShortcutQuery q = new ShortcutQuery();
1246 q.setQueryFlags(queryFlags);
1247 ret[0] = mLauncherApps.getShortcuts(q, UserHandle.of(userId));
1248 });
1249 return ret[0];
1250 }
1251
1252 protected List<ShortcutInfo> getLauncherPinnedShortcuts(String launcher, int userId) {
1253 return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
1254 }
1255
1256 protected ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId,
1257 int userId) {
1258 final List<ShortcutInfo> infoList =
1259 mLauncherApps.getShortcutInfo(packageName, list(shortcutId),
1260 UserHandle.of(userId));
1261 assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size());
1262 return infoList.get(0);
1263 }
1264
1265 protected Intent genPackageAddIntent(String pakcageName, int userId) {
1266 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
1267 i.setData(Uri.parse("package:" + pakcageName));
1268 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1269 return i;
1270 }
1271
1272 protected Intent genPackageDeleteIntent(String pakcageName, int userId) {
1273 Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
1274 i.setData(Uri.parse("package:" + pakcageName));
1275 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1276 return i;
1277 }
1278
1279 protected Intent genPackageUpdateIntent(String pakcageName, int userId) {
1280 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
1281 i.setData(Uri.parse("package:" + pakcageName));
1282 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1283 i.putExtra(Intent.EXTRA_REPLACING, true);
1284 return i;
1285 }
1286
1287 protected Intent genPackageDataClear(String packageName, int userId) {
1288 Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED);
1289 i.setData(Uri.parse("package:" + packageName));
1290 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1291 return i;
1292 }
1293
1294 protected void assertExistsAndShadow(ShortcutPackageItem spi) {
1295 assertNotNull(spi);
1296 assertTrue(spi.getPackageInfo().isShadow());
1297 }
1298
1299 protected File makeFile(File baseDirectory, String... paths) {
1300 File ret = baseDirectory;
1301
1302 for (String path : paths) {
1303 ret = new File(ret, path);
1304 }
1305
1306 return ret;
1307 }
1308
1309 protected boolean bitmapDirectoryExists(String packageName, int userId) {
1310 final File path = new File(mService.getUserBitmapFilePath(userId), packageName);
1311 return path.isDirectory();
1312 }
1313 protected static ShortcutQuery buildQuery(long changedSince,
1314 String packageName, ComponentName componentName,
1315 /* @ShortcutQuery.QueryFlags */ int flags) {
1316 return buildQuery(changedSince, packageName, null, componentName, flags);
1317 }
1318
1319 protected static ShortcutQuery buildQuery(long changedSince,
1320 String packageName, List<String> shortcutIds, ComponentName componentName,
1321 /* @ShortcutQuery.QueryFlags */ int flags) {
1322 final ShortcutQuery q = new ShortcutQuery();
1323 q.setChangedSince(changedSince);
1324 q.setPackage(packageName);
1325 q.setShortcutIds(shortcutIds);
1326 q.setActivity(componentName);
1327 q.setQueryFlags(flags);
1328 return q;
1329 }
1330
1331 protected static ShortcutQuery buildAllQuery(String packageName) {
1332 final ShortcutQuery q = new ShortcutQuery();
1333 q.setPackage(packageName);
1334 q.setQueryFlags(ShortcutQuery.FLAG_GET_DYNAMIC | ShortcutQuery.FLAG_GET_PINNED);
1335 return q;
1336 }
1337
1338 protected static ShortcutQuery buildPinnedQuery(String packageName) {
1339 final ShortcutQuery q = new ShortcutQuery();
1340 q.setPackage(packageName);
1341 q.setQueryFlags(ShortcutQuery.FLAG_GET_PINNED);
1342 return q;
1343 }
1344
1345 protected void backupAndRestore() {
1346 int prevUid = mInjectedCallingUid;
1347
1348 mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it.
1349
1350 dumpsysOnLogcat("Before backup");
1351
1352 final byte[] payload = mService.getBackupPayload(USER_0);
1353 if (ENABLE_DUMP) {
1354 final String xml = new String(payload);
1355 Log.v(TAG, "Backup payload:");
1356 for (String line : xml.split("\n")) {
1357 Log.v(TAG, line);
1358 }
1359 }
1360
1361 // Before doing anything else, uninstall all packages.
1362 for (int userId : list(USER_0, USER_P0)) {
1363 for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
1364 LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) {
1365 uninstallPackage(userId, pkg);
1366 }
1367 }
1368
1369 shutdownServices();
1370
1371 deleteAllSavedFiles();
1372
1373 initService();
1374 mService.applyRestore(payload, USER_0);
1375
1376 // handleUnlockUser will perform the gone package check, but it shouldn't remove
1377 // shadow information.
1378 mService.handleUnlockUser(USER_0);
1379
1380 dumpsysOnLogcat("After restore");
1381
1382 mInjectedCallingUid = prevUid;
1383 }
1384
1385 protected void prepareCrossProfileDataSet() {
1386 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1387 assertTrue(mManager.setDynamicShortcuts(list(
1388 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1389 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1390 });
1391 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1392 assertTrue(mManager.setDynamicShortcuts(list(
1393 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1394 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1395 });
1396 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1397 assertTrue(mManager.setDynamicShortcuts(list(
1398 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1399 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1400 });
1401 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1402 assertTrue(mManager.setDynamicShortcuts(list()));
1403 });
1404 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1405 assertTrue(mManager.setDynamicShortcuts(list(
1406 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1407 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1408 });
1409 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1410 assertTrue(mManager.setDynamicShortcuts(list(
1411 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"),
1412 makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6"))));
1413 });
1414
1415 runWithCaller(LAUNCHER_1, USER_0, () -> {
1416 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
1417 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0);
1418 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0);
1419
1420 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0);
1421 });
1422 runWithCaller(LAUNCHER_2, USER_0, () -> {
1423 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
1424 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0);
1425 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0);
1426
1427 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
1428 });
1429 runWithCaller(LAUNCHER_3, USER_0, () -> {
1430 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
1431 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
1432 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0);
1433
1434 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0);
1435 });
1436 runWithCaller(LAUNCHER_4, USER_0, () -> {
1437 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0);
1438 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0);
1439 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0);
1440 mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0);
1441 });
1442
1443 // Launcher on a managed profile is referring ot user 0!
1444 runWithCaller(LAUNCHER_1, USER_P0, () -> {
1445 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0);
1446 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0);
1447 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"),
1448 HANDLE_USER_0);
1449
1450 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0);
1451 });
1452 runWithCaller(LAUNCHER_1, USER_10, () -> {
1453 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10);
1454 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10);
1455 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"),
1456 HANDLE_USER_10);
1457 });
1458
1459 // Then remove some dynamic shortcuts.
1460 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1461 assertTrue(mManager.setDynamicShortcuts(list(
1462 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1463 });
1464 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1465 assertTrue(mManager.setDynamicShortcuts(list(
1466 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1467 });
1468 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1469 assertTrue(mManager.setDynamicShortcuts(list(
1470 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1471 });
1472 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1473 assertTrue(mManager.setDynamicShortcuts(list()));
1474 });
1475 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1476 assertTrue(mManager.setDynamicShortcuts(list(
1477 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1478 });
1479 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1480 assertTrue(mManager.setDynamicShortcuts(list(
1481 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
1482 });
1483 }
1484}