blob: f2bd1184db15af9da1d99cdd87e2dcc0a1232e0f [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;
Makoto Onuki157b1622016-06-02 16:13:10 -070025import static org.mockito.Matchers.anyInt;
26import static org.mockito.Matchers.anyString;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070027import static org.mockito.Matchers.eq;
28import static org.mockito.Mockito.doAnswer;
29import static org.mockito.Mockito.mock;
30import static org.mockito.Mockito.reset;
31import static org.mockito.Mockito.spy;
Makoto Onukiff14f732016-06-30 17:07:25 -070032import static org.mockito.Mockito.times;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070033import static org.mockito.Mockito.verify;
34import static org.mockito.Mockito.when;
35
36import android.annotation.NonNull;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070037import android.annotation.UserIdInt;
38import android.app.Activity;
Makoto Onuki33525d22016-08-03 15:45:24 -070039import android.app.ActivityManager;
Makoto Onukiea11db12016-06-24 15:17:44 -070040import android.app.ActivityManagerInternal;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070041import android.app.IUidObserver;
Makoto Onukiac042502016-05-20 16:39:42 -070042import android.app.usage.UsageStatsManagerInternal;
Makoto Onuki440a1ea2016-07-20 14:21:18 -070043import android.content.ActivityNotFoundException;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070044import android.content.BroadcastReceiver;
45import android.content.ComponentName;
46import android.content.Context;
47import android.content.Intent;
48import android.content.IntentFilter;
Makoto Onuki2d895c32016-12-02 15:48:40 -080049import android.content.IntentSender;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070050import android.content.pm.ActivityInfo;
51import android.content.pm.ApplicationInfo;
52import android.content.pm.ILauncherApps;
53import android.content.pm.LauncherApps;
54import android.content.pm.LauncherApps.ShortcutQuery;
55import android.content.pm.PackageInfo;
56import android.content.pm.PackageManager;
57import android.content.pm.PackageManagerInternal;
Makoto Onukib08790c2016-06-23 14:05:46 -070058import android.content.pm.ResolveInfo;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070059import android.content.pm.ShortcutInfo;
60import android.content.pm.ShortcutManager;
61import android.content.pm.ShortcutServiceInternal;
62import android.content.pm.Signature;
63import android.content.pm.UserInfo;
64import android.content.res.Resources;
65import android.content.res.XmlResourceParser;
66import android.graphics.drawable.Icon;
67import android.net.Uri;
68import android.os.Bundle;
69import android.os.FileUtils;
70import android.os.Handler;
71import android.os.Looper;
Makoto Onukib5a012f2016-06-21 11:13:53 -070072import android.os.PersistableBundle;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070073import android.os.Process;
Makoto Onukia01f4f02016-12-15 15:58:41 -080074import android.os.RemoteException;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070075import android.os.UserHandle;
76import android.os.UserManager;
77import android.test.InstrumentationTestCase;
78import android.test.mock.MockContext;
Makoto Onuki2d895c32016-12-02 15:48:40 -080079import android.util.ArrayMap;
Makoto Onuki51ab2b32016-06-02 11:03:51 -070080import android.util.Log;
81import android.util.Pair;
82
83import com.android.internal.util.Preconditions;
84import com.android.server.LocalServices;
85import com.android.server.SystemService;
86import com.android.server.pm.LauncherAppsService.LauncherAppsImpl;
87import com.android.server.pm.ShortcutUser.PackageWithUser;
88
89import org.junit.Assert;
90import org.mockito.ArgumentCaptor;
91import org.mockito.invocation.InvocationOnMock;
92import org.mockito.stubbing.Answer;
93
94import java.io.BufferedReader;
95import java.io.ByteArrayOutputStream;
96import java.io.File;
97import java.io.FileReader;
Makoto Onuki76269922016-07-15 14:58:54 -070098import java.io.IOException;
99import java.io.InputStreamReader;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700100import java.io.PrintWriter;
101import java.util.ArrayList;
102import java.util.HashMap;
103import java.util.HashSet;
104import java.util.LinkedHashMap;
105import java.util.List;
Makoto Onuki157b1622016-06-02 16:13:10 -0700106import java.util.Locale;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700107import java.util.Map;
108import java.util.Set;
Makoto Onukib08790c2016-06-23 14:05:46 -0700109import java.util.function.BiFunction;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700110import java.util.function.BiPredicate;
111import java.util.function.Consumer;
Makoto Onukia2241832016-07-06 13:28:37 -0700112import java.util.function.Function;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700113
114public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
115 protected static final String TAG = "ShortcutManagerTest";
116
Makoto Onuki4e6cef42016-07-13 16:14:01 -0700117 protected static final boolean DUMP_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
118
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700119 /**
120 * Whether to enable dump or not. Should be only true when debugging to avoid bugs where
121 * dump affecting the behavior.
122 */
Makoto Onuki4e6cef42016-07-13 16:14:01 -0700123 protected static final boolean ENABLE_DUMP = false // DO NOT SUBMIT WITH true
124 || DUMP_IN_TEARDOWN || ShortcutService.DEBUG;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700125
126 protected static final String[] EMPTY_STRINGS = new String[0]; // Just for readability.
127
Makoto Onukib08790c2016-06-23 14:05:46 -0700128 protected static final String MAIN_ACTIVITY_CLASS = "MainActivity";
Makoto Onuki2d895c32016-12-02 15:48:40 -0800129 protected static final String PIN_CONFIRM_ACTIVITY_CLASS = "PinConfirmActivity";
Makoto Onukib08790c2016-06-23 14:05:46 -0700130
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700131 // public for mockito
132 public class BaseContext extends MockContext {
133 @Override
134 public Object getSystemService(String name) {
135 switch (name) {
136 case Context.USER_SERVICE:
137 return mMockUserManager;
138 }
139 throw new UnsupportedOperationException();
140 }
141
142 @Override
143 public String getSystemServiceName(Class<?> serviceClass) {
144 return getTestContext().getSystemServiceName(serviceClass);
145 }
146
147 @Override
148 public PackageManager getPackageManager() {
149 return mMockPackageManager;
150 }
151
152 @Override
153 public Resources getResources() {
154 return getTestContext().getResources();
155 }
156
157 @Override
158 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
159 IntentFilter filter, String broadcastPermission, Handler scheduler) {
160 // ignore.
161 return null;
162 }
Makoto Onuki4e6cef42016-07-13 16:14:01 -0700163
164 @Override
165 public void unregisterReceiver(BroadcastReceiver receiver) {
166 // ignore.
167 }
Makoto Onuki2d895c32016-12-02 15:48:40 -0800168
169 @Override
170 public void startActivityAsUser(Intent intent, UserHandle user) {
171 // ignore, use spy to intercept it.
172 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700173 }
174
175 /** Context used in the client side */
176 public class ClientContext extends BaseContext {
177 @Override
178 public String getPackageName() {
179 return mInjectedClientPackage;
180 }
181
182 @Override
183 public int getUserId() {
184 return getCallingUserId();
185 }
186 }
187
188 /** Context used in the service side */
189 public class ServiceContext extends BaseContext {
190 long injectClearCallingIdentity() {
191 final int prevCallingUid = mInjectedCallingUid;
192 mInjectedCallingUid = Process.SYSTEM_UID;
193 return prevCallingUid;
194 }
195
196 void injectRestoreCallingIdentity(long token) {
197 mInjectedCallingUid = (int) token;
198 }
199
200 @Override
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700201 public int getUserId() {
202 return UserHandle.USER_SYSTEM;
203 }
204
205 public PackageInfo injectGetActivitiesWithMetadata(
206 String packageName, @UserIdInt int userId) {
207 return BaseShortcutManagerTest.this.injectGetActivitiesWithMetadata(packageName, userId);
208 }
209
210 public XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
211 return BaseShortcutManagerTest.this.injectXmlMetaData(activityInfo, key);
212 }
Makoto Onuki2d895c32016-12-02 15:48:40 -0800213
214 public void sendIntentSender(IntentSender intent) {
215 // Placeholder for spying.
216 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700217 }
218
219 /** ShortcutService with injection override methods. */
220 protected final class ShortcutServiceTestable extends ShortcutService {
221 final ServiceContext mContext;
222 IUidObserver mUidObserver;
223
224 public ShortcutServiceTestable(ServiceContext context, Looper looper) {
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700225 super(context, looper, /* onyForPackageManagerApis */ false);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700226 mContext = context;
227 }
228
229 @Override
Makoto Onuki4e6cef42016-07-13 16:14:01 -0700230 public String injectGetLocaleTagsForUser(@UserIdInt int userId) {
231 return mInjectedLocale.toLanguageTag();
232 }
233
234 @Override
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700235 boolean injectShouldPerformVerification() {
236 return true; // Always verify during unit tests.
237 }
238
239 @Override
240 String injectShortcutManagerConstants() {
241 return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + ","
242 + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + ","
243 + ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "="
244 + MAX_UPDATES_PER_INTERVAL + ","
245 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + ","
246 + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "="
247 + MAX_ICON_DIMENSION_LOWRAM + ","
248 + ConfigConstants.KEY_ICON_FORMAT + "=PNG,"
249 + ConfigConstants.KEY_ICON_QUALITY + "=100";
250 }
251
252 @Override
253 long injectClearCallingIdentity() {
254 return mContext.injectClearCallingIdentity();
255 }
256
257 @Override
258 void injectRestoreCallingIdentity(long token) {
259 mContext.injectRestoreCallingIdentity(token);
260 }
261
262 @Override
263 int injectDipToPixel(int dip) {
264 return dip;
265 }
266
267 @Override
268 long injectCurrentTimeMillis() {
269 return mInjectedCurrentTimeMillis;
270 }
271
272 @Override
273 long injectElapsedRealtime() {
274 // TODO This should be kept separately from mInjectedCurrentTimeMillis, since
275 // this should increase even if we rewind mInjectedCurrentTimeMillis in some tests.
276 return mInjectedCurrentTimeMillis - START_TIME;
277 }
278
279 @Override
280 int injectBinderCallingUid() {
281 return mInjectedCallingUid;
282 }
283
284 @Override
285 int injectGetPackageUid(String packageName, int userId) {
286 return getInjectedPackageInfo(packageName, userId, false).applicationInfo.uid;
287 }
288
289 @Override
290 File injectSystemDataPath() {
291 return new File(mInjectedFilePathRoot, "system");
292 }
293
294 @Override
295 File injectUserDataPath(@UserIdInt int userId) {
296 return new File(mInjectedFilePathRoot, "user-" + userId);
297 }
298
299 @Override
300 void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) {
301 // Can't check
302 }
303
304 @Override
305 boolean injectIsLowRamDevice() {
306 return mInjectedIsLowRamDevice;
307 }
308
309 @Override
310 void injectRegisterUidObserver(IUidObserver observer, int which) {
311 mUidObserver = observer;
312 }
313
314 @Override
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700315 boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
316 return mDefaultLauncherChecker.test(callingPackage, userId);
317 }
318
319 @Override
Makoto Onuki2d895c32016-12-02 15:48:40 -0800320 ComponentName getDefaultLauncher(@UserIdInt int userId) {
321 final ComponentName activity = mDefaultLauncher.get(userId);
322 if (activity != null) {
323 return activity;
324 }
325 return super.getDefaultLauncher(userId);
326 }
327
328 @Override
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700329 PackageInfo injectPackageInfoWithUninstalled(String packageName, @UserIdInt int userId,
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700330 boolean getSignatures) {
331 return getInjectedPackageInfo(packageName, userId, getSignatures);
332 }
333
334 @Override
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700335 ApplicationInfo injectApplicationInfoWithUninstalled(
336 String packageName, @UserIdInt int userId) {
337 PackageInfo pi = injectPackageInfoWithUninstalled(
338 packageName, userId, /* getSignatures= */ false);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700339 return pi != null ? pi.applicationInfo : null;
340 }
341
342 @Override
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700343 List<PackageInfo> injectGetPackagesWithUninstalled(@UserIdInt int userId) {
344 return BaseShortcutManagerTest.this.getInstalledPackagesWithUninstalled(userId);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700345 }
346
347 @Override
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700348 ActivityInfo injectGetActivityInfoWithMetadataWithUninstalled(ComponentName activity,
Makoto Onukib08790c2016-06-23 14:05:46 -0700349 @UserIdInt int userId) {
350 final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
351 activity.getPackageName(), userId);
352 if (pi == null || pi.activities == null) {
353 return null;
354 }
355 for (ActivityInfo ai : pi.activities) {
356 if (!mEnabledActivityChecker.test(ai.getComponentName(), userId)) {
357 continue;
358 }
359 if (activity.equals(ai.getComponentName())) {
360 return ai;
361 }
362 }
363 return null;
364 }
365
366 @Override
367 boolean injectIsMainActivity(@NonNull ComponentName activity, int userId) {
368 if (!mEnabledActivityChecker.test(activity, userId)) {
369 return false;
370 }
371 return mMainActivityChecker.test(activity, userId);
372 }
373
374 @Override
375 List<ResolveInfo> injectGetMainActivities(@NonNull String packageName, int userId) {
376 final PackageInfo pi = mContext.injectGetActivitiesWithMetadata(
377 packageName, userId);
378 if (pi == null || pi.activities == null) {
379 return null;
380 }
381 final ArrayList<ResolveInfo> ret = new ArrayList<>(pi.activities.length);
382 for (int i = 0; i < pi.activities.length; i++) {
383 if (!mEnabledActivityChecker.test(pi.activities[i].getComponentName(), userId)) {
384 continue;
385 }
386 final ResolveInfo ri = new ResolveInfo();
387 ri.activityInfo = pi.activities[i];
388 ret.add(ri);
389 }
390
391 return ret;
392 }
393
394 @Override
395 ComponentName injectGetDefaultMainActivity(@NonNull String packageName, int userId) {
396 return mMainActivityFetcher.apply(packageName, userId);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700397 }
398
399 @Override
Makoto Onuki2d895c32016-12-02 15:48:40 -0800400 ComponentName injectGetPinConfirmationActivity(@NonNull String launcherPackageName,
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800401 int launcherUserId, int requestType) {
Makoto Onuki2d895c32016-12-02 15:48:40 -0800402 return mPinConfirmActivityFetcher.apply(launcherPackageName, launcherUserId);
403 }
404
405 @Override
Makoto Onukiee6b6e42016-06-29 17:34:02 -0700406 boolean injectIsActivityEnabledAndExported(ComponentName activity, @UserIdInt int userId) {
407 return mEnabledActivityChecker.test(activity, userId);
408 }
409
410 @Override
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700411 XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
412 return mContext.injectXmlMetaData(activityInfo, key);
413 }
414
415 @Override
Makoto Onuki157b1622016-06-02 16:13:10 -0700416 void injectPostToHandler(Runnable r) {
Makoto Onukia2241832016-07-06 13:28:37 -0700417 runOnHandler(r);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700418 }
419
420 @Override
Makoto Onuki085a05c2016-08-19 11:39:29 -0700421 void injectRunOnNewThread(Runnable r) {
422 runOnHandler(r);
423 }
424
425 @Override
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700426 void injectEnforceCallingPermission(String permission, String message) {
427 if (!mCallerPermissions.contains(permission)) {
428 throw new SecurityException("Missing permission: " + permission);
429 }
430 }
431
432 @Override
Makoto Onukib08790c2016-06-23 14:05:46 -0700433 boolean injectIsSafeModeEnabled() {
434 return mSafeMode;
435 }
436
437 @Override
Makoto Onuki33663282016-08-22 16:19:04 -0700438 String injectBuildFingerprint() {
439 return mInjectedBuildFingerprint;
440 }
441
442 @Override
Sunny Goyal87a563e2017-01-01 19:42:45 -0800443 void injectSendIntentSender(IntentSender intent, Intent extras) {
Makoto Onuki2d895c32016-12-02 15:48:40 -0800444 mContext.sendIntentSender(intent);
445 }
446
447 @Override
Makoto Onukia2241832016-07-06 13:28:37 -0700448 void wtf(String message, Throwable th) {
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700449 // During tests, WTF is fatal.
Makoto Onukia2241832016-07-06 13:28:37 -0700450 fail(message + " exception: " + th + "\n" + Log.getStackTraceString(th));
451 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700452 }
453
454 /** ShortcutManager with injection override methods. */
455 protected class ShortcutManagerTestable extends ShortcutManager {
456 public ShortcutManagerTestable(Context context, ShortcutServiceTestable service) {
457 super(context, service);
458 }
459
460 @Override
461 protected int injectMyUserId() {
462 return UserHandle.getUserId(mInjectedCallingUid);
463 }
464
465 @Override
466 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
467 // Note to simulate the binder RPC, we need to clone the incoming arguments.
468 // Otherwise bad things will happen because they're mutable.
469 return super.setDynamicShortcuts(cloneShortcutList(shortcutInfoList));
470 }
471
472 @Override
473 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
474 // Note to simulate the binder RPC, we need to clone the incoming arguments.
475 return super.addDynamicShortcuts(cloneShortcutList(shortcutInfoList));
476 }
477
478 @Override
479 public boolean updateShortcuts(List<ShortcutInfo> shortcutInfoList) {
480 // Note to simulate the binder RPC, we need to clone the incoming arguments.
481 return super.updateShortcuts(cloneShortcutList(shortcutInfoList));
482 }
483 }
484
485 protected class LauncherAppImplTestable extends LauncherAppsImpl {
486 final ServiceContext mContext;
487
488 public LauncherAppImplTestable(ServiceContext context) {
489 super(context);
490 mContext = context;
491 }
492
493 @Override
494 public void verifyCallingPackage(String callingPackage) {
495 // SKIP
496 }
497
498 @Override
499 void postToPackageMonitorHandler(Runnable r) {
Makoto Onukia2241832016-07-06 13:28:37 -0700500 runOnHandler(r);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700501 }
502
503 @Override
504 int injectBinderCallingUid() {
505 return mInjectedCallingUid;
506 }
507
508 @Override
509 long injectClearCallingIdentity() {
510 final int prevCallingUid = mInjectedCallingUid;
511 mInjectedCallingUid = Process.SYSTEM_UID;
512 return prevCallingUid;
513 }
514
515 @Override
516 void injectRestoreCallingIdentity(long token) {
517 mInjectedCallingUid = (int) token;
518 }
519 }
520
521 protected class LauncherAppsTestable extends LauncherApps {
522 public LauncherAppsTestable(Context context, ILauncherApps service) {
523 super(context, service);
524 }
525 }
526
527 public static class ShortcutActivity extends Activity {
528 }
529
530 public static class ShortcutActivity2 extends Activity {
531 }
532
533 public static class ShortcutActivity3 extends Activity {
534 }
535
Makoto Onukia2241832016-07-06 13:28:37 -0700536 protected Looper mLooper;
537 protected Handler mHandler;
538
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700539 protected ServiceContext mServiceContext;
540 protected ClientContext mClientContext;
541
542 protected ShortcutServiceTestable mService;
543 protected ShortcutManagerTestable mManager;
544 protected ShortcutServiceInternal mInternal;
545
546 protected LauncherAppImplTestable mLauncherAppImpl;
547
548 // LauncherApps has per-instace state, so we need a differnt instance for each launcher.
549 protected final Map<Pair<Integer, String>, LauncherAppsTestable>
550 mLauncherAppsMap = new HashMap<>();
551 protected LauncherAppsTestable mLauncherApps; // Current one
552
553 protected File mInjectedFilePathRoot;
554
Makoto Onukib08790c2016-06-23 14:05:46 -0700555 protected boolean mSafeMode;
556
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700557 protected long mInjectedCurrentTimeMillis;
558
559 protected boolean mInjectedIsLowRamDevice;
560
Makoto Onuki157b1622016-06-02 16:13:10 -0700561 protected Locale mInjectedLocale = Locale.ENGLISH;
562
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700563 protected int mInjectedCallingUid;
564 protected String mInjectedClientPackage;
565
566 protected Map<String, PackageInfo> mInjectedPackages;
567
568 protected Set<PackageWithUser> mUninstalledPackages;
Makoto Onuki33663282016-08-22 16:19:04 -0700569 protected Set<String> mSystemPackages;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700570
571 protected PackageManager mMockPackageManager;
572 protected PackageManagerInternal mMockPackageManagerInternal;
573 protected UserManager mMockUserManager;
Makoto Onukiac042502016-05-20 16:39:42 -0700574 protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
Makoto Onukiea11db12016-06-24 15:17:44 -0700575 protected ActivityManagerInternal mMockActivityManagerInternal;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700576
577 protected static final String CALLING_PACKAGE_1 = "com.android.test.1";
578 protected static final int CALLING_UID_1 = 10001;
579
580 protected static final String CALLING_PACKAGE_2 = "com.android.test.2";
581 protected static final int CALLING_UID_2 = 10002;
582
583 protected static final String CALLING_PACKAGE_3 = "com.android.test.3";
584 protected static final int CALLING_UID_3 = 10003;
585
586 protected static final String CALLING_PACKAGE_4 = "com.android.test.4";
587 protected static final int CALLING_UID_4 = 10004;
588
589 protected static final String LAUNCHER_1 = "com.android.launcher.1";
590 protected static final int LAUNCHER_UID_1 = 10011;
591
592 protected static final String LAUNCHER_2 = "com.android.launcher.2";
593 protected static final int LAUNCHER_UID_2 = 10012;
594
595 protected static final String LAUNCHER_3 = "com.android.launcher.3";
596 protected static final int LAUNCHER_UID_3 = 10013;
597
598 protected static final String LAUNCHER_4 = "com.android.launcher.4";
599 protected static final int LAUNCHER_UID_4 = 10014;
600
601 protected static final int USER_0 = UserHandle.USER_SYSTEM;
602 protected static final int USER_10 = 10;
603 protected static final int USER_11 = 11;
604 protected static final int USER_P0 = 20; // profile of user 0
605
606 protected static final UserHandle HANDLE_USER_0 = UserHandle.of(USER_0);
607 protected static final UserHandle HANDLE_USER_10 = UserHandle.of(USER_10);
608 protected static final UserHandle HANDLE_USER_11 = UserHandle.of(USER_11);
609 protected static final UserHandle HANDLE_USER_P0 = UserHandle.of(USER_P0);
610
611 protected static final UserInfo USER_INFO_0 = withProfileGroupId(
612 new UserInfo(USER_0, "user0",
Makoto Onuki2d895c32016-12-02 15:48:40 -0800613 UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY | UserInfo.FLAG_INITIALIZED), 0);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700614
615 protected static final UserInfo USER_INFO_10 =
616 new UserInfo(USER_10, "user10", UserInfo.FLAG_INITIALIZED);
617
618 protected static final UserInfo USER_INFO_11 =
619 new UserInfo(USER_11, "user11", UserInfo.FLAG_INITIALIZED);
620
Makoto Onukiaecbd032017-01-19 12:11:11 -0800621 /*
622 * Cheat: USER_P0 is a sub profile of USER_0, but it doesn't have the MANAGED_PROFILE flag set.
623 * Due to a change made to LauncherApps (b/34340531), work profile apps a no longer able
624 * to see the main profile, which would break tons of unit tests. We avoid it by not setting
625 * MANAGED_PROFILE for P0.
626 * We cover this negative case in CTS. (i.e. CTS has tests to make sure maanged profile
627 * can't access main profile's shortcuts.)
628 */
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700629 protected static final UserInfo USER_INFO_P0 = withProfileGroupId(
Makoto Onukiaecbd032017-01-19 12:11:11 -0800630 new UserInfo(USER_P0, "userP0", UserInfo.FLAG_INITIALIZED), 0);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700631
632 protected BiPredicate<String, Integer> mDefaultLauncherChecker =
633 (callingPackage, userId) ->
634 LAUNCHER_1.equals(callingPackage) || LAUNCHER_2.equals(callingPackage)
635 || LAUNCHER_3.equals(callingPackage) || LAUNCHER_4.equals(callingPackage);
636
Makoto Onuki2d895c32016-12-02 15:48:40 -0800637 private final Map<Integer, ComponentName> mDefaultLauncher = new ArrayMap<>();
638
Makoto Onukib08790c2016-06-23 14:05:46 -0700639 protected BiPredicate<ComponentName, Integer> mMainActivityChecker =
640 (activity, userId) -> true;
641
642 protected BiFunction<String, Integer, ComponentName> mMainActivityFetcher =
643 (packageName, userId) -> new ComponentName(packageName, MAIN_ACTIVITY_CLASS);
644
Makoto Onuki2d895c32016-12-02 15:48:40 -0800645 protected BiFunction<String, Integer, ComponentName> mPinConfirmActivityFetcher =
646 (packageName, userId) -> new ComponentName(packageName, PIN_CONFIRM_ACTIVITY_CLASS);
647
Makoto Onukib08790c2016-06-23 14:05:46 -0700648 protected BiPredicate<ComponentName, Integer> mEnabledActivityChecker
649 = (activity, userId) -> true; // all activities are enabled.
650
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700651 protected static final long START_TIME = 1440000000101L;
652
653 protected static final long INTERVAL = 10000;
654
655 protected static final int MAX_SHORTCUTS = 10;
656
657 protected static final int MAX_UPDATES_PER_INTERVAL = 3;
658
659 protected static final int MAX_ICON_DIMENSION = 128;
660
661 protected static final int MAX_ICON_DIMENSION_LOWRAM = 32;
662
663 protected static final ShortcutQuery QUERY_ALL = new ShortcutQuery();
664
665 protected final ArrayList<String> mCallerPermissions = new ArrayList<>();
666
667 protected final HashMap<String, LinkedHashMap<ComponentName, Integer>> mActivityMetadataResId
668 = new HashMap<>();
669
Makoto Onukia2241832016-07-06 13:28:37 -0700670 protected final Map<Integer, UserInfo> mUserInfos = new HashMap<>();
671 protected final Map<Integer, Boolean> mRunningUsers = new HashMap<>();
672 protected final Map<Integer, Boolean> mUnlockedUsers = new HashMap<>();
673
Makoto Onuki0b9d1db2016-07-18 14:16:41 -0700674 protected static final String PACKAGE_SYSTEM_LAUNCHER = "com.android.systemlauncher";
675 protected static final String PACKAGE_SYSTEM_LAUNCHER_NAME = "systemlauncher_name";
676 protected static final int PACKAGE_SYSTEM_LAUNCHER_PRIORITY = 0;
677
678 protected static final String PACKAGE_FALLBACK_LAUNCHER = "com.android.settings";
679 protected static final String PACKAGE_FALLBACK_LAUNCHER_NAME = "fallback";
680 protected static final int PACKAGE_FALLBACK_LAUNCHER_PRIORITY = -999;
681
Makoto Onuki33663282016-08-22 16:19:04 -0700682 protected String mInjectedBuildFingerprint = "build1";
683
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700684 static {
685 QUERY_ALL.setQueryFlags(
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700686 ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700687 }
688
689 @Override
690 protected void setUp() throws Exception {
691 super.setUp();
692
Makoto Onukia2241832016-07-06 13:28:37 -0700693 mLooper = Looper.getMainLooper();
694 mHandler = new Handler(mLooper);
695
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700696 mServiceContext = spy(new ServiceContext());
697 mClientContext = new ClientContext();
698
699 mMockPackageManager = mock(PackageManager.class);
700 mMockPackageManagerInternal = mock(PackageManagerInternal.class);
701 mMockUserManager = mock(UserManager.class);
Makoto Onukiac042502016-05-20 16:39:42 -0700702 mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
Makoto Onukiea11db12016-06-24 15:17:44 -0700703 mMockActivityManagerInternal = mock(ActivityManagerInternal.class);
Makoto Onukiac042502016-05-20 16:39:42 -0700704
705 LocalServices.removeServiceForTest(PackageManagerInternal.class);
706 LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
707 LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
708 LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal);
Makoto Onukiea11db12016-06-24 15:17:44 -0700709 LocalServices.removeServiceForTest(ActivityManagerInternal.class);
710 LocalServices.addService(ActivityManagerInternal.class, mMockActivityManagerInternal);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700711
712 // Prepare injection values.
713
714 mInjectedCurrentTimeMillis = START_TIME;
715
716 mInjectedPackages = new HashMap<>();
717 addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 1);
718 addPackage(CALLING_PACKAGE_2, CALLING_UID_2, 2);
719 addPackage(CALLING_PACKAGE_3, CALLING_UID_3, 3);
720 addPackage(CALLING_PACKAGE_4, CALLING_UID_4, 10);
721 addPackage(LAUNCHER_1, LAUNCHER_UID_1, 4);
722 addPackage(LAUNCHER_2, LAUNCHER_UID_2, 5);
723 addPackage(LAUNCHER_3, LAUNCHER_UID_3, 6);
724 addPackage(LAUNCHER_4, LAUNCHER_UID_4, 10);
725
726 // CALLING_PACKAGE_3 / LAUNCHER_3 are not backup target.
727 updatePackageInfo(CALLING_PACKAGE_3,
728 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
729 updatePackageInfo(LAUNCHER_3,
730 pi -> pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_ALLOW_BACKUP);
731
732 mUninstalledPackages = new HashSet<>();
Makoto Onuki33663282016-08-22 16:19:04 -0700733 mSystemPackages = new HashSet<>();
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700734
735 mInjectedFilePathRoot = new File(getTestContext().getCacheDir(), "test-files");
736
737 deleteAllSavedFiles();
738
739 // Set up users.
Makoto Onukia2241832016-07-06 13:28:37 -0700740 when(mMockUserManager.getUserInfo(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
741 inv -> mUserInfos.get((Integer) inv.getArguments()[0])));
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700742
Makoto Onukia2241832016-07-06 13:28:37 -0700743 mUserInfos.put(USER_0, USER_INFO_0);
744 mUserInfos.put(USER_10, USER_INFO_10);
745 mUserInfos.put(USER_11, USER_INFO_11);
746 mUserInfos.put(USER_P0, USER_INFO_P0);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700747
Makoto Onukia2241832016-07-06 13:28:37 -0700748 // Set up isUserRunning and isUserUnlocked.
749 when(mMockUserManager.isUserRunning(anyInt())).thenAnswer(new AnswerWithSystemCheck<>(
Makoto Onuki9c850012016-07-26 15:50:50 -0700750 inv -> b(mRunningUsers.get((Integer) inv.getArguments()[0]))));
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700751
Makoto Onuki9c850012016-07-26 15:50:50 -0700752 when(mMockUserManager.isUserUnlocked(anyInt()))
753 .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
754 final int userId = (Integer) inv.getArguments()[0];
755 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
756 }));
757 // isUserUnlockingOrUnlocked() return the same value as isUserUnlocked().
758 when(mMockUserManager.isUserUnlockingOrUnlocked(anyInt()))
759 .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
760 final int userId = (Integer) inv.getArguments()[0];
761 return b(mRunningUsers.get(userId)) && b(mUnlockedUsers.get(userId));
762 }));
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700763
Makoto Onuki2d895c32016-12-02 15:48:40 -0800764 when(mMockUserManager.getProfileParent(anyInt()))
765 .thenAnswer(new AnswerWithSystemCheck<>(inv -> {
766 final int userId = (Integer) inv.getArguments()[0];
767 final UserInfo ui = mUserInfos.get(userId);
768 assertNotNull(ui);
769 if (ui.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID) {
770 return null;
771 }
772 final UserInfo parent = mUserInfos.get(ui.profileGroupId);
773 assertNotNull(parent);
774 return parent;
775 }));
776
Makoto Onuki33525d22016-08-03 15:45:24 -0700777 when(mMockActivityManagerInternal.getUidProcessState(anyInt())).thenReturn(
778 ActivityManager.PROCESS_STATE_CACHED_EMPTY);
779
Makoto Onuki9c850012016-07-26 15:50:50 -0700780 // User 0 and P0 are always running
Makoto Onukia2241832016-07-06 13:28:37 -0700781 mRunningUsers.put(USER_0, true);
782 mRunningUsers.put(USER_10, false);
783 mRunningUsers.put(USER_11, false);
Makoto Onuki9c850012016-07-26 15:50:50 -0700784 mRunningUsers.put(USER_P0, true);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700785
Makoto Onukia2241832016-07-06 13:28:37 -0700786 // Unlock all users by default.
787 mUnlockedUsers.put(USER_0, true);
788 mUnlockedUsers.put(USER_10, true);
789 mUnlockedUsers.put(USER_11, true);
790 mUnlockedUsers.put(USER_P0, true);
791
792 // Set up resources
Makoto Onuki157b1622016-06-02 16:13:10 -0700793 setUpAppResources();
794
795 // Start the service.
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700796 initService();
797 setCaller(CALLING_PACKAGE_1);
Makoto Onuki248a0ef2016-11-03 15:59:01 -0700798
799 if (ENABLE_DUMP) {
800 Log.d(TAG, "setUp done");
801 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700802 }
803
Makoto Onuki9c850012016-07-26 15:50:50 -0700804 private static boolean b(Boolean value) {
805 return (value != null && value);
806 }
807
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700808 /**
809 * Returns a boolean but also checks if the current UID is SYSTEM_UID.
810 */
Makoto Onukia2241832016-07-06 13:28:37 -0700811 protected class AnswerWithSystemCheck<T> implements Answer<T> {
812 private final Function<InvocationOnMock, T> mChecker;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700813
Makoto Onukia2241832016-07-06 13:28:37 -0700814 public AnswerWithSystemCheck(Function<InvocationOnMock, T> checker) {
815 mChecker = checker;
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700816 }
817
818 @Override
Makoto Onukia2241832016-07-06 13:28:37 -0700819 public T answer(InvocationOnMock invocation) throws Throwable {
820 assertEquals("Must be called on SYSTEM UID.",
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700821 Process.SYSTEM_UID, mInjectedCallingUid);
Makoto Onukia2241832016-07-06 13:28:37 -0700822 return mChecker.apply(invocation);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700823 }
824 }
825
Makoto Onuki157b1622016-06-02 16:13:10 -0700826 protected void setUpAppResources() throws Exception {
827 setUpAppResources(/* offset = */ 0);
828 }
829
830 protected void setUpAppResources(int ressIdOffset) throws Exception {
831 // ressIdOffset is used to adjust resource IDs to emulate the case where an updated app
832 // has resource IDs changed.
833
834 doAnswer(pmInvocation -> {
835 assertEquals(Process.SYSTEM_UID, mInjectedCallingUid);
836
837 final String packageName = (String) pmInvocation.getArguments()[0];
838 final int userId = (Integer) pmInvocation.getArguments()[1];
839
840 final Resources res = mock(Resources.class);
841
842 doAnswer(resInvocation -> {
843 final int argResId = (Integer) resInvocation.getArguments()[0];
844
845 return "string-" + packageName + "-user:" + userId + "-res:" + argResId
846 + "/" + mInjectedLocale;
847 }).when(res).getString(anyInt());
848
849 doAnswer(resInvocation -> {
850 final int resId = (Integer) resInvocation.getArguments()[0];
851
852 // Always use the "string" resource type. The type doesn't matter during the test.
853 return packageName + ":string/r" + resId;
854 }).when(res).getResourceName(anyInt());
855
856 doAnswer(resInvocation -> {
857 final String argResName = (String) resInvocation.getArguments()[0];
858 final String argType = (String) resInvocation.getArguments()[1];
859 final String argPackageName = (String) resInvocation.getArguments()[2];
860
861 // See the above code. getResourceName() will just use "r" + res ID as the entry
862 // name.
863 String entryName = argResName;
864 if (entryName.contains("/")) {
865 entryName = ShortcutInfo.getResourceEntryName(entryName);
866 }
867 return Integer.parseInt(entryName.substring(1)) + ressIdOffset;
868 }).when(res).getIdentifier(anyString(), anyString(), anyString());
869 return res;
870 }).when(mMockPackageManager).getResourcesForApplicationAsUser(anyString(), anyInt());
871 }
872
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700873 protected static UserInfo withProfileGroupId(UserInfo in, int groupId) {
874 in.profileGroupId = groupId;
875 return in;
876 }
877
878 @Override
879 protected void tearDown() throws Exception {
880 if (DUMP_IN_TEARDOWN) dumpsysOnLogcat("Teardown");
881
882 shutdownServices();
883
884 super.tearDown();
885 }
886
887 protected Context getTestContext() {
888 return getInstrumentation().getContext();
889 }
890
Makoto Onukia1d38b32016-06-10 15:32:26 -0700891 protected ShortcutManager getManager() {
892 return mManager;
893 }
894
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700895 protected void deleteAllSavedFiles() {
896 // Empty the data directory.
897 if (mInjectedFilePathRoot.exists()) {
898 Assert.assertTrue("failed to delete dir",
899 FileUtils.deleteContents(mInjectedFilePathRoot));
900 }
901 mInjectedFilePathRoot.mkdirs();
902 }
903
904 /** (Re-) init the manager and the service. */
905 protected void initService() {
906 shutdownServices();
907
908 LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
909
910 // Instantiate targets.
Makoto Onukia2241832016-07-06 13:28:37 -0700911 mService = new ShortcutServiceTestable(mServiceContext, mLooper);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700912 mManager = new ShortcutManagerTestable(mClientContext, mService);
913
914 mInternal = LocalServices.getService(ShortcutServiceInternal.class);
915
916 mLauncherAppImpl = new LauncherAppImplTestable(mServiceContext);
917 mLauncherApps = null;
918 mLauncherAppsMap.clear();
919
Makoto Onuki157b1622016-06-02 16:13:10 -0700920 // Send boot sequence events.
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700921 mService.onBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
Makoto Onuki157b1622016-06-02 16:13:10 -0700922
Makoto Onuki157b1622016-06-02 16:13:10 -0700923 mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700924 }
925
926 protected void shutdownServices() {
927 if (mService != null) {
928 // Flush all the unsaved data from the previous instance.
929 mService.saveDirtyInfo();
Makoto Onuki9e1f5592016-06-08 12:30:23 -0700930
931 // Make sure everything is consistent.
932 mService.verifyStates();
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700933 }
934 LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
935
936 mService = null;
937 mManager = null;
938 mInternal = null;
939 mLauncherAppImpl = null;
940 mLauncherApps = null;
941 mLauncherAppsMap.clear();
942 }
943
Makoto Onukia2241832016-07-06 13:28:37 -0700944 protected void runOnHandler(Runnable r) {
945 final long token = mServiceContext.injectClearCallingIdentity();
946 try {
947 r.run();
948 } finally {
949 mServiceContext.injectRestoreCallingIdentity(token);
950 }
951 }
952
Makoto Onuki51ab2b32016-06-02 11:03:51 -0700953 protected void addPackage(String packageName, int uid, int version) {
954 addPackage(packageName, uid, version, packageName);
955 }
956
957 protected Signature[] genSignatures(String... signatures) {
958 final Signature[] sigs = new Signature[signatures.length];
959 for (int i = 0; i < signatures.length; i++){
960 sigs[i] = new Signature(signatures[i].getBytes());
961 }
962 return sigs;
963 }
964
965 protected PackageInfo genPackage(String packageName, int uid, int version, String... signatures) {
966 final PackageInfo pi = new PackageInfo();
967 pi.packageName = packageName;
968 pi.applicationInfo = new ApplicationInfo();
969 pi.applicationInfo.uid = uid;
970 pi.applicationInfo.flags = ApplicationInfo.FLAG_INSTALLED
971 | ApplicationInfo.FLAG_ALLOW_BACKUP;
972 pi.versionCode = version;
973 pi.applicationInfo.versionCode = version;
974 pi.signatures = genSignatures(signatures);
975
976 return pi;
977 }
978
979 protected void addPackage(String packageName, int uid, int version, String... signatures) {
980 mInjectedPackages.put(packageName, genPackage(packageName, uid, version, signatures));
981 }
982
983 protected void updatePackageInfo(String packageName, Consumer<PackageInfo> c) {
984 c.accept(mInjectedPackages.get(packageName));
985 }
986
987 protected void updatePackageVersion(String packageName, int increment) {
988 updatePackageInfo(packageName, pi -> {
989 pi.versionCode += increment;
990 pi.applicationInfo.versionCode += increment;
991 });
992 }
993
994 protected void updatePackageLastUpdateTime(String packageName, long increment) {
995 updatePackageInfo(packageName, pi -> {
996 pi.lastUpdateTime += increment;
997 });
998 }
999
Makoto Onuki085a05c2016-08-19 11:39:29 -07001000 protected void setPackageLastUpdateTime(String packageName, long value) {
1001 updatePackageInfo(packageName, pi -> {
1002 pi.lastUpdateTime = value;
1003 });
1004 }
1005
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001006 protected void uninstallPackage(int userId, String packageName) {
1007 if (ENABLE_DUMP) {
1008 Log.v(TAG, "Unnstall package " + packageName + " / " + userId);
1009 }
1010 mUninstalledPackages.add(PackageWithUser.of(userId, packageName));
1011 }
1012
1013 protected void installPackage(int userId, String packageName) {
1014 if (ENABLE_DUMP) {
1015 Log.v(TAG, "Install package " + packageName + " / " + userId);
1016 }
1017 mUninstalledPackages.remove(PackageWithUser.of(userId, packageName));
1018 }
1019
1020 PackageInfo getInjectedPackageInfo(String packageName, @UserIdInt int userId,
1021 boolean getSignatures) {
1022 final PackageInfo pi = mInjectedPackages.get(packageName);
1023 if (pi == null) return null;
1024
1025 final PackageInfo ret = new PackageInfo();
1026 ret.packageName = pi.packageName;
1027 ret.versionCode = pi.versionCode;
1028 ret.lastUpdateTime = pi.lastUpdateTime;
1029
1030 ret.applicationInfo = new ApplicationInfo(pi.applicationInfo);
1031 ret.applicationInfo.uid = UserHandle.getUid(userId, pi.applicationInfo.uid);
1032 ret.applicationInfo.packageName = pi.packageName;
1033
1034 if (mUninstalledPackages.contains(PackageWithUser.of(userId, packageName))) {
1035 ret.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
1036 }
Makoto Onuki33663282016-08-22 16:19:04 -07001037 if (mSystemPackages.contains(packageName)) {
1038 ret.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
1039 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001040
1041 if (getSignatures) {
1042 ret.signatures = pi.signatures;
1043 }
1044
1045 return ret;
1046 }
1047
1048 protected void addApplicationInfo(PackageInfo pi, List<ApplicationInfo> list) {
1049 if (pi != null && pi.applicationInfo != null) {
1050 list.add(pi.applicationInfo);
1051 }
1052 }
1053
1054 protected List<ApplicationInfo> getInstalledApplications(int userId) {
1055 final ArrayList<ApplicationInfo> ret = new ArrayList<>();
1056
1057 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret);
1058 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret);
1059 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret);
1060 addApplicationInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret);
1061 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret);
1062 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret);
1063 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret);
1064 addApplicationInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret);
1065
1066 return ret;
1067 }
1068
Makoto Onuki6dd9fb72016-06-01 13:55:54 -07001069 private void addPackageInfo(PackageInfo pi, List<PackageInfo> list) {
1070 if (pi != null) {
1071 list.add(pi);
1072 }
1073 }
1074
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001075 private List<PackageInfo> getInstalledPackagesWithUninstalled(int userId) {
Makoto Onuki6dd9fb72016-06-01 13:55:54 -07001076 final ArrayList<PackageInfo> ret = new ArrayList<>();
1077
1078 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_1, userId, false), ret);
1079 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_2, userId, false), ret);
1080 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_3, userId, false), ret);
1081 addPackageInfo(getInjectedPackageInfo(CALLING_PACKAGE_4, userId, false), ret);
1082 addPackageInfo(getInjectedPackageInfo(LAUNCHER_1, userId, false), ret);
1083 addPackageInfo(getInjectedPackageInfo(LAUNCHER_2, userId, false), ret);
1084 addPackageInfo(getInjectedPackageInfo(LAUNCHER_3, userId, false), ret);
1085 addPackageInfo(getInjectedPackageInfo(LAUNCHER_4, userId, false), ret);
1086
1087 return ret;
1088 }
1089
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001090 protected void addManifestShortcutResource(ComponentName activity, int resId) {
1091 final String packageName = activity.getPackageName();
1092 LinkedHashMap<ComponentName, Integer> map = mActivityMetadataResId.get(packageName);
1093 if (map == null) {
1094 map = new LinkedHashMap<>();
1095 mActivityMetadataResId.put(packageName, map);
1096 }
1097 map.put(activity, resId);
1098 }
1099
1100 protected PackageInfo injectGetActivitiesWithMetadata(String packageName, @UserIdInt int userId) {
1101 final PackageInfo ret = getInjectedPackageInfo(packageName, userId,
1102 /* getSignatures=*/ false);
1103
1104 final HashMap<ComponentName, Integer> activities = mActivityMetadataResId.get(packageName);
1105 if (activities != null) {
1106 final ArrayList<ActivityInfo> list = new ArrayList<>();
1107
1108 for (ComponentName cn : activities.keySet()) {
1109 ActivityInfo ai = new ActivityInfo();
1110 ai.packageName = cn.getPackageName();
1111 ai.name = cn.getClassName();
1112 ai.metaData = new Bundle();
1113 ai.metaData.putInt(ShortcutParser.METADATA_KEY, activities.get(cn));
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001114 ai.applicationInfo = ret.applicationInfo;
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001115 list.add(ai);
1116 }
1117 ret.activities = list.toArray(new ActivityInfo[list.size()]);
1118 }
1119 return ret;
1120 }
1121
1122 protected XmlResourceParser injectXmlMetaData(ActivityInfo activityInfo, String key) {
1123 if (!ShortcutParser.METADATA_KEY.equals(key) || activityInfo.metaData == null) {
1124 return null;
1125 }
1126 final int resId = activityInfo.metaData.getInt(key);
1127 return getTestContext().getResources().getXml(resId);
1128 }
1129
1130 /** Replace the current calling package */
1131 protected void setCaller(String packageName, int userId) {
1132 mInjectedClientPackage = packageName;
1133 mInjectedCallingUid =
1134 Preconditions.checkNotNull(getInjectedPackageInfo(packageName, userId, false),
1135 "Unknown package").applicationInfo.uid;
1136
1137 // Set up LauncherApps for this caller.
1138 final Pair<Integer, String> key = Pair.create(userId, packageName);
1139 if (!mLauncherAppsMap.containsKey(key)) {
1140 mLauncherAppsMap.put(key, new LauncherAppsTestable(mClientContext, mLauncherAppImpl));
1141 }
1142 mLauncherApps = mLauncherAppsMap.get(key);
1143 }
1144
1145 protected void setCaller(String packageName) {
1146 setCaller(packageName, UserHandle.USER_SYSTEM);
1147 }
1148
1149 protected String getCallingPackage() {
1150 return mInjectedClientPackage;
1151 }
1152
Makoto Onuki2d895c32016-12-02 15:48:40 -08001153 /**
1154 * This controls {@link ShortcutService#hasShortcutHostPermission(String, int)}, but
1155 * not {@link ShortcutService#getDefaultLauncher(int)}. To control the later, use
1156 * {@link #setDefaultLauncher(int, ComponentName)}.
1157 */
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001158 protected void setDefaultLauncherChecker(BiPredicate<String, Integer> p) {
1159 mDefaultLauncherChecker = p;
1160 }
1161
Makoto Onuki2d895c32016-12-02 15:48:40 -08001162 /**
1163 * Set the default launcher. This will update {@link #mDefaultLauncherChecker} set by
1164 * {@link #setDefaultLauncherChecker} too.
1165 */
1166 protected void setDefaultLauncher(int userId, ComponentName launcherActivity) {
1167 mDefaultLauncher.put(userId, launcherActivity);
1168
1169 final BiPredicate<String, Integer> oldChecker = mDefaultLauncherChecker;
1170 mDefaultLauncherChecker = (checkPackageName, checkUserId) -> {
1171 if ((checkUserId == userId) && (launcherActivity != null)) {
1172 return launcherActivity.getPackageName().equals(checkPackageName);
1173 }
1174 return oldChecker.test(checkPackageName, checkUserId);
1175 };
1176 }
1177
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001178 protected void runWithCaller(String packageName, int userId, Runnable r) {
1179 final String previousPackage = mInjectedClientPackage;
1180 final int previousUserId = UserHandle.getUserId(mInjectedCallingUid);
1181
1182 setCaller(packageName, userId);
1183
1184 r.run();
1185
1186 setCaller(previousPackage, previousUserId);
1187 }
1188
Makoto Onuki157b1622016-06-02 16:13:10 -07001189 protected void runWithSystemUid(Runnable r) {
1190 final int origUid = mInjectedCallingUid;
1191 mInjectedCallingUid = Process.SYSTEM_UID;
1192 r.run();
1193 mInjectedCallingUid = origUid;
1194 }
1195
1196 protected void lookupAndFillInResourceNames(ShortcutInfo si) {
1197 runWithSystemUid(() -> si.lookupAndFillInResourceNames(
1198 mService.injectGetResourcesForApplicationAsUser(si.getPackage(), si.getUserId())));
1199 }
1200
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001201 protected int getCallingUserId() {
1202 return UserHandle.getUserId(mInjectedCallingUid);
1203 }
1204
1205 protected UserHandle getCallingUser() {
1206 return UserHandle.of(getCallingUserId());
1207 }
1208
1209 /** For debugging */
1210 protected void dumpsysOnLogcat() {
1211 dumpsysOnLogcat("");
1212 }
1213
1214 protected void dumpsysOnLogcat(String message) {
1215 dumpsysOnLogcat(message, false);
1216 }
1217
1218 protected void dumpsysOnLogcat(String message, boolean force) {
1219 if (force || !ENABLE_DUMP) return;
1220
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001221 Log.v(TAG, "Dumping ShortcutService: " + message);
Makoto Onuki76269922016-07-15 14:58:54 -07001222 for (String line : dumpsys(null).split("\n")) {
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001223 Log.v(TAG, line);
1224 }
1225 }
1226
Makoto Onuki76269922016-07-15 14:58:54 -07001227 protected String dumpCheckin() {
1228 return dumpsys(new String[]{"--checkin"});
1229 }
1230
1231 private String dumpsys(String[] args) {
1232 final ArrayList<String> origPermissions = new ArrayList<>(mCallerPermissions);
1233 mCallerPermissions.add(android.Manifest.permission.DUMP);
1234 try {
1235 final ByteArrayOutputStream out = new ByteArrayOutputStream();
1236 final PrintWriter pw = new PrintWriter(out);
1237 mService.dump(/* fd */ null, pw, args);
1238 pw.close();
1239
1240 return out.toString();
1241 } finally {
1242 mCallerPermissions.clear();
1243 mCallerPermissions.addAll(origPermissions);
1244 }
1245 }
1246
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001247 /**
1248 * For debugging, dump arbitrary file on logcat.
1249 */
1250 protected void dumpFileOnLogcat(String path) {
1251 dumpFileOnLogcat(path, "");
1252 }
1253
1254 protected void dumpFileOnLogcat(String path, String message) {
1255 if (!ENABLE_DUMP) return;
1256
1257 Log.v(TAG, "Dumping file: " + path + " " + message);
1258 final StringBuilder sb = new StringBuilder();
1259 try (BufferedReader br = new BufferedReader(new FileReader(path))) {
1260 String line;
1261 while ((line = br.readLine()) != null) {
1262 Log.v(TAG, line);
1263 }
1264 } catch (Exception e) {
1265 Log.e(TAG, "Couldn't read file", e);
1266 fail("Exception " + e);
1267 }
1268 }
1269
1270 /**
1271 * For debugging, dump the main state file on logcat.
1272 */
1273 protected void dumpBaseStateFile() {
1274 mService.saveDirtyInfo();
1275 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
1276 + "/system/" + ShortcutService.FILENAME_BASE_STATE);
1277 }
1278
1279 /**
1280 * For debugging, dump per-user state file on logcat.
1281 */
1282 protected void dumpUserFile(int userId) {
1283 dumpUserFile(userId, "");
1284 }
1285
1286 protected void dumpUserFile(int userId, String message) {
1287 mService.saveDirtyInfo();
1288 dumpFileOnLogcat(mInjectedFilePathRoot.getAbsolutePath()
1289 + "/user-" + userId
1290 + "/" + ShortcutService.FILENAME_USER_PACKAGES, message);
1291 }
1292
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001293 /**
Makoto Onukia01f4f02016-12-15 15:58:41 -08001294 * Make a shortcut with an ID only.
1295 */
1296 protected ShortcutInfo makeShortcutIdOnly(String id) {
1297 return new ShortcutInfo.Builder(mClientContext, id).build();
1298 }
1299
1300 /**
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001301 * Make a shortcut with an ID.
1302 */
1303 protected ShortcutInfo makeShortcut(String id) {
1304 return makeShortcut(
1305 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1306 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1307 }
1308
Makoto Onukia01f4f02016-12-15 15:58:41 -08001309 @Deprecated // Title was renamed to short label.
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001310 protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
1311 return makeShortcut(
1312 id, title, /* activity =*/ null, /* icon =*/ null,
1313 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1314 }
1315
Makoto Onukia01f4f02016-12-15 15:58:41 -08001316 protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
1317 return makeShortcut(
1318 id, shortLabel, /* activity =*/ null, /* icon =*/ null,
1319 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1320 }
1321
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001322 /**
1323 * Make a shortcut with an ID and timestamp.
1324 */
1325 protected ShortcutInfo makeShortcutWithTimestamp(String id, long timestamp) {
1326 final ShortcutInfo s = makeShortcut(
1327 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1328 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1329 s.setTimestamp(timestamp);
1330 return s;
1331 }
1332
1333 /**
1334 * Make a shortcut with an ID, a timestamp and an activity component
1335 */
1336 protected ShortcutInfo makeShortcutWithTimestampWithActivity(String id, long timestamp,
1337 ComponentName activity) {
1338 final ShortcutInfo s = makeShortcut(
1339 id, "Title-" + id, activity, /* icon =*/ null,
1340 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1341 s.setTimestamp(timestamp);
1342 return s;
1343 }
1344
1345 /**
1346 * Make a shortcut with an ID and icon.
1347 */
1348 protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
1349 return makeShortcut(
1350 id, "Title-" + id, /* activity =*/ null, icon,
1351 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1352 }
1353
1354 protected ShortcutInfo makePackageShortcut(String packageName, String id) {
1355 String origCaller = getCallingPackage();
1356
1357 setCaller(packageName);
1358 ShortcutInfo s = makeShortcut(
1359 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1360 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1361 setCaller(origCaller); // restore the caller
1362
1363 return s;
1364 }
1365
1366 /**
1367 * Make multiple shortcuts with IDs.
1368 */
1369 protected List<ShortcutInfo> makeShortcuts(String... ids) {
1370 final ArrayList<ShortcutInfo> ret = new ArrayList();
1371 for (String id : ids) {
1372 ret.add(makeShortcut(id));
1373 }
1374 return ret;
1375 }
1376
1377 protected ShortcutInfo.Builder makeShortcutBuilder() {
1378 return new ShortcutInfo.Builder(mClientContext);
1379 }
1380
1381 protected ShortcutInfo makeShortcutWithActivity(String id, ComponentName activity) {
1382 return makeShortcut(
1383 id, "Title-" + id, activity, /* icon =*/ null,
1384 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1385 }
1386
Makoto Onukib5a012f2016-06-21 11:13:53 -07001387 protected ShortcutInfo makeShortcutWithIntent(String id, Intent intent) {
1388 return makeShortcut(
1389 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1390 intent, /* rank =*/ 0);
1391 }
1392
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001393 protected ShortcutInfo makeShortcutWithActivityAndTitle(String id, ComponentName activity,
1394 String title) {
1395 return makeShortcut(
1396 id, title, activity, /* icon =*/ null,
1397 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
1398 }
1399
1400 protected ShortcutInfo makeShortcutWithActivityAndRank(String id, ComponentName activity,
1401 int rank) {
1402 return makeShortcut(
1403 id, "Title-" + id, activity, /* icon =*/ null,
1404 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank);
1405 }
1406
1407 /**
1408 * Make a shortcut with details.
1409 */
1410 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
1411 Icon icon, Intent intent, int rank) {
Makoto Onukib5a012f2016-06-21 11:13:53 -07001412 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
Makoto Onuki255461f2017-01-10 11:47:25 -08001413 .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
Makoto Onukib5a012f2016-06-21 11:13:53 -07001414 .setShortLabel(title)
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001415 .setRank(rank)
1416 .setIntent(intent);
1417 if (icon != null) {
1418 b.setIcon(icon);
1419 }
1420 if (activity != null) {
1421 b.setActivity(activity);
1422 }
1423 final ShortcutInfo s = b.build();
1424
1425 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
1426
1427 return s;
1428 }
1429
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001430 protected ShortcutInfo makeShortcutWithIntents(String id, Intent... intents) {
1431 return makeShortcut(
1432 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
1433 intents, /* rank =*/ 0);
1434 }
1435
1436 /**
1437 * Make a shortcut with details.
1438 */
1439 protected ShortcutInfo makeShortcut(String id, String title, ComponentName activity,
1440 Icon icon, Intent[] intents, int rank) {
1441 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
Makoto Onuki255461f2017-01-10 11:47:25 -08001442 .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001443 .setShortLabel(title)
1444 .setRank(rank)
1445 .setIntents(intents);
1446 if (icon != null) {
1447 b.setIcon(icon);
1448 }
1449 if (activity != null) {
1450 b.setActivity(activity);
1451 }
1452 final ShortcutInfo s = b.build();
1453
1454 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
1455
1456 return s;
1457 }
1458
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001459 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -07001460 * Make a shortcut with details.
1461 */
1462 protected ShortcutInfo makeShortcutWithExtras(String id, Intent intent,
1463 PersistableBundle extras) {
1464 final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, id)
Makoto Onuki255461f2017-01-10 11:47:25 -08001465 .setActivity(new ComponentName(mClientContext.getPackageName(), "main"))
Makoto Onukib5a012f2016-06-21 11:13:53 -07001466 .setShortLabel("title-" + id)
1467 .setExtras(extras)
1468 .setIntent(intent);
1469 final ShortcutInfo s = b.build();
1470
1471 s.setTimestamp(mInjectedCurrentTimeMillis); // HACK
1472
1473 return s;
1474 }
1475
1476 /**
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001477 * Make an intent.
1478 */
1479 protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
1480 final Intent intent = new Intent(action);
1481 intent.setComponent(makeComponent(clazz));
1482 intent.replaceExtras(makeBundle(bundleKeysAndValues));
1483 return intent;
1484 }
1485
1486 /**
1487 * Make an component name, with the client context.
1488 */
1489 @NonNull
1490 protected ComponentName makeComponent(Class<?> clazz) {
1491 return new ComponentName(mClientContext, clazz);
1492 }
1493
1494 @NonNull
1495 protected ShortcutInfo findById(List<ShortcutInfo> list, String id) {
1496 for (ShortcutInfo s : list) {
1497 if (s.getId().equals(id)) {
1498 return s;
1499 }
1500 }
1501 fail("Shortcut with id " + id + " not found");
1502 return null;
1503 }
1504
1505 protected void assertSystem() {
1506 assertEquals("Caller must be system", Process.SYSTEM_UID, mInjectedCallingUid);
1507 }
1508
1509 protected void assertResetTimes(long expectedLastResetTime, long expectedNextResetTime) {
1510 assertEquals(expectedLastResetTime, mService.getLastResetTimeLocked());
1511 assertEquals(expectedNextResetTime, mService.getNextResetTimeLocked());
1512 }
1513
1514 public static List<ShortcutInfo> assertAllNotHaveIcon(
1515 List<ShortcutInfo> actualShortcuts) {
1516 for (ShortcutInfo s : actualShortcuts) {
1517 assertNull("ID " + s.getId(), s.getIcon());
1518 }
1519 return actualShortcuts;
1520 }
1521
1522 @NonNull
1523 protected List<ShortcutInfo> assertAllHaveFlags(@NonNull List<ShortcutInfo> actualShortcuts,
1524 int shortcutFlags) {
1525 for (ShortcutInfo s : actualShortcuts) {
1526 assertTrue("ID " + s.getId() + " doesn't have flags " + shortcutFlags,
1527 s.hasFlags(shortcutFlags));
1528 }
1529 return actualShortcuts;
1530 }
1531
1532 protected ShortcutInfo getPackageShortcut(String packageName, String shortcutId, int userId) {
1533 return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
1534 }
1535
1536 protected void assertShortcutExists(String packageName, String shortcutId, int userId) {
1537 assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null);
1538 }
1539
1540 protected void assertShortcutNotExists(String packageName, String shortcutId, int userId) {
1541 assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null);
1542 }
1543
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001544 protected Intent[] launchShortcutAndGetIntentsInner(Runnable shortcutStarter,
1545 @NonNull String packageName, @NonNull String shortcutId, int userId) {
1546 reset(mMockActivityManagerInternal);
1547 shortcutStarter.run();
1548
1549 final ArgumentCaptor<Intent[]> intentsCaptor = ArgumentCaptor.forClass(Intent[].class);
1550 verify(mMockActivityManagerInternal).startActivitiesAsPackage(
1551 eq(packageName),
1552 eq(userId),
1553 intentsCaptor.capture(),
1554 any(Bundle.class));
1555 return intentsCaptor.getValue();
1556 }
1557
1558 protected Intent[] launchShortcutAndGetIntents(
1559 @NonNull String packageName, @NonNull String shortcutId, int userId) {
1560 return launchShortcutAndGetIntentsInner(
1561 () -> {
1562 mLauncherApps.startShortcut(packageName, shortcutId, null, null,
1563 UserHandle.of(userId));
1564 }, packageName, shortcutId, userId
1565 );
1566 }
1567
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001568 protected Intent launchShortcutAndGetIntent(
1569 @NonNull String packageName, @NonNull String shortcutId, int userId) {
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001570 final Intent[] intents = launchShortcutAndGetIntents(packageName, shortcutId, userId);
1571 assertEquals(1, intents.length);
1572 return intents[0];
1573 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001574
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001575 protected Intent[] launchShortcutAndGetIntents_withShortcutInfo(
1576 @NonNull String packageName, @NonNull String shortcutId, int userId) {
1577 return launchShortcutAndGetIntentsInner(
1578 () -> {
1579 mLauncherApps.startShortcut(
1580 getShortcutInfoAsLauncher(packageName, shortcutId, userId), null, null);
1581 }, packageName, shortcutId, userId
1582 );
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001583 }
1584
1585 protected Intent launchShortcutAndGetIntent_withShortcutInfo(
1586 @NonNull String packageName, @NonNull String shortcutId, int userId) {
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001587 final Intent[] intents = launchShortcutAndGetIntents_withShortcutInfo(
1588 packageName, shortcutId, userId);
1589 assertEquals(1, intents.length);
1590 return intents[0];
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001591 }
1592
1593 protected void assertShortcutLaunchable(@NonNull String packageName, @NonNull String shortcutId,
1594 int userId) {
1595 assertNotNull(launchShortcutAndGetIntent(packageName, shortcutId, userId));
1596 assertNotNull(launchShortcutAndGetIntent_withShortcutInfo(packageName, shortcutId, userId));
1597 }
1598
Makoto Onuki440a1ea2016-07-20 14:21:18 -07001599 protected void assertShortcutNotLaunched(@NonNull String packageName,
1600 @NonNull String shortcutId, int userId) {
1601 reset(mMockActivityManagerInternal);
1602 try {
1603 mLauncherApps.startShortcut(packageName, shortcutId, null, null,
1604 UserHandle.of(userId));
1605 fail("ActivityNotFoundException was not thrown");
1606 } catch (ActivityNotFoundException expected) {
1607 }
1608 // This shouldn't have been called.
1609 verify(mMockActivityManagerInternal, times(0)).startActivitiesAsPackage(
1610 anyString(),
1611 anyInt(),
1612 any(Intent[].class),
1613 any(Bundle.class));
1614 }
1615
1616 protected void assertStartShortcutThrowsException(@NonNull String packageName,
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001617 @NonNull String shortcutId, int userId, Class<?> expectedException) {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001618 Exception thrown = null;
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001619 try {
Makoto Onukid6880792016-06-29 13:37:43 -07001620 mLauncherApps.startShortcut(packageName, shortcutId, null, null,
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001621 UserHandle.of(userId));
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001622 } catch (Exception e) {
1623 thrown = e;
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001624 }
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001625 assertNotNull("Exception was not thrown", thrown);
1626 assertEquals("Exception type different", expectedException, thrown.getClass());
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001627 }
1628
1629 protected void assertBitmapDirectories(int userId, String... expectedDirectories) {
1630 final Set<String> expected = hashSet(set(expectedDirectories));
1631
1632 final Set<String> actual = new HashSet<>();
1633
1634 final File[] files = mService.getUserBitmapFilePath(userId).listFiles();
1635 if (files != null) {
1636 for (File child : files) {
1637 if (child.isDirectory()) {
1638 actual.add(child.getName());
1639 }
1640 }
1641 }
1642
1643 assertEquals(expected, actual);
1644 }
1645
1646 protected void assertBitmapFiles(int userId, String packageName, String... expectedFiles) {
1647 final Set<String> expected = hashSet(set(expectedFiles));
1648
1649 final Set<String> actual = new HashSet<>();
1650
1651 final File[] files = new File(mService.getUserBitmapFilePath(userId), packageName)
1652 .listFiles();
1653 if (files != null) {
1654 for (File child : files) {
1655 if (child.isFile()) {
1656 actual.add(child.getName());
1657 }
1658 }
1659 }
1660
1661 assertEquals(expected, actual);
1662 }
1663
1664 protected String getBitmapFilename(int userId, String packageName, String shortcutId) {
1665 final ShortcutInfo si = mService.getPackageShortcutForTest(packageName, shortcutId, userId);
1666 if (si == null) {
1667 return null;
1668 }
1669 return new File(si.getBitmapPath()).getName();
1670 }
1671
Makoto Onukif3ba2e02016-07-12 09:18:50 -07001672 /**
1673 * @return all shortcuts stored internally for the caller. This reflects the *internal* view
1674 * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would
1675 * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door"
1676 * which performs some extra checks, like {@link ShortcutPackage#onRestored}.
1677 */
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001678 protected List<ShortcutInfo> getCallerShortcuts() {
1679 final ShortcutPackage p = mService.getPackageShortcutForTest(
1680 getCallingPackage(), getCallingUserId());
1681 return p == null ? null : p.getAllShortcutsForTest();
1682 }
1683
Makoto Onukif3ba2e02016-07-12 09:18:50 -07001684 /**
1685 * @return all shortcuts owned by caller that are actually visible via ShortcutManager.
1686 * See also {@link #getCallerShortcuts}.
1687 */
1688 protected List<ShortcutInfo> getCallerVisibleShortcuts() {
1689 final ArrayList<ShortcutInfo> ret = new ArrayList<>();
1690 ret.addAll(mManager.getDynamicShortcuts());
1691 ret.addAll(mManager.getPinnedShortcuts());
1692 ret.addAll(mManager.getManifestShortcuts());
1693 return ret;
1694 }
1695
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001696 protected ShortcutInfo getCallerShortcut(String shortcutId) {
1697 return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
1698 }
1699
1700 protected List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) {
1701 final List<ShortcutInfo>[] ret = new List[1];
1702 runWithCaller(launcher, userId, () -> {
1703 final ShortcutQuery q = new ShortcutQuery();
1704 q.setQueryFlags(queryFlags);
1705 ret[0] = mLauncherApps.getShortcuts(q, UserHandle.of(userId));
1706 });
1707 return ret[0];
1708 }
1709
1710 protected List<ShortcutInfo> getLauncherPinnedShortcuts(String launcher, int userId) {
1711 return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
1712 }
1713
Makoto Onukia01f4f02016-12-15 15:58:41 -08001714 protected List<ShortcutInfo> getShortcutAsLauncher(int targetUserId) {
1715 final ShortcutQuery q = new ShortcutQuery();
1716 q.setQueryFlags(ShortcutQuery.FLAG_MATCH_DYNAMIC | ShortcutQuery.FLAG_MATCH_DYNAMIC
1717 | ShortcutQuery.FLAG_MATCH_PINNED);
1718 return mLauncherApps.getShortcuts(q, UserHandle.of(targetUserId));
1719 }
1720
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001721 protected ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId,
1722 int userId) {
1723 final List<ShortcutInfo> infoList =
1724 mLauncherApps.getShortcutInfo(packageName, list(shortcutId),
1725 UserHandle.of(userId));
1726 assertEquals("No shortcutInfo found (or too many of them)", 1, infoList.size());
1727 return infoList.get(0);
1728 }
1729
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001730 protected Intent genPackageAddIntent(String packageName, int userId) {
1731 installPackage(userId, packageName);
1732
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001733 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001734 i.setData(Uri.parse("package:" + packageName));
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001735 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1736 return i;
1737 }
1738
1739 protected Intent genPackageDeleteIntent(String pakcageName, int userId) {
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001740 uninstallPackage(userId, pakcageName);
1741
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001742 Intent i = new Intent(Intent.ACTION_PACKAGE_REMOVED);
1743 i.setData(Uri.parse("package:" + pakcageName));
1744 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1745 return i;
1746 }
1747
1748 protected Intent genPackageUpdateIntent(String pakcageName, int userId) {
Makoto Onukiee6b6e42016-06-29 17:34:02 -07001749 installPackage(userId, pakcageName);
1750
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001751 Intent i = new Intent(Intent.ACTION_PACKAGE_ADDED);
1752 i.setData(Uri.parse("package:" + pakcageName));
1753 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1754 i.putExtra(Intent.EXTRA_REPLACING, true);
1755 return i;
1756 }
1757
Makoto Onukib08790c2016-06-23 14:05:46 -07001758 protected Intent genPackageChangedIntent(String pakcageName, int userId) {
1759 Intent i = new Intent(Intent.ACTION_PACKAGE_CHANGED);
1760 i.setData(Uri.parse("package:" + pakcageName));
1761 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1762 return i;
1763 }
1764
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001765 protected Intent genPackageDataClear(String packageName, int userId) {
1766 Intent i = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED);
1767 i.setData(Uri.parse("package:" + packageName));
1768 i.putExtra(Intent.EXTRA_USER_HANDLE, userId);
1769 return i;
1770 }
1771
1772 protected void assertExistsAndShadow(ShortcutPackageItem spi) {
1773 assertNotNull(spi);
1774 assertTrue(spi.getPackageInfo().isShadow());
1775 }
1776
1777 protected File makeFile(File baseDirectory, String... paths) {
1778 File ret = baseDirectory;
1779
1780 for (String path : paths) {
1781 ret = new File(ret, path);
1782 }
1783
1784 return ret;
1785 }
1786
1787 protected boolean bitmapDirectoryExists(String packageName, int userId) {
1788 final File path = new File(mService.getUserBitmapFilePath(userId), packageName);
1789 return path.isDirectory();
1790 }
1791 protected static ShortcutQuery buildQuery(long changedSince,
1792 String packageName, ComponentName componentName,
1793 /* @ShortcutQuery.QueryFlags */ int flags) {
1794 return buildQuery(changedSince, packageName, null, componentName, flags);
1795 }
1796
1797 protected static ShortcutQuery buildQuery(long changedSince,
1798 String packageName, List<String> shortcutIds, ComponentName componentName,
1799 /* @ShortcutQuery.QueryFlags */ int flags) {
1800 final ShortcutQuery q = new ShortcutQuery();
1801 q.setChangedSince(changedSince);
1802 q.setPackage(packageName);
1803 q.setShortcutIds(shortcutIds);
1804 q.setActivity(componentName);
1805 q.setQueryFlags(flags);
1806 return q;
1807 }
1808
1809 protected static ShortcutQuery buildAllQuery(String packageName) {
1810 final ShortcutQuery q = new ShortcutQuery();
1811 q.setPackage(packageName);
Makoto Onuki4d6b87f2016-06-17 13:47:40 -07001812 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001813 return q;
1814 }
1815
1816 protected static ShortcutQuery buildPinnedQuery(String packageName) {
1817 final ShortcutQuery q = new ShortcutQuery();
1818 q.setPackage(packageName);
1819 q.setQueryFlags(ShortcutQuery.FLAG_GET_PINNED);
1820 return q;
1821 }
1822
Makoto Onuki4d6b87f2016-06-17 13:47:40 -07001823 protected static ShortcutQuery buildQueryWithFlags(int queryFlags) {
1824 final ShortcutQuery q = new ShortcutQuery();
1825 q.setQueryFlags(queryFlags);
1826 return q;
1827 }
1828
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001829 protected void backupAndRestore() {
1830 int prevUid = mInjectedCallingUid;
1831
1832 mInjectedCallingUid = Process.SYSTEM_UID; // Only system can call it.
1833
1834 dumpsysOnLogcat("Before backup");
1835
1836 final byte[] payload = mService.getBackupPayload(USER_0);
1837 if (ENABLE_DUMP) {
1838 final String xml = new String(payload);
1839 Log.v(TAG, "Backup payload:");
1840 for (String line : xml.split("\n")) {
1841 Log.v(TAG, line);
1842 }
1843 }
1844
1845 // Before doing anything else, uninstall all packages.
1846 for (int userId : list(USER_0, USER_P0)) {
1847 for (String pkg : list(CALLING_PACKAGE_1, CALLING_PACKAGE_2, CALLING_PACKAGE_3,
1848 LAUNCHER_1, LAUNCHER_2, LAUNCHER_3)) {
1849 uninstallPackage(userId, pkg);
1850 }
1851 }
1852
1853 shutdownServices();
1854
1855 deleteAllSavedFiles();
1856
1857 initService();
1858 mService.applyRestore(payload, USER_0);
1859
1860 // handleUnlockUser will perform the gone package check, but it shouldn't remove
1861 // shadow information.
1862 mService.handleUnlockUser(USER_0);
1863
1864 dumpsysOnLogcat("After restore");
1865
1866 mInjectedCallingUid = prevUid;
1867 }
1868
1869 protected void prepareCrossProfileDataSet() {
Makoto Onuki9c850012016-07-26 15:50:50 -07001870 mRunningUsers.put(USER_10, true); // this test needs user 10.
1871
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001872 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1873 assertTrue(mManager.setDynamicShortcuts(list(
1874 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1875 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1876 });
1877 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1878 assertTrue(mManager.setDynamicShortcuts(list(
1879 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1880 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1881 });
1882 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1883 assertTrue(mManager.setDynamicShortcuts(list(
1884 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1885 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1886 });
1887 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1888 assertTrue(mManager.setDynamicShortcuts(list()));
1889 });
1890 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1891 assertTrue(mManager.setDynamicShortcuts(list(
1892 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"),
1893 makeShortcut("s4"), makeShortcut("s5"), makeShortcut("s6"))));
1894 });
1895 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1896 assertTrue(mManager.setDynamicShortcuts(list(
1897 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"),
1898 makeShortcut("x4"), makeShortcut("x5"), makeShortcut("x6"))));
1899 });
1900
1901 runWithCaller(LAUNCHER_1, USER_0, () -> {
1902 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1"), HANDLE_USER_0);
1903 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s1", "s2"), HANDLE_USER_0);
1904 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s1", "s2", "s3"), HANDLE_USER_0);
1905
1906 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s1", "s4"), HANDLE_USER_P0);
1907 });
1908 runWithCaller(LAUNCHER_2, USER_0, () -> {
1909 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2"), HANDLE_USER_0);
1910 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s2", "s3"), HANDLE_USER_0);
1911 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s2", "s3", "s4"), HANDLE_USER_0);
1912
1913 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
1914 });
Makoto Onukif3ba2e02016-07-12 09:18:50 -07001915
1916 // Note LAUNCHER_3 has allowBackup=false.
Makoto Onuki51ab2b32016-06-02 11:03:51 -07001917 runWithCaller(LAUNCHER_3, USER_0, () -> {
1918 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
1919 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
1920 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5"), HANDLE_USER_0);
1921
1922 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s6"), HANDLE_USER_P0);
1923 });
1924 runWithCaller(LAUNCHER_4, USER_0, () -> {
1925 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list(), HANDLE_USER_0);
1926 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list(), HANDLE_USER_0);
1927 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list(), HANDLE_USER_0);
1928 mLauncherApps.pinShortcuts(CALLING_PACKAGE_4, list(), HANDLE_USER_0);
1929 });
1930
1931 // Launcher on a managed profile is referring ot user 0!
1932 runWithCaller(LAUNCHER_1, USER_P0, () -> {
1933 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3", "s4"), HANDLE_USER_0);
1934 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4", "s5"), HANDLE_USER_0);
1935 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("s3", "s4", "s5", "s6"),
1936 HANDLE_USER_0);
1937
1938 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s4", "s1"), HANDLE_USER_P0);
1939 });
1940 runWithCaller(LAUNCHER_1, USER_10, () -> {
1941 mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("x4", "x5"), HANDLE_USER_10);
1942 mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("x4", "x5", "x6"), HANDLE_USER_10);
1943 mLauncherApps.pinShortcuts(CALLING_PACKAGE_3, list("x4", "x5", "x6", "x1"),
1944 HANDLE_USER_10);
1945 });
1946
1947 // Then remove some dynamic shortcuts.
1948 runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1949 assertTrue(mManager.setDynamicShortcuts(list(
1950 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1951 });
1952 runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1953 assertTrue(mManager.setDynamicShortcuts(list(
1954 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1955 });
1956 runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1957 assertTrue(mManager.setDynamicShortcuts(list(
1958 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1959 });
1960 runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1961 assertTrue(mManager.setDynamicShortcuts(list()));
1962 });
1963 runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1964 assertTrue(mManager.setDynamicShortcuts(list(
1965 makeShortcut("s1"), makeShortcut("s2"), makeShortcut("s3"))));
1966 });
1967 runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1968 assertTrue(mManager.setDynamicShortcuts(list(
1969 makeShortcut("x1"), makeShortcut("x2"), makeShortcut("x3"))));
1970 });
1971 }
Makoto Onukib5a012f2016-06-21 11:13:53 -07001972
1973 public static List<ShortcutInfo> assertAllHaveIconResId(
1974 List<ShortcutInfo> actualShortcuts) {
1975 for (ShortcutInfo s : actualShortcuts) {
1976 assertTrue("ID " + s.getId() + " not have icon res ID", s.hasIconResource());
1977 assertFalse("ID " + s.getId() + " shouldn't have icon FD", s.hasIconFile());
1978 }
1979 return actualShortcuts;
1980 }
1981
1982 public static List<ShortcutInfo> assertAllHaveIconFile(
1983 List<ShortcutInfo> actualShortcuts) {
1984 for (ShortcutInfo s : actualShortcuts) {
1985 assertFalse("ID " + s.getId() + " shouldn't have icon res ID", s.hasIconResource());
1986 assertTrue("ID " + s.getId() + " not have icon FD", s.hasIconFile());
1987 }
1988 return actualShortcuts;
1989 }
1990
1991 public static List<ShortcutInfo> assertAllHaveIcon(
1992 List<ShortcutInfo> actualShortcuts) {
1993 for (ShortcutInfo s : actualShortcuts) {
Makoto Onukia01f4f02016-12-15 15:58:41 -08001994 assertTrue("ID " + s.getId() + " has no icon ",
1995 s.hasIconFile() || s.hasIconResource() || s.getIcon() != null);
Makoto Onukib5a012f2016-06-21 11:13:53 -07001996 }
1997 return actualShortcuts;
1998 }
1999
2000 public static List<ShortcutInfo> assertAllStringsResolved(
2001 List<ShortcutInfo> actualShortcuts) {
2002 for (ShortcutInfo s : actualShortcuts) {
2003 assertTrue("ID " + s.getId(), s.hasStringResourcesResolved());
2004 }
2005 return actualShortcuts;
2006 }
Makoto Onuki76269922016-07-15 14:58:54 -07002007
2008 public String readTestAsset(String assetPath) throws IOException {
2009 final StringBuilder sb = new StringBuilder();
2010 try (BufferedReader br = new BufferedReader(
2011 new InputStreamReader(
2012 getTestContext().getResources().getAssets().open(assetPath)))) {
2013 String line;
2014 while ((line = br.readLine()) != null) {
2015 sb.append(line);
2016 sb.append(System.lineSeparator());
2017 }
2018 }
2019 return sb.toString();
2020 }
Makoto Onuki0b9d1db2016-07-18 14:16:41 -07002021
2022 protected void prepareGetHomeActivitiesAsUser(ComponentName preferred,
2023 List<ResolveInfo> candidates, int userId) {
2024 doAnswer(inv -> {
2025 ((List) inv.getArguments()[0]).addAll(candidates);
2026 return preferred;
2027 }).when(mMockPackageManagerInternal).getHomeActivitiesAsUser(any(List.class), eq(userId));
2028 }
2029
2030 protected static ComponentName cn(String packageName, String name) {
2031 return new ComponentName(packageName, name);
2032 }
2033
2034 protected static ResolveInfo ri(String packageName, String name, boolean isSystem, int priority) {
2035 final ResolveInfo ri = new ResolveInfo();
2036 ri.activityInfo = new ActivityInfo();
2037 ri.activityInfo.applicationInfo = new ApplicationInfo();
2038
2039 ri.activityInfo.packageName = packageName;
2040 ri.activityInfo.name = name;
2041 if (isSystem) {
2042 ri.activityInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
2043 }
2044 ri.priority = priority;
2045 return ri;
2046 }
2047
2048 protected static ResolveInfo getSystemLauncher() {
2049 return ri(PACKAGE_SYSTEM_LAUNCHER, PACKAGE_SYSTEM_LAUNCHER_NAME, true,
2050 PACKAGE_SYSTEM_LAUNCHER_PRIORITY);
2051 }
2052
2053 protected static ResolveInfo getFallbackLauncher() {
2054 return ri(PACKAGE_FALLBACK_LAUNCHER, PACKAGE_FALLBACK_LAUNCHER_NAME, true,
2055 PACKAGE_FALLBACK_LAUNCHER_PRIORITY);
2056 }
Makoto Onukia01f4f02016-12-15 15:58:41 -08002057
2058 protected void makeCallerForeground() {
2059 try {
2060 mService.mUidObserver.onUidStateChanged(
2061 mInjectedCallingUid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
2062 } catch (RemoteException e) {
2063 e.rethrowAsRuntimeException();
2064 }
2065 }
2066
2067 protected void makeCallerBackground() {
2068 try {
2069 mService.mUidObserver.onUidStateChanged(
2070 mInjectedCallingUid, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
2071 } catch (RemoteException e) {
2072 e.rethrowAsRuntimeException();
2073 }
2074 }
2075
2076 protected void publishManifestShortcutsAsCaller(int resId) {
2077 addManifestShortcutResource(
2078 new ComponentName(getCallingPackage(), ShortcutActivity.class.getName()),
2079 resId);
2080 updatePackageVersion(getCallingPackage(), 1);
2081 mService.mPackageMonitor.onReceive(getTestContext(),
2082 genPackageAddIntent(getCallingPackage(), getCallingUserId()));
2083 }
Makoto Onuki51ab2b32016-06-02 11:03:51 -07002084}