1 /*
2  * Copyright (C) 2014 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  */
16 
17 package com.android.server.pm;
18 
19 import static android.app.ActivityOptions.KEY_SPLASH_SCREEN_THEME;
20 import static android.app.PendingIntent.FLAG_IMMUTABLE;
21 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
22 import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
23 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
24 import static android.content.pm.LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS;
25 import static android.content.pm.LauncherApps.FLAG_CACHE_NOTIFICATION_SHORTCUTS;
26 import static android.content.pm.LauncherApps.FLAG_CACHE_PEOPLE_TILE_SHORTCUTS;
27 
28 import android.annotation.AppIdInt;
29 import android.annotation.NonNull;
30 import android.annotation.Nullable;
31 import android.annotation.UserIdInt;
32 import android.app.ActivityManager;
33 import android.app.ActivityManagerInternal;
34 import android.app.ActivityOptions;
35 import android.app.AppGlobals;
36 import android.app.IApplicationThread;
37 import android.app.PendingIntent;
38 import android.app.admin.DevicePolicyManager;
39 import android.app.usage.UsageStatsManagerInternal;
40 import android.content.ActivityNotFoundException;
41 import android.content.BroadcastReceiver;
42 import android.content.ComponentName;
43 import android.content.Context;
44 import android.content.Intent;
45 import android.content.IntentFilter;
46 import android.content.IntentSender;
47 import android.content.LocusId;
48 import android.content.pm.ActivityInfo;
49 import android.content.pm.ApplicationInfo;
50 import android.content.pm.ILauncherApps;
51 import android.content.pm.IOnAppsChangedListener;
52 import android.content.pm.IPackageInstallerCallback;
53 import android.content.pm.IPackageManager;
54 import android.content.pm.IShortcutChangeCallback;
55 import android.content.pm.IncrementalStatesInfo;
56 import android.content.pm.LauncherActivityInfoInternal;
57 import android.content.pm.LauncherApps;
58 import android.content.pm.LauncherApps.ShortcutQuery;
59 import android.content.pm.PackageInfo;
60 import android.content.pm.PackageInstaller.SessionInfo;
61 import android.content.pm.PackageManager;
62 import android.content.pm.PackageManagerInternal;
63 import android.content.pm.ParceledListSlice;
64 import android.content.pm.ResolveInfo;
65 import android.content.pm.ShortcutInfo;
66 import android.content.pm.ShortcutQueryWrapper;
67 import android.content.pm.ShortcutServiceInternal;
68 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
69 import android.content.pm.UserInfo;
70 import android.graphics.Rect;
71 import android.net.Uri;
72 import android.os.Binder;
73 import android.os.Bundle;
74 import android.os.Handler;
75 import android.os.IInterface;
76 import android.os.ParcelFileDescriptor;
77 import android.os.Process;
78 import android.os.RemoteCallbackList;
79 import android.os.RemoteException;
80 import android.os.ServiceManager;
81 import android.os.UserHandle;
82 import android.os.UserManager;
83 import android.provider.Settings;
84 import android.util.Log;
85 import android.util.Pair;
86 import android.util.Slog;
87 
88 import com.android.internal.annotations.GuardedBy;
89 import com.android.internal.annotations.VisibleForTesting;
90 import com.android.internal.content.PackageMonitor;
91 import com.android.internal.os.BackgroundThread;
92 import com.android.internal.util.ArrayUtils;
93 import com.android.internal.util.CollectionUtils;
94 import com.android.internal.util.Preconditions;
95 import com.android.server.LocalServices;
96 import com.android.server.SystemService;
97 import com.android.server.pm.parsing.pkg.AndroidPackage;
98 import com.android.server.wm.ActivityTaskManagerInternal;
99 
100 import java.util.ArrayList;
101 import java.util.Arrays;
102 import java.util.Collections;
103 import java.util.HashSet;
104 import java.util.List;
105 import java.util.Objects;
106 
107 /**
108  * Service that manages requests and callbacks for launchers that support
109  * managed profiles.
110  */
111 public class LauncherAppsService extends SystemService {
112 
113     private final LauncherAppsImpl mLauncherAppsImpl;
114 
LauncherAppsService(Context context)115     public LauncherAppsService(Context context) {
116         super(context);
117         mLauncherAppsImpl = new LauncherAppsImpl(context);
118     }
119 
120     @Override
onStart()121     public void onStart() {
122         publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
123         mLauncherAppsImpl.registerLoadingProgressForIncrementalApps();
124     }
125 
126     static class BroadcastCookie {
127         public final UserHandle user;
128         public final String packageName;
129         public final int callingUid;
130         public final int callingPid;
131 
BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid)132         BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid) {
133             this.user = userHandle;
134             this.packageName = packageName;
135             this.callingUid = callingUid;
136             this.callingPid = callingPid;
137         }
138     }
139 
140     @VisibleForTesting
141     static class LauncherAppsImpl extends ILauncherApps.Stub {
142         private static final boolean DEBUG = false;
143         private static final String TAG = "LauncherAppsService";
144 
145         private final Context mContext;
146         private final UserManager mUm;
147         private final IPackageManager mIPM;
148         private final UserManagerInternal mUserManagerInternal;
149         private final UsageStatsManagerInternal mUsageStatsManagerInternal;
150         private final ActivityManagerInternal mActivityManagerInternal;
151         private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
152         private final ShortcutServiceInternal mShortcutServiceInternal;
153         private final PackageManagerInternal mPackageManagerInternal;
154         private final PackageCallbackList<IOnAppsChangedListener> mListeners
155                 = new PackageCallbackList<IOnAppsChangedListener>();
156         private final DevicePolicyManager mDpm;
157 
158         private final PackageRemovedListener mPackageRemovedListener =
159                 new PackageRemovedListener();
160         private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
161 
162         @GuardedBy("mListeners")
163         private boolean mIsWatchingPackageBroadcasts = false;
164 
165         private final ShortcutChangeHandler mShortcutChangeHandler;
166 
167         private final Handler mCallbackHandler;
168 
169         private PackageInstallerService mPackageInstallerService;
170 
LauncherAppsImpl(Context context)171         public LauncherAppsImpl(Context context) {
172             mContext = context;
173             mIPM = AppGlobals.getPackageManager();
174             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
175             mUserManagerInternal = Objects.requireNonNull(
176                     LocalServices.getService(UserManagerInternal.class));
177             mUsageStatsManagerInternal = Objects.requireNonNull(
178                     LocalServices.getService(UsageStatsManagerInternal.class));
179             mActivityManagerInternal = Objects.requireNonNull(
180                     LocalServices.getService(ActivityManagerInternal.class));
181             mActivityTaskManagerInternal = Objects.requireNonNull(
182                     LocalServices.getService(ActivityTaskManagerInternal.class));
183             mShortcutServiceInternal = Objects.requireNonNull(
184                     LocalServices.getService(ShortcutServiceInternal.class));
185             mPackageManagerInternal = Objects.requireNonNull(
186                     LocalServices.getService(PackageManagerInternal.class));
187             mShortcutServiceInternal.addListener(mPackageMonitor);
188             mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal);
189             mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler);
190             mCallbackHandler = BackgroundThread.getHandler();
191             mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
192         }
193 
194         @VisibleForTesting
injectBinderCallingUid()195         int injectBinderCallingUid() {
196             return getCallingUid();
197         }
198 
199         @VisibleForTesting
injectBinderCallingPid()200         int injectBinderCallingPid() {
201             return getCallingPid();
202         }
203 
injectCallingUserId()204         final int injectCallingUserId() {
205             return UserHandle.getUserId(injectBinderCallingUid());
206         }
207 
208         @VisibleForTesting
injectClearCallingIdentity()209         long injectClearCallingIdentity() {
210             return Binder.clearCallingIdentity();
211         }
212 
213         // Injection point.
214         @VisibleForTesting
injectRestoreCallingIdentity(long token)215         void injectRestoreCallingIdentity(long token) {
216             Binder.restoreCallingIdentity(token);
217         }
218 
getCallingUserId()219         private int getCallingUserId() {
220             return UserHandle.getUserId(injectBinderCallingUid());
221         }
222 
223         /*
224          * @see android.content.pm.ILauncherApps#addOnAppsChangedListener
225          */
226         @Override
addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)227         public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
228                 throws RemoteException {
229             verifyCallingPackage(callingPackage);
230             synchronized (mListeners) {
231                 if (DEBUG) {
232                     Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
233                 }
234                 if (mListeners.getRegisteredCallbackCount() == 0) {
235                     if (DEBUG) {
236                         Log.d(TAG, "Starting package monitoring");
237                     }
238                     startWatchingPackageBroadcasts();
239                 }
240                 mListeners.unregister(listener);
241                 mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
242                         callingPackage, injectBinderCallingPid(), injectBinderCallingUid()));
243             }
244         }
245 
246         /*
247          * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener
248          */
249         @Override
removeOnAppsChangedListener(IOnAppsChangedListener listener)250         public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
251                 throws RemoteException {
252             synchronized (mListeners) {
253                 if (DEBUG) {
254                     Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle());
255                 }
256                 mListeners.unregister(listener);
257                 if (mListeners.getRegisteredCallbackCount() == 0) {
258                     stopWatchingPackageBroadcasts();
259                 }
260             }
261         }
262 
263         /**
264          * @see android.content.pm.ILauncherApps#registerPackageInstallerCallback
265          */
266         @Override
registerPackageInstallerCallback(String callingPackage, IPackageInstallerCallback callback)267         public void registerPackageInstallerCallback(String callingPackage,
268                 IPackageInstallerCallback callback) {
269             verifyCallingPackage(callingPackage);
270             UserHandle callingIdUserHandle = new UserHandle(getCallingUserId());
271             getPackageInstallerService().registerCallback(callback, eventUserId ->
272                             isEnabledProfileOf(callingIdUserHandle,
273                                     new UserHandle(eventUserId), "shouldReceiveEvent"));
274         }
275 
276         @Override
getAllSessions(String callingPackage)277         public ParceledListSlice<SessionInfo> getAllSessions(String callingPackage) {
278             verifyCallingPackage(callingPackage);
279             List<SessionInfo> sessionInfos = new ArrayList<>();
280             int[] userIds = mUm.getEnabledProfileIds(getCallingUserId());
281             final long token = Binder.clearCallingIdentity();
282             try {
283                 for (int userId : userIds) {
284                     sessionInfos.addAll(getPackageInstallerService().getAllSessions(userId)
285                             .getList());
286                 }
287             } finally {
288                 Binder.restoreCallingIdentity(token);
289             }
290             return new ParceledListSlice<>(sessionInfos);
291         }
292 
getPackageInstallerService()293         private PackageInstallerService getPackageInstallerService() {
294             if (mPackageInstallerService == null) {
295                 mPackageInstallerService = ((PackageInstallerService) ((PackageManagerService)
296                         ServiceManager.getService("package")).getPackageInstaller());
297             }
298             return mPackageInstallerService;
299         }
300 
301         /**
302          * Register a receiver to watch for package broadcasts
303          */
startWatchingPackageBroadcasts()304         private void startWatchingPackageBroadcasts() {
305             if (!mIsWatchingPackageBroadcasts) {
306                 final IntentFilter filter = new IntentFilter();
307                 filter.addAction(Intent.ACTION_PACKAGE_REMOVED_INTERNAL);
308                 filter.addDataScheme("package");
309                 mContext.registerReceiverAsUser(mPackageRemovedListener, UserHandle.ALL, filter,
310                         /* broadcastPermission= */ null, mCallbackHandler);
311                 mPackageMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler);
312                 mIsWatchingPackageBroadcasts = true;
313             }
314         }
315 
316         /**
317          * Unregister package broadcast receiver
318          */
stopWatchingPackageBroadcasts()319         private void stopWatchingPackageBroadcasts() {
320             if (DEBUG) {
321                 Log.d(TAG, "Stopped watching for packages");
322             }
323             if (mIsWatchingPackageBroadcasts) {
324                 mContext.unregisterReceiver(mPackageRemovedListener);
325                 mPackageMonitor.unregister();
326                 mIsWatchingPackageBroadcasts = false;
327             }
328         }
329 
checkCallbackCount()330         void checkCallbackCount() {
331             synchronized (mListeners) {
332                 if (DEBUG) {
333                     Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount());
334                 }
335                 if (mListeners.getRegisteredCallbackCount() == 0) {
336                     stopWatchingPackageBroadcasts();
337                 }
338             }
339         }
340 
341         /**
342          * Checks if the calling user is in the same group as {@code targetUser}, and allowed
343          * to access it.
344          *
345          * @return TRUE if the calling user can access {@code targetUserId}.  FALSE if not *but
346          * they're still in the same profile group*.
347          *
348          * @throws SecurityException if the calling user and {@code targetUser} are not in the same
349          * group.
350          */
canAccessProfile(int targetUserId, String message)351         private boolean canAccessProfile(int targetUserId, String message) {
352             final int callingUserId = injectCallingUserId();
353 
354             if (targetUserId == callingUserId) return true;
355             if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(),
356                     injectBinderCallingUid())) {
357                 return true;
358             }
359 
360             long ident = injectClearCallingIdentity();
361             try {
362                 final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
363                 if (callingUserInfo != null && callingUserInfo.isProfile()) {
364                     Slog.w(TAG, message + " for another profile "
365                             + targetUserId + " from " + callingUserId + " not allowed");
366                     return false;
367                 }
368             } finally {
369                 injectRestoreCallingIdentity(ident);
370             }
371 
372             return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
373                     message, true);
374         }
375 
376         @VisibleForTesting // We override it in unit tests
verifyCallingPackage(String callingPackage)377         void verifyCallingPackage(String callingPackage) {
378             int packageUid = -1;
379             try {
380                 packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
381                         PackageManager.MATCH_DIRECT_BOOT_AWARE
382                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
383                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
384                         UserHandle.getUserId(getCallingUid()));
385             } catch (RemoteException ignore) {
386             }
387             if (packageUid < 0) {
388                 Log.e(TAG, "Package not found: " + callingPackage);
389             }
390             if (packageUid != injectBinderCallingUid()) {
391                 throw new SecurityException("Calling package name mismatch");
392             }
393         }
394 
getHiddenAppActivityInfo(String packageName, int callingUid, UserHandle user)395         private LauncherActivityInfoInternal getHiddenAppActivityInfo(String packageName,
396                 int callingUid, UserHandle user) {
397             Intent intent = new Intent();
398             intent.setComponent(new ComponentName(packageName,
399                     PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME));
400             final List<LauncherActivityInfoInternal> apps = queryIntentLauncherActivities(intent,
401                     callingUid, user);
402             if (apps.size() > 0) {
403                 return apps.get(0);
404             }
405             return null;
406         }
407 
408         @Override
shouldHideFromSuggestions(String packageName, UserHandle user)409         public boolean shouldHideFromSuggestions(String packageName, UserHandle user) {
410             if (!canAccessProfile(user.getIdentifier(), "cannot get shouldHideFromSuggestions")) {
411                 return false;
412             }
413             final int flags = mPackageManagerInternal.getDistractingPackageRestrictions(packageName,
414                     user.getIdentifier());
415             return (flags & PackageManager.RESTRICTION_HIDE_FROM_SUGGESTIONS) != 0;
416         }
417 
418         @Override
getLauncherActivities( String callingPackage, String packageName, UserHandle user)419         public ParceledListSlice<LauncherActivityInfoInternal> getLauncherActivities(
420                 String callingPackage, String packageName, UserHandle user) throws RemoteException {
421             ParceledListSlice<LauncherActivityInfoInternal> launcherActivities =
422                     queryActivitiesForUser(callingPackage,
423                             new Intent(Intent.ACTION_MAIN)
424                                     .addCategory(Intent.CATEGORY_LAUNCHER)
425                                     .setPackage(packageName),
426                             user);
427             if (Settings.Global.getInt(mContext.getContentResolver(),
428                     Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) {
429                 return launcherActivities;
430             }
431             if (launcherActivities == null) {
432                 // Cannot access profile, so we don't even return any hidden apps.
433                 return null;
434             }
435 
436             final int callingUid = injectBinderCallingUid();
437             final long ident = injectClearCallingIdentity();
438             try {
439                 if (mUm.getUserInfo(user.getIdentifier()).isManagedProfile()) {
440                     // Managed profile should not show hidden apps
441                     return launcherActivities;
442                 }
443                 if (mDpm.getDeviceOwnerComponentOnAnyUser() != null) {
444                     // Device owner devices should not show hidden apps
445                     return launcherActivities;
446                 }
447 
448                 final ArrayList<LauncherActivityInfoInternal> result = new ArrayList<>(
449                         launcherActivities.getList());
450                 if (packageName != null) {
451                     // If this hidden app should not be shown, return the original list.
452                     // Otherwise, inject hidden activity that forwards user to app details page.
453                     if (result.size() > 0) {
454                         return launcherActivities;
455                     }
456                     final ApplicationInfo appInfo = mPackageManagerInternal.getApplicationInfo(
457                             packageName, /* flags= */ 0, callingUid, user.getIdentifier());
458                     if (shouldShowSyntheticActivity(user, appInfo)) {
459                         LauncherActivityInfoInternal info = getHiddenAppActivityInfo(packageName,
460                                 callingUid, user);
461                         if (info != null) {
462                             result.add(info);
463                         }
464                     }
465                     return new ParceledListSlice<>(result);
466                 }
467                 final HashSet<String> visiblePackages = new HashSet<>();
468                 for (LauncherActivityInfoInternal info : result) {
469                     visiblePackages.add(info.getActivityInfo().packageName);
470                 }
471                 final List<ApplicationInfo> installedPackages =
472                         mPackageManagerInternal.getInstalledApplications(/* flags= */ 0,
473                                 user.getIdentifier(), callingUid);
474                 for (ApplicationInfo applicationInfo : installedPackages) {
475                     if (!visiblePackages.contains(applicationInfo.packageName)) {
476                         if (!shouldShowSyntheticActivity(user, applicationInfo)) {
477                             continue;
478                         }
479                         LauncherActivityInfoInternal info = getHiddenAppActivityInfo(
480                                 applicationInfo.packageName, callingUid, user);
481                         if (info != null) {
482                             result.add(info);
483                         }
484                     }
485                 }
486                 return new ParceledListSlice<>(result);
487             } finally {
488                 injectRestoreCallingIdentity(ident);
489             }
490         }
491 
shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo)492         private boolean shouldShowSyntheticActivity(UserHandle user, ApplicationInfo appInfo) {
493             if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
494                 return false;
495             }
496             if (isManagedProfileAdmin(user, appInfo.packageName)) {
497                 return false;
498             }
499             final AndroidPackage pkg = mPackageManagerInternal.getPackage(appInfo.packageName);
500             if (pkg == null) {
501                 // Should not happen, but we shouldn't be failing if it does
502                 return false;
503             }
504             // If app does not have any default enabled launcher activity or any permissions,
505             // the app can legitimately have no icon so we do not show the synthetic activity.
506             return requestsPermissions(pkg) && hasDefaultEnableLauncherActivity(
507                     appInfo.packageName);
508         }
509 
requestsPermissions(@onNull AndroidPackage pkg)510         private boolean requestsPermissions(@NonNull AndroidPackage pkg) {
511             return !ArrayUtils.isEmpty(pkg.getRequestedPermissions());
512         }
513 
hasDefaultEnableLauncherActivity(@onNull String packageName)514         private boolean hasDefaultEnableLauncherActivity(@NonNull String packageName) {
515             final Intent matchIntent = new Intent(Intent.ACTION_MAIN);
516             matchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
517             matchIntent.setPackage(packageName);
518             final List<ResolveInfo> infoList = mPackageManagerInternal.queryIntentActivities(
519                     matchIntent, matchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
520                     PackageManager.MATCH_DISABLED_COMPONENTS, Binder.getCallingUid(),
521                     getCallingUserId());
522             final int size = infoList.size();
523             for (int i = 0; i < size; i++) {
524                 if (infoList.get(i).activityInfo.enabled) {
525                     return true;
526                 }
527             }
528             return false;
529         }
530 
isManagedProfileAdmin(UserHandle user, String packageName)531         private boolean isManagedProfileAdmin(UserHandle user, String packageName) {
532             final List<UserInfo> userInfoList = mUm.getProfiles(user.getIdentifier());
533             for (int i = 0; i < userInfoList.size(); i++) {
534                 UserInfo userInfo = userInfoList.get(i);
535                 if (!userInfo.isManagedProfile()) {
536                     continue;
537                 }
538                 ComponentName componentName = mDpm.getProfileOwnerAsUser(userInfo.getUserHandle());
539                 if (componentName == null) {
540                     continue;
541                 }
542                 if (componentName.getPackageName().equals(packageName)) {
543                     return true;
544                 }
545             }
546             return false;
547         }
548 
549         @Override
resolveLauncherActivityInternal( String callingPackage, ComponentName component, UserHandle user)550         public LauncherActivityInfoInternal resolveLauncherActivityInternal(
551                 String callingPackage, ComponentName component, UserHandle user)
552                 throws RemoteException {
553             if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
554                 return null;
555             }
556 
557             final int callingUid = injectBinderCallingUid();
558             final long ident = Binder.clearCallingIdentity();
559             try {
560                 final ActivityInfo activityInfo = mPackageManagerInternal.getActivityInfo(component,
561                         PackageManager.MATCH_DIRECT_BOOT_AWARE
562                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
563                         callingUid, user.getIdentifier());
564                 if (activityInfo == null) {
565                     return null;
566                 }
567                 if (component == null || component.getPackageName() == null) {
568                     // should not happen
569                     return null;
570                 }
571                 final IncrementalStatesInfo incrementalStatesInfo =
572                         mPackageManagerInternal.getIncrementalStatesInfo(component.getPackageName(),
573                                 callingUid, user.getIdentifier());
574                 if (incrementalStatesInfo == null) {
575                     // package does not exist; should not happen
576                     return null;
577                 }
578                 return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo);
579             } finally {
580                 Binder.restoreCallingIdentity(ident);
581             }
582         }
583 
584         @Override
getShortcutConfigActivities( String callingPackage, String packageName, UserHandle user)585         public ParceledListSlice getShortcutConfigActivities(
586                 String callingPackage, String packageName, UserHandle user)
587                 throws RemoteException {
588             return queryActivitiesForUser(callingPackage,
589                     new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user);
590         }
591 
queryActivitiesForUser( String callingPackage, Intent intent, UserHandle user)592         private ParceledListSlice<LauncherActivityInfoInternal> queryActivitiesForUser(
593                 String callingPackage, Intent intent, UserHandle user) {
594             if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
595                 return null;
596             }
597             final int callingUid = injectBinderCallingUid();
598             long ident = injectClearCallingIdentity();
599             try {
600                 return new ParceledListSlice<>(queryIntentLauncherActivities(intent, callingUid,
601                         user));
602             } finally {
603                 injectRestoreCallingIdentity(ident);
604             }
605         }
606 
queryIntentLauncherActivities( Intent intent, int callingUid, UserHandle user)607         private List<LauncherActivityInfoInternal> queryIntentLauncherActivities(
608                 Intent intent, int callingUid, UserHandle user) {
609             final List<ResolveInfo> apps = mPackageManagerInternal.queryIntentActivities(intent,
610                     intent.resolveTypeIfNeeded(mContext.getContentResolver()),
611                     PackageManager.MATCH_DIRECT_BOOT_AWARE
612                             | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
613                     callingUid, user.getIdentifier());
614             final int numResolveInfos = apps.size();
615             List<LauncherActivityInfoInternal> results = new ArrayList<>();
616             for (int i = 0; i < numResolveInfos; i++) {
617                 final ResolveInfo ri = apps.get(i);
618                 final String packageName = ri.activityInfo.packageName;
619                 if (packageName == null) {
620                     // should not happen
621                     continue;
622                 }
623                 final IncrementalStatesInfo incrementalStatesInfo =
624                         mPackageManagerInternal.getIncrementalStatesInfo(packageName, callingUid,
625                                 user.getIdentifier());
626                 if (incrementalStatesInfo == null) {
627                     // package doesn't exist any more; should not happen
628                     continue;
629                 }
630                 results.add(new LauncherActivityInfoInternal(ri.activityInfo,
631                         incrementalStatesInfo));
632             }
633             return results;
634         }
635 
636         @Override
getShortcutConfigActivityIntent(String callingPackage, ComponentName component, UserHandle user)637         public IntentSender getShortcutConfigActivityIntent(String callingPackage,
638                 ComponentName component, UserHandle user) throws RemoteException {
639             ensureShortcutPermission(callingPackage);
640             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
641                 return null;
642             }
643             Objects.requireNonNull(component);
644 
645             // All right, create the sender.
646             final int callingUid = injectBinderCallingUid();
647             final long identity = Binder.clearCallingIdentity();
648             try {
649                 Intent packageIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT)
650                         .setPackage(component.getPackageName());
651                 List<ResolveInfo> apps =
652                         mPackageManagerInternal.queryIntentActivities(packageIntent,
653                                 packageIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
654                                 PackageManager.MATCH_DIRECT_BOOT_AWARE
655                                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
656                                 callingUid, user.getIdentifier());
657                 // ensure that the component is present in the list
658                 if (!apps.stream().anyMatch(
659                         ri -> component.getClassName().equals(ri.activityInfo.name))) {
660                     return null;
661                 }
662 
663                 Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
664                 final PendingIntent pi = PendingIntent.getActivityAsUser(
665                         mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
666                                 | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
667                         null, user);
668                 return pi == null ? null : pi.getIntentSender();
669             } finally {
670                 Binder.restoreCallingIdentity(identity);
671             }
672         }
673 
674         /**
675          * Returns the intents for a specific shortcut.
676          */
677         @Nullable
678         @Override
getShortcutIntent(@onNull final String callingPackage, @NonNull final String packageName, @NonNull final String shortcutId, @Nullable final Bundle opts, @NonNull final UserHandle user)679         public PendingIntent getShortcutIntent(@NonNull final String callingPackage,
680                 @NonNull final String packageName, @NonNull final String shortcutId,
681                 @Nullable final Bundle opts, @NonNull final UserHandle user)
682                 throws RemoteException {
683             Objects.requireNonNull(callingPackage);
684             Objects.requireNonNull(packageName);
685             Objects.requireNonNull(shortcutId);
686             Objects.requireNonNull(user);
687 
688             ensureShortcutPermission(callingPackage);
689             if (!canAccessProfile(user.getIdentifier(), "Cannot get shortcuts")) {
690                 return null;
691             }
692 
693             final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
694                     getCallingUserId(), callingPackage, packageName, shortcutId,
695                     user.getIdentifier(), injectBinderCallingPid(), injectBinderCallingUid());
696             if (intents == null || intents.length == 0) {
697                 return null;
698             }
699             final long ident = Binder.clearCallingIdentity();
700             try {
701                 return injectCreatePendingIntent(0 /* requestCode */, intents,
702                         FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT, opts, packageName,
703                         mPackageManagerInternal.getPackageUid(
704                                 packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO,
705                                 user.getIdentifier()));
706             } finally {
707                 Binder.restoreCallingIdentity(ident);
708             }
709         }
710 
711         @Override
isPackageEnabled(String callingPackage, String packageName, UserHandle user)712         public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
713                 throws RemoteException {
714             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
715                 return false;
716             }
717 
718             final int callingUid = injectBinderCallingUid();
719             final long ident = Binder.clearCallingIdentity();
720             try {
721                 final PackageInfo info = mPackageManagerInternal.getPackageInfo(packageName,
722                         PackageManager.MATCH_DIRECT_BOOT_AWARE
723                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
724                         callingUid, user.getIdentifier());
725                 return info != null && info.applicationInfo.enabled;
726             } finally {
727                 Binder.restoreCallingIdentity(ident);
728             }
729         }
730 
731         @Override
getSuspendedPackageLauncherExtras(String packageName, UserHandle user)732         public Bundle getSuspendedPackageLauncherExtras(String packageName,
733                 UserHandle user) {
734             if (!canAccessProfile(user.getIdentifier(), "Cannot get launcher extras")) {
735                 return null;
736             }
737             return mPackageManagerInternal.getSuspendedPackageLauncherExtras(packageName,
738                     user.getIdentifier());
739         }
740 
741         @Override
getApplicationInfo( String callingPackage, String packageName, int flags, UserHandle user)742         public ApplicationInfo getApplicationInfo(
743                 String callingPackage, String packageName, int flags, UserHandle user)
744                 throws RemoteException {
745             if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
746                 return null;
747             }
748 
749             final int callingUid = injectBinderCallingUid();
750             final long ident = Binder.clearCallingIdentity();
751             try {
752                 final ApplicationInfo info = mPackageManagerInternal.getApplicationInfo(packageName,
753                         flags, callingUid, user.getIdentifier());
754                 return info;
755             } finally {
756                 Binder.restoreCallingIdentity(ident);
757             }
758         }
759 
760         @Override
getAppUsageLimit(String callingPackage, String packageName, UserHandle user)761         public LauncherApps.AppUsageLimit getAppUsageLimit(String callingPackage,
762                 String packageName, UserHandle user) {
763             verifyCallingPackage(callingPackage);
764             if (!canAccessProfile(user.getIdentifier(), "Cannot access usage limit")) {
765                 return null;
766             }
767             if (!mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
768                 throw new SecurityException("Caller is not the recents app");
769             }
770 
771             final UsageStatsManagerInternal.AppUsageLimitData data =
772                     mUsageStatsManagerInternal.getAppUsageLimit(packageName, user);
773             if (data == null) {
774                 return null;
775             }
776             return new LauncherApps.AppUsageLimit(
777                     data.getTotalUsageLimit(), data.getUsageRemaining());
778         }
779 
ensureShortcutPermission(@onNull String callingPackage)780         private void ensureShortcutPermission(@NonNull String callingPackage) {
781             verifyCallingPackage(callingPackage);
782             if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
783                     callingPackage, injectBinderCallingPid(), injectBinderCallingUid())) {
784                 throw new SecurityException("Caller can't access shortcut information");
785             }
786         }
787 
ensureStrictAccessShortcutsPermission(@onNull String callingPackage)788         private void ensureStrictAccessShortcutsPermission(@NonNull String callingPackage) {
789             verifyCallingPackage(callingPackage);
790             if (!injectHasAccessShortcutsPermission(injectBinderCallingPid(),
791                     injectBinderCallingUid())) {
792                 throw new SecurityException("Caller can't access shortcut information");
793             }
794         }
795 
796         /**
797          * Returns true if the caller has the "ACCESS_SHORTCUTS" permission.
798          */
799         @VisibleForTesting
injectHasAccessShortcutsPermission(int callingPid, int callingUid)800         boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
801             return mContext.checkPermission(android.Manifest.permission.ACCESS_SHORTCUTS,
802                     callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
803         }
804 
805         /**
806          * Returns true if the caller has the "INTERACT_ACROSS_USERS_FULL" permission.
807          */
808         @VisibleForTesting
injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid)809         boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
810             return mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
811                     callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
812         }
813 
814         @VisibleForTesting
injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents, int flags, Bundle options, String ownerPackage, int ownerUserId)815         PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
816                 int flags, Bundle options, String ownerPackage, int ownerUserId) {
817             return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
818                     flags, null /* options */, ownerPackage, ownerUserId);
819         }
820 
821         @Override
getShortcuts(@onNull final String callingPackage, @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser)822         public ParceledListSlice getShortcuts(@NonNull final String callingPackage,
823                 @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser) {
824             ensureShortcutPermission(callingPackage);
825             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
826                 return new ParceledListSlice<>(Collections.EMPTY_LIST);
827             }
828 
829             final long changedSince = query.getChangedSince();
830             final String packageName = query.getPackage();
831             final List<String> shortcutIds = query.getShortcutIds();
832             final List<LocusId> locusIds = query.getLocusIds();
833             final ComponentName componentName = query.getActivity();
834             final int flags = query.getQueryFlags();
835             if (shortcutIds != null && packageName == null) {
836                 throw new IllegalArgumentException(
837                         "To query by shortcut ID, package name must also be set");
838             }
839             if (locusIds != null && packageName == null) {
840                 throw new IllegalArgumentException(
841                         "To query by locus ID, package name must also be set");
842             }
843             if ((query.getQueryFlags() & ShortcutQuery.FLAG_GET_PERSONS_DATA) != 0) {
844                 ensureStrictAccessShortcutsPermission(callingPackage);
845             }
846 
847             // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
848             return new ParceledListSlice<>((List<ShortcutInfo>)
849                     mShortcutServiceInternal.getShortcuts(getCallingUserId(),
850                             callingPackage, changedSince, packageName, shortcutIds, locusIds,
851                             componentName, flags, targetUser.getIdentifier(),
852                             injectBinderCallingPid(), injectBinderCallingUid()));
853         }
854 
855         @Override
registerShortcutChangeCallback(@onNull final String callingPackage, @NonNull final ShortcutQueryWrapper query, @NonNull final IShortcutChangeCallback callback)856         public void registerShortcutChangeCallback(@NonNull final String callingPackage,
857                 @NonNull final ShortcutQueryWrapper query,
858                 @NonNull final IShortcutChangeCallback callback) {
859 
860             ensureShortcutPermission(callingPackage);
861 
862             if (query.getShortcutIds() != null && query.getPackage() == null) {
863                 throw new IllegalArgumentException(
864                         "To query by shortcut ID, package name must also be set");
865             }
866             if (query.getLocusIds() != null && query.getPackage() == null) {
867                 throw new IllegalArgumentException(
868                         "To query by locus ID, package name must also be set");
869             }
870 
871             UserHandle user = UserHandle.of(injectCallingUserId());
872             if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(),
873                     injectBinderCallingUid())) {
874                 user = null;
875             }
876 
877             mShortcutChangeHandler.addShortcutChangeCallback(callback, query, user);
878         }
879 
880         @Override
unregisterShortcutChangeCallback(String callingPackage, IShortcutChangeCallback callback)881         public void unregisterShortcutChangeCallback(String callingPackage,
882                 IShortcutChangeCallback callback) {
883             ensureShortcutPermission(callingPackage);
884 
885             mShortcutChangeHandler.removeShortcutChangeCallback(callback);
886         }
887 
888         @Override
pinShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser)889         public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
890                 UserHandle targetUser) {
891             ensureShortcutPermission(callingPackage);
892             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) {
893                 return;
894             }
895 
896             mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
897                     callingPackage, packageName, ids, targetUser.getIdentifier());
898         }
899 
900         @Override
cacheShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser, int cacheFlags)901         public void cacheShortcuts(String callingPackage, String packageName, List<String> ids,
902                 UserHandle targetUser, int cacheFlags) {
903             ensureStrictAccessShortcutsPermission(callingPackage);
904             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot cache shortcuts")) {
905                 return;
906             }
907 
908             mShortcutServiceInternal.cacheShortcuts(
909                     getCallingUserId(), callingPackage, packageName, ids,
910                     targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags));
911         }
912 
913         @Override
uncacheShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser, int cacheFlags)914         public void uncacheShortcuts(String callingPackage, String packageName, List<String> ids,
915                 UserHandle targetUser, int cacheFlags) {
916             ensureStrictAccessShortcutsPermission(callingPackage);
917             if (!canAccessProfile(targetUser.getIdentifier(), "Cannot uncache shortcuts")) {
918                 return;
919             }
920 
921             mShortcutServiceInternal.uncacheShortcuts(
922                     getCallingUserId(), callingPackage, packageName, ids,
923                     targetUser.getIdentifier(), toShortcutsCacheFlags(cacheFlags));
924         }
925 
926         @Override
getShortcutIconResId(String callingPackage, String packageName, String id, int targetUserId)927         public int getShortcutIconResId(String callingPackage, String packageName, String id,
928                 int targetUserId) {
929             ensureShortcutPermission(callingPackage);
930             if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
931                 return 0;
932             }
933 
934             return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
935                     callingPackage, packageName, id, targetUserId);
936         }
937 
938         @Override
getShortcutIconFd(String callingPackage, String packageName, String id, int targetUserId)939         public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
940                 String packageName, String id, int targetUserId) {
941             ensureShortcutPermission(callingPackage);
942             if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
943                 return null;
944             }
945 
946             return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
947                     callingPackage, packageName, id, targetUserId);
948         }
949 
950         @Override
getShortcutIconUri(String callingPackage, String packageName, String shortcutId, int userId)951         public String getShortcutIconUri(String callingPackage, String packageName,
952                 String shortcutId, int userId) {
953             ensureShortcutPermission(callingPackage);
954             if (!canAccessProfile(userId, "Cannot access shortcuts")) {
955                 return null;
956             }
957 
958             return mShortcutServiceInternal.getShortcutIconUri(getCallingUserId(), callingPackage,
959                     packageName, shortcutId, userId);
960         }
961 
962         @Override
hasShortcutHostPermission(String callingPackage)963         public boolean hasShortcutHostPermission(String callingPackage) {
964             verifyCallingPackage(callingPackage);
965             return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
966                     callingPackage, injectBinderCallingPid(), injectBinderCallingUid());
967         }
968 
969         @Override
startShortcut(String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId)970         public boolean startShortcut(String callingPackage, String packageName, String featureId,
971                 String shortcutId, Rect sourceBounds, Bundle startActivityOptions,
972                 int targetUserId) {
973             verifyCallingPackage(callingPackage);
974             if (!canAccessProfile(targetUserId, "Cannot start activity")) {
975                 return false;
976             }
977 
978             // Even without the permission, pinned shortcuts are always launchable.
979             if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
980                     callingPackage, packageName, shortcutId, targetUserId)) {
981                 ensureShortcutPermission(callingPackage);
982             }
983 
984             final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
985                     getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId,
986                     injectBinderCallingPid(), injectBinderCallingUid());
987             if (intents == null || intents.length == 0) {
988                 return false;
989             }
990             // Note the target activity doesn't have to be exported.
991 
992             // Flag for bubble
993             ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions);
994             if (options != null && options.isApplyActivityFlagsForBubbles()) {
995                 // Flag for bubble to make behaviour match documentLaunchMode=always.
996                 intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
997                 intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
998             }
999 
1000             intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1001             intents[0].setSourceBounds(sourceBounds);
1002 
1003             // Replace theme for splash screen
1004             final String splashScreenThemeResName =
1005                     mShortcutServiceInternal.getShortcutStartingThemeResName(getCallingUserId(),
1006                             callingPackage, packageName, shortcutId, targetUserId);
1007             if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) {
1008                 if (startActivityOptions == null) {
1009                     startActivityOptions = new Bundle();
1010                 }
1011                 startActivityOptions.putString(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResName);
1012             }
1013             return startShortcutIntentsAsPublisher(
1014                     intents, packageName, featureId, startActivityOptions, targetUserId);
1015         }
1016 
startShortcutIntentsAsPublisher(@onNull Intent[] intents, @NonNull String publisherPackage, @Nullable String publishedFeatureId, Bundle startActivityOptions, int userId)1017         private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents,
1018                 @NonNull String publisherPackage, @Nullable String publishedFeatureId,
1019                 Bundle startActivityOptions, int userId) {
1020             final int code;
1021             try {
1022                 code = mActivityTaskManagerInternal.startActivitiesAsPackage(publisherPackage,
1023                         publishedFeatureId, userId, intents, startActivityOptions);
1024                 if (ActivityManager.isStartResultSuccessful(code)) {
1025                     return true; // Success
1026                 } else {
1027                     Log.e(TAG, "Couldn't start activity, code=" + code);
1028                 }
1029                 return false;
1030             } catch (SecurityException e) {
1031                 if (DEBUG) {
1032                     Slog.d(TAG, "SecurityException while launching intent", e);
1033                 }
1034                 return false;
1035             }
1036         }
1037 
1038         @Override
isActivityEnabled( String callingPackage, ComponentName component, UserHandle user)1039         public boolean isActivityEnabled(
1040                 String callingPackage, ComponentName component, UserHandle user)
1041                 throws RemoteException {
1042             if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) {
1043                 return false;
1044             }
1045 
1046             final int callingUid = injectBinderCallingUid();
1047             final int state = mPackageManagerInternal.getComponentEnabledSetting(component,
1048                     callingUid, user.getIdentifier());
1049             switch (state) {
1050                 case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT:
1051                     break; // Need to check the manifest's enabled state.
1052                 case PackageManager.COMPONENT_ENABLED_STATE_ENABLED:
1053                     return true;
1054                 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED:
1055                 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER:
1056                 case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
1057                     return false;
1058             }
1059 
1060             final long ident = Binder.clearCallingIdentity();
1061             try {
1062                 final ActivityInfo info = mPackageManagerInternal.getActivityInfo(component,
1063                         PackageManager.MATCH_DIRECT_BOOT_AWARE
1064                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1065                         callingUid, user.getIdentifier());
1066                 // Note we don't check "exported" because if the caller has the same UID as the
1067                 // callee's UID, it can still be launched.
1068                 // (If an app doesn't export a front door activity and causes issues with the
1069                 // launcher, that's just the app's bug.)
1070                 return info != null && info.isEnabled();
1071             } finally {
1072                 Binder.restoreCallingIdentity(ident);
1073             }
1074         }
1075 
1076         @Override
startSessionDetailsActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, SessionInfo sessionInfo, Rect sourceBounds, Bundle opts, UserHandle userHandle)1077         public void startSessionDetailsActivityAsUser(IApplicationThread caller,
1078                 String callingPackage, String callingFeatureId, SessionInfo sessionInfo,
1079                 Rect sourceBounds, Bundle opts, UserHandle userHandle) throws RemoteException {
1080             int userId = userHandle.getIdentifier();
1081             if (!canAccessProfile(userId, "Cannot start details activity")) {
1082                 return;
1083             }
1084 
1085             Intent i = new Intent(Intent.ACTION_VIEW)
1086                     .setData(new Uri.Builder()
1087                             .scheme("market")
1088                             .authority("details")
1089                             .appendQueryParameter("id", sessionInfo.appPackageName)
1090                             .build())
1091                     .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
1092                             .authority(callingPackage).build());
1093             i.setSourceBounds(sourceBounds);
1094 
1095             mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,
1096                     callingFeatureId, i, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK, opts,
1097                     userId);
1098         }
1099 
1100         @Override
getActivityLaunchIntent(ComponentName component, Bundle opts, UserHandle user)1101         public PendingIntent getActivityLaunchIntent(ComponentName component, Bundle opts,
1102                 UserHandle user) {
1103             if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
1104                 throw new ActivityNotFoundException("Activity could not be found");
1105             }
1106 
1107             final Intent launchIntent = getMainActivityLaunchIntent(component, user);
1108             if (launchIntent == null) {
1109                 throw new SecurityException("Attempt to launch activity without "
1110                         + " category Intent.CATEGORY_LAUNCHER " + component);
1111             }
1112 
1113             final long ident = Binder.clearCallingIdentity();
1114             try {
1115                 // If we reach here, we've verified that the caller has access to the profile and
1116                 // is launching an exported activity with CATEGORY_LAUNCHER so we can clear the
1117                 // calling identity to mirror the startActivityAsUser() call which does not validate
1118                 // the calling user
1119                 return PendingIntent.getActivityAsUser(mContext, 0 /* requestCode */, launchIntent,
1120                         FLAG_IMMUTABLE, null /* options */, user);
1121             } finally {
1122                 Binder.restoreCallingIdentity(ident);
1123             }
1124         }
1125 
1126         @Override
startActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user)1127         public void startActivityAsUser(IApplicationThread caller, String callingPackage,
1128                 String callingFeatureId, ComponentName component, Rect sourceBounds,
1129                 Bundle opts, UserHandle user) throws RemoteException {
1130             if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
1131                 return;
1132             }
1133 
1134             Intent launchIntent = getMainActivityLaunchIntent(component, user);
1135             if (launchIntent == null) {
1136                 throw new SecurityException("Attempt to launch activity without "
1137                         + " category Intent.CATEGORY_LAUNCHER " + component);
1138             }
1139             launchIntent.setSourceBounds(sourceBounds);
1140 
1141             mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,
1142                     callingFeatureId, launchIntent, /* resultTo= */ null,
1143                     Intent.FLAG_ACTIVITY_NEW_TASK, opts, user.getIdentifier());
1144         }
1145 
1146         /**
1147          * Returns the main activity launch intent for the given component package.
1148          */
getMainActivityLaunchIntent(ComponentName component, UserHandle user)1149         private Intent getMainActivityLaunchIntent(ComponentName component, UserHandle user) {
1150             Intent launchIntent = new Intent(Intent.ACTION_MAIN);
1151             launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
1152             launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
1153                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
1154             launchIntent.setPackage(component.getPackageName());
1155 
1156             boolean canLaunch = false;
1157 
1158             final int callingUid = injectBinderCallingUid();
1159             final long ident = Binder.clearCallingIdentity();
1160             try {
1161                 // Check that the component actually has Intent.CATEGORY_LAUCNCHER
1162                 // as calling startActivityAsUser ignores the category and just
1163                 // resolves based on the component if present.
1164                 final List<ResolveInfo> apps = mPackageManagerInternal.queryIntentActivities(
1165                         launchIntent,
1166                         launchIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
1167                         PackageManager.MATCH_DIRECT_BOOT_AWARE
1168                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1169                         callingUid, user.getIdentifier());
1170                 final int size = apps.size();
1171                 for (int i = 0; i < size; ++i) {
1172                     ActivityInfo activityInfo = apps.get(i).activityInfo;
1173                     if (activityInfo.packageName.equals(component.getPackageName()) &&
1174                             activityInfo.name.equals(component.getClassName())) {
1175                         if (!activityInfo.exported) {
1176                             throw new SecurityException("Cannot launch non-exported components "
1177                                     + component);
1178                         }
1179 
1180                         // Found an activity with category launcher that matches
1181                         // this component so ok to launch.
1182                         launchIntent.setPackage(null);
1183                         launchIntent.setComponent(component);
1184                         canLaunch = true;
1185                         break;
1186                     }
1187                 }
1188                 if (!canLaunch) {
1189                     return null;
1190                 }
1191             } finally {
1192                 Binder.restoreCallingIdentity(ident);
1193             }
1194             return launchIntent;
1195         }
1196 
1197         @Override
showAppDetailsAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user)1198         public void showAppDetailsAsUser(IApplicationThread caller,
1199                 String callingPackage, String callingFeatureId, ComponentName component,
1200                 Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {
1201             if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {
1202                 return;
1203             }
1204 
1205             final Intent intent;
1206             final long ident = Binder.clearCallingIdentity();
1207             try {
1208                 String packageName = component.getPackageName();
1209                 int uId = -1;
1210                 try {
1211                     uId = mContext.getPackageManager().getApplicationInfo(
1212                             packageName, PackageManager.MATCH_ANY_USER).uid;
1213                 } catch (PackageManager.NameNotFoundException e) {
1214                     Log.d(TAG, "package not found: " + e);
1215                 }
1216                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
1217                         Uri.fromParts("package", packageName, null));
1218                 intent.putExtra("uId", uId);
1219                 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1220                 intent.setSourceBounds(sourceBounds);
1221             } finally {
1222                 Binder.restoreCallingIdentity(ident);
1223             }
1224             mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,
1225                     callingFeatureId, intent, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK,
1226                     opts, user.getIdentifier());
1227         }
1228 
1229         /** Checks if user is a profile of or same as listeningUser.
1230          * and the user is enabled. */
isEnabledProfileOf(UserHandle listeningUser, UserHandle user, String debugMsg)1231         private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
1232                 String debugMsg) {
1233             return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(),
1234                     user.getIdentifier(), debugMsg, false);
1235         }
1236 
1237         /** Returns whether or not the result to the listener should be filtered. */
isPackageVisibleToListener(String packageName, BroadcastCookie cookie)1238         private boolean isPackageVisibleToListener(String packageName, BroadcastCookie cookie) {
1239             return !mPackageManagerInternal.filterAppAccess(packageName, cookie.callingUid,
1240                     cookie.user.getIdentifier());
1241         }
1242 
1243         /** Returns whether or not the given appId is in allow list */
isCallingAppIdAllowed(int[] appIdAllowList, @AppIdInt int appId)1244         private static boolean isCallingAppIdAllowed(int[] appIdAllowList, @AppIdInt int appId) {
1245             if (appIdAllowList == null) {
1246                 return true;
1247             }
1248             return Arrays.binarySearch(appIdAllowList, appId) > -1;
1249         }
1250 
getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie)1251         private String[] getFilteredPackageNames(String[] packageNames, BroadcastCookie cookie) {
1252             final List<String> filteredPackageNames = new ArrayList<>();
1253             for (String packageName : packageNames) {
1254                 if (!isPackageVisibleToListener(packageName, cookie)) {
1255                     continue;
1256                 }
1257                 filteredPackageNames.add(packageName);
1258             }
1259             return filteredPackageNames.toArray(new String[filteredPackageNames.size()]);
1260         }
1261 
toShortcutsCacheFlags(int cacheFlags)1262         private int toShortcutsCacheFlags(int cacheFlags) {
1263             int ret = 0;
1264             if (cacheFlags == FLAG_CACHE_NOTIFICATION_SHORTCUTS) {
1265                 ret = ShortcutInfo.FLAG_CACHED_NOTIFICATIONS;
1266             } else if (cacheFlags == FLAG_CACHE_BUBBLE_SHORTCUTS) {
1267                 ret = ShortcutInfo.FLAG_CACHED_BUBBLES;
1268             } else if (cacheFlags == FLAG_CACHE_PEOPLE_TILE_SHORTCUTS) {
1269                 ret = ShortcutInfo.FLAG_CACHED_PEOPLE_TILE;
1270             }
1271             Preconditions.checkArgumentPositive(ret, "Invalid cache owner");
1272 
1273             return ret;
1274         }
1275 
1276         @VisibleForTesting
postToPackageMonitorHandler(Runnable r)1277         void postToPackageMonitorHandler(Runnable r) {
1278             mCallbackHandler.post(r);
1279         }
1280 
1281         /**
1282          * Check all installed apps and if a package is installed via Incremental and not fully
1283          * loaded, register loading progress listener.
1284          */
registerLoadingProgressForIncrementalApps()1285         void registerLoadingProgressForIncrementalApps() {
1286             final List<UserHandle> users = mUm.getUserProfiles();
1287             if (users == null) {
1288                 return;
1289             }
1290             for (UserHandle user : users) {
1291                 mPackageManagerInternal.forEachInstalledPackage(pkg -> {
1292                     final String packageName = pkg.getPackageName();
1293                     if (mPackageManagerInternal.getIncrementalStatesInfo(packageName,
1294                             Process.myUid(), user.getIdentifier()).isLoading()) {
1295                         mPackageManagerInternal.registerInstalledLoadingProgressCallback(
1296                                 packageName, new PackageLoadingProgressCallback(packageName, user),
1297                                 user.getIdentifier());
1298                     }
1299                 }, user.getIdentifier());
1300             }
1301         }
1302 
1303         public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback {
1304             private final UserManagerInternal mUserManagerInternal;
1305 
ShortcutChangeHandler(UserManagerInternal userManager)1306             ShortcutChangeHandler(UserManagerInternal userManager) {
1307                 mUserManagerInternal = userManager;
1308             }
1309 
1310             private final RemoteCallbackList<IShortcutChangeCallback> mCallbacks =
1311                     new RemoteCallbackList<>();
1312 
addShortcutChangeCallback(IShortcutChangeCallback callback, ShortcutQueryWrapper query, UserHandle user)1313             public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback,
1314                     ShortcutQueryWrapper query, UserHandle user) {
1315                 mCallbacks.unregister(callback);
1316                 mCallbacks.register(callback, new Pair<>(query, user));
1317             }
1318 
removeShortcutChangeCallback( IShortcutChangeCallback callback)1319             public synchronized void removeShortcutChangeCallback(
1320                     IShortcutChangeCallback callback) {
1321                 mCallbacks.unregister(callback);
1322             }
1323 
1324             @Override
onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts, UserHandle user)1325             public void onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts,
1326                     UserHandle user) {
1327                 onShortcutEvent(packageName, shortcuts, user, false);
1328             }
1329 
1330             @Override
onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts, UserHandle user)1331             public void onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts,
1332                     UserHandle user) {
1333                 onShortcutEvent(packageName, shortcuts, user, true);
1334             }
1335 
onShortcutEvent(String packageName, List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved)1336             private void onShortcutEvent(String packageName,
1337                     List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved) {
1338                 int count = mCallbacks.beginBroadcast();
1339 
1340                 for (int i = 0; i < count; i++) {
1341                     final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i);
1342                     final Pair<ShortcutQueryWrapper, UserHandle> cookie =
1343                             (Pair<ShortcutQueryWrapper, UserHandle>)
1344                                     mCallbacks.getBroadcastCookie(i);
1345 
1346                     final UserHandle callbackUser = cookie.second;
1347                     if (callbackUser != null && !hasUserAccess(callbackUser, user)) {
1348                         // Callback owner does not have access to the shortcuts' user.
1349                         continue;
1350                     }
1351 
1352                     // Filter the list by query, if any matches exists, send via callback.
1353                     List<ShortcutInfo> matchedList = filterShortcutsByQuery(packageName, shortcuts,
1354                             cookie.first, shortcutsRemoved);
1355                     if (!CollectionUtils.isEmpty(matchedList)) {
1356                         try {
1357                             if (shortcutsRemoved) {
1358                                 callback.onShortcutsRemoved(packageName, matchedList, user);
1359                             } else {
1360                                 callback.onShortcutsAddedOrUpdated(packageName, matchedList, user);
1361                             }
1362                         } catch (RemoteException e) {
1363                             // The RemoteCallbackList will take care of removing the dead object.
1364                         }
1365                     }
1366                 }
1367 
1368                 mCallbacks.finishBroadcast();
1369             }
1370 
filterShortcutsByQuery(String packageName, List<ShortcutInfo> shortcuts, ShortcutQueryWrapper query, boolean shortcutsRemoved)1371             public static List<ShortcutInfo> filterShortcutsByQuery(String packageName,
1372                     List<ShortcutInfo> shortcuts, ShortcutQueryWrapper query,
1373                     boolean shortcutsRemoved) {
1374                 final long changedSince = query.getChangedSince();
1375                 final String queryPackage = query.getPackage();
1376                 final List<String> shortcutIds = query.getShortcutIds();
1377                 final List<LocusId> locusIds = query.getLocusIds();
1378                 final ComponentName activity = query.getActivity();
1379                 final int flags = query.getQueryFlags();
1380 
1381                 if (queryPackage != null && !queryPackage.equals(packageName)) {
1382                     return null;
1383                 }
1384 
1385                 List<ShortcutInfo> matches = new ArrayList<>();
1386 
1387                 final boolean matchDynamic = (flags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
1388                 final boolean matchPinned = (flags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
1389                 final boolean matchManifest = (flags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
1390                 final boolean matchCached = (flags & ShortcutQuery.FLAG_MATCH_CACHED) != 0;
1391                 final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
1392                         | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
1393                         | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
1394                         | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);
1395 
1396                 for (int i = 0; i < shortcuts.size(); i++) {
1397                     final ShortcutInfo si = shortcuts.get(i);
1398 
1399                     if (activity != null && !activity.equals(si.getActivity())) {
1400                         continue;
1401                     }
1402                     if (changedSince != 0 && changedSince > si.getLastChangedTimestamp()) {
1403                         continue;
1404                     }
1405                     if (shortcutIds != null && !shortcutIds.contains(si.getId())) {
1406                         continue;
1407                     }
1408                     if (locusIds != null && !locusIds.contains(si.getLocusId())) {
1409                         continue;
1410                     }
1411                     if (shortcutsRemoved || (shortcutFlags & si.getFlags()) != 0) {
1412                         matches.add(si);
1413                     }
1414                 }
1415 
1416                 return matches;
1417             }
1418 
hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser)1419             private boolean hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser) {
1420                 final int callbackUserId = callbackUser.getIdentifier();
1421                 final int shortcutUserId = shortcutUser.getIdentifier();
1422 
1423                 if (shortcutUser == callbackUser) return true;
1424                 return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId,
1425                         null, false);
1426             }
1427         }
1428 
1429         private class PackageRemovedListener extends BroadcastReceiver {
1430 
1431             @Override
onReceive(Context context, Intent intent)1432             public void onReceive(Context context, Intent intent) {
1433                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
1434                         UserHandle.USER_NULL);
1435                 if (userId == UserHandle.USER_NULL) {
1436                     Slog.w(TAG, "Intent broadcast does not contain user handle: " + intent);
1437                     return;
1438                 }
1439                 final String action = intent.getAction();
1440                 // Handle onPackageRemoved.
1441                 if (Intent.ACTION_PACKAGE_REMOVED_INTERNAL.equals(action)) {
1442                     final String packageName = getPackageName(intent);
1443                     final int[] appIdAllowList =
1444                             intent.getIntArrayExtra(Intent.EXTRA_VISIBILITY_ALLOW_LIST);
1445                     // If {@link #EXTRA_REPLACING} is true, that will be onPackageChanged case.
1446                     if (packageName != null && !intent.getBooleanExtra(
1447                             Intent.EXTRA_REPLACING, /* defaultValue= */ false)) {
1448                         final UserHandle user = new UserHandle(userId);
1449                         final int n = mListeners.beginBroadcast();
1450                         try {
1451                             for (int i = 0; i < n; i++) {
1452                                 final IOnAppsChangedListener listener =
1453                                         mListeners.getBroadcastItem(i);
1454                                 final BroadcastCookie cookie =
1455                                         (BroadcastCookie) mListeners.getBroadcastCookie(i);
1456                                 if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) {
1457                                     continue;
1458                                 }
1459                                 if (!isCallingAppIdAllowed(appIdAllowList, UserHandle.getAppId(
1460                                         cookie.callingUid))) {
1461                                     continue;
1462                                 }
1463                                 try {
1464                                     listener.onPackageRemoved(user, packageName);
1465                                 } catch (RemoteException re) {
1466                                     Slog.d(TAG, "Callback failed ", re);
1467                                 }
1468                             }
1469                         } finally {
1470                             mListeners.finishBroadcast();
1471                         }
1472                     }
1473                 }
1474             }
1475 
getPackageName(Intent intent)1476             private String getPackageName(Intent intent) {
1477                 final Uri uri = intent.getData();
1478                 final String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
1479                 return pkg;
1480             }
1481         }
1482 
1483         private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
1484 
1485             // TODO Simplify with lambdas.
1486 
1487             @Override
onPackageAdded(String packageName, int uid)1488             public void onPackageAdded(String packageName, int uid) {
1489                 UserHandle user = new UserHandle(getChangingUserId());
1490                 final int n = mListeners.beginBroadcast();
1491                 try {
1492                     for (int i = 0; i < n; i++) {
1493                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1494                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1495                         if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) {
1496                             continue;
1497                         }
1498                         if (!isPackageVisibleToListener(packageName, cookie)) {
1499                             continue;
1500                         }
1501                         try {
1502                             listener.onPackageAdded(user, packageName);
1503                         } catch (RemoteException re) {
1504                             Slog.d(TAG, "Callback failed ", re);
1505                         }
1506                     }
1507                 } finally {
1508                     mListeners.finishBroadcast();
1509                 }
1510                 super.onPackageAdded(packageName, uid);
1511                 mPackageManagerInternal.registerInstalledLoadingProgressCallback(packageName,
1512                         new PackageLoadingProgressCallback(packageName, user),
1513                         user.getIdentifier());
1514             }
1515 
1516             @Override
onPackageModified(String packageName)1517             public void onPackageModified(String packageName) {
1518                 onPackageChanged(packageName);
1519                 super.onPackageModified(packageName);
1520             }
1521 
onPackageChanged(String packageName)1522             private void onPackageChanged(String packageName) {
1523                 UserHandle user = new UserHandle(getChangingUserId());
1524                 final int n = mListeners.beginBroadcast();
1525                 try {
1526                     for (int i = 0; i < n; i++) {
1527                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1528                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1529                         if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) {
1530                             continue;
1531                         }
1532                         if (!isPackageVisibleToListener(packageName, cookie)) {
1533                             continue;
1534                         }
1535                         try {
1536                             listener.onPackageChanged(user, packageName);
1537                         } catch (RemoteException re) {
1538                             Slog.d(TAG, "Callback failed ", re);
1539                         }
1540                     }
1541                 } finally {
1542                     mListeners.finishBroadcast();
1543                 }
1544             }
1545 
1546             @Override
onPackagesAvailable(String[] packages)1547             public void onPackagesAvailable(String[] packages) {
1548                 UserHandle user = new UserHandle(getChangingUserId());
1549                 final int n = mListeners.beginBroadcast();
1550                 try {
1551                     for (int i = 0; i < n; i++) {
1552                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1553                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1554                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) {
1555                             continue;
1556                         }
1557                         final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
1558                         // If all packages are filtered, skip notifying listener.
1559                         if (ArrayUtils.isEmpty(filteredPackages)) {
1560                             continue;
1561                         }
1562                         try {
1563                             listener.onPackagesAvailable(user, filteredPackages, isReplacing());
1564                         } catch (RemoteException re) {
1565                             Slog.d(TAG, "Callback failed ", re);
1566                         }
1567                     }
1568                 } finally {
1569                     mListeners.finishBroadcast();
1570                 }
1571 
1572                 super.onPackagesAvailable(packages);
1573             }
1574 
1575             @Override
onPackagesUnavailable(String[] packages)1576             public void onPackagesUnavailable(String[] packages) {
1577                 UserHandle user = new UserHandle(getChangingUserId());
1578                 final int n = mListeners.beginBroadcast();
1579                 try {
1580                     for (int i = 0; i < n; i++) {
1581                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1582                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1583                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) {
1584                             continue;
1585                         }
1586                         final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
1587                         // If all packages are filtered, skip notifying listener.
1588                         if (ArrayUtils.isEmpty(filteredPackages)) {
1589                             continue;
1590                         }
1591                         try {
1592                             listener.onPackagesUnavailable(user, filteredPackages, isReplacing());
1593                         } catch (RemoteException re) {
1594                             Slog.d(TAG, "Callback failed ", re);
1595                         }
1596                     }
1597                 } finally {
1598                     mListeners.finishBroadcast();
1599                 }
1600 
1601                 super.onPackagesUnavailable(packages);
1602             }
1603 
1604             @Override
onPackagesSuspended(String[] packages)1605             public void onPackagesSuspended(String[] packages) {
1606                 UserHandle user = new UserHandle(getChangingUserId());
1607                 final ArrayList<Pair<String, Bundle>> packagesWithExtras = new ArrayList<>();
1608                 final ArrayList<String> packagesWithoutExtras = new ArrayList<>();
1609                 for (String pkg : packages) {
1610                     final Bundle launcherExtras =
1611                             mPackageManagerInternal.getSuspendedPackageLauncherExtras(pkg,
1612                                     user.getIdentifier());
1613                     if (launcherExtras != null) {
1614                         packagesWithExtras.add(new Pair<>(pkg, launcherExtras));
1615                     } else {
1616                         packagesWithoutExtras.add(pkg);
1617                     }
1618                 }
1619                 final String[] packagesNullExtras = packagesWithoutExtras.toArray(
1620                         new String[packagesWithoutExtras.size()]);
1621                 final int n = mListeners.beginBroadcast();
1622                 try {
1623                     for (int i = 0; i < n; i++) {
1624                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1625                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1626                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) {
1627                             continue;
1628                         }
1629                         final String[] filteredPackagesWithoutExtras =
1630                                 getFilteredPackageNames(packages, cookie);
1631                         // If all packages are filtered, skip notifying listener.
1632                         if (ArrayUtils.isEmpty(filteredPackagesWithoutExtras)) {
1633                             continue;
1634                         }
1635                         try {
1636                             listener.onPackagesSuspended(user, filteredPackagesWithoutExtras,
1637                                     /* launcherExtras= */ null);
1638                             for (int idx = 0; idx < packagesWithExtras.size(); idx++) {
1639                                 Pair<String, Bundle> packageExtraPair = packagesWithExtras.get(idx);
1640                                 if (!isPackageVisibleToListener(packageExtraPair.first, cookie)) {
1641                                     continue;
1642                                 }
1643                                 listener.onPackagesSuspended(user,
1644                                         new String[]{packageExtraPair.first},
1645                                         packageExtraPair.second);
1646                             }
1647                         } catch (RemoteException re) {
1648                             Slog.d(TAG, "Callback failed ", re);
1649                         }
1650                     }
1651                 } finally {
1652                     mListeners.finishBroadcast();
1653                 }
1654             }
1655 
1656             @Override
onPackagesUnsuspended(String[] packages)1657             public void onPackagesUnsuspended(String[] packages) {
1658                 UserHandle user = new UserHandle(getChangingUserId());
1659                 final int n = mListeners.beginBroadcast();
1660                 try {
1661                     for (int i = 0; i < n; i++) {
1662                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1663                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1664                         if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) {
1665                             continue;
1666                         }
1667                         final String[] filteredPackages = getFilteredPackageNames(packages, cookie);
1668                         // If all packages are filtered, skip notifying listener.
1669                         if (ArrayUtils.isEmpty(filteredPackages)) {
1670                             continue;
1671                         }
1672                         try {
1673                             listener.onPackagesUnsuspended(user, filteredPackages);
1674                         } catch (RemoteException re) {
1675                             Slog.d(TAG, "Callback failed ", re);
1676                         }
1677                     }
1678                 } finally {
1679                     mListeners.finishBroadcast();
1680                 }
1681 
1682                 super.onPackagesUnsuspended(packages);
1683             }
1684 
1685             @Override
onShortcutChanged(@onNull String packageName, @UserIdInt int userId)1686             public void onShortcutChanged(@NonNull String packageName,
1687                     @UserIdInt int userId) {
1688                 postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId));
1689             }
1690 
onShortcutChangedInner(@onNull String packageName, @UserIdInt int userId)1691             private void onShortcutChangedInner(@NonNull String packageName,
1692                     @UserIdInt int userId) {
1693                 final int n = mListeners.beginBroadcast();
1694                 try {
1695                     final UserHandle user = UserHandle.of(userId);
1696 
1697                     for (int i = 0; i < n; i++) {
1698                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1699                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1700                         if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) {
1701                             continue;
1702                         }
1703                         if (!isPackageVisibleToListener(packageName, cookie)) {
1704                             continue;
1705                         }
1706                         final int launcherUserId = cookie.user.getIdentifier();
1707 
1708                         // Make sure the caller has the permission.
1709                         if (!mShortcutServiceInternal.hasShortcutHostPermission(
1710                                 launcherUserId, cookie.packageName,
1711                                 cookie.callingPid, cookie.callingUid)) {
1712                             continue;
1713                         }
1714                         // Each launcher has a different set of pinned shortcuts, so we need to do a
1715                         // query in here.
1716                         // (As of now, only one launcher has the permission at a time, so it's bit
1717                         // moot, but we may change the permission model eventually.)
1718                         final List<ShortcutInfo> list =
1719                                 mShortcutServiceInternal.getShortcuts(launcherUserId,
1720                                         cookie.packageName,
1721                                         /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
1722                                         /* locusIds=*/ null, /* component= */ null,
1723                                         ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
1724                                         | ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED
1725                                         , userId, cookie.callingPid, cookie.callingUid);
1726                         try {
1727                             listener.onShortcutChanged(user, packageName,
1728                                     new ParceledListSlice<>(list));
1729                         } catch (RemoteException re) {
1730                             Slog.d(TAG, "Callback failed ", re);
1731                         }
1732 
1733                     }
1734                 } catch (RuntimeException e) {
1735                     // When the user is locked we get IllegalState, so just catch all.
1736                     Log.w(TAG, e.getMessage(), e);
1737                 } finally {
1738                     mListeners.finishBroadcast();
1739                 }
1740             }
1741 
1742             @Override
onPackageStateChanged(String packageName, int uid)1743             public void onPackageStateChanged(String packageName, int uid) {
1744                 onPackageChanged(packageName);
1745                 super.onPackageStateChanged(packageName, uid);
1746             }
1747         }
1748 
1749         class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
1750             @Override
onCallbackDied(T callback, Object cookie)1751             public void onCallbackDied(T callback, Object cookie) {
1752                 checkCallbackCount();
1753             }
1754         }
1755 
1756         class PackageLoadingProgressCallback extends
1757                 PackageManagerInternal.InstalledLoadingProgressCallback {
1758             private String mPackageName;
1759             private UserHandle mUser;
1760 
PackageLoadingProgressCallback(String packageName, UserHandle user)1761             PackageLoadingProgressCallback(String packageName, UserHandle user) {
1762                 super(mCallbackHandler);
1763                 mPackageName = packageName;
1764                 mUser = user;
1765             }
1766 
1767             @Override
onLoadingProgressChanged(float progress)1768             public void onLoadingProgressChanged(float progress) {
1769                 final int n = mListeners.beginBroadcast();
1770                 try {
1771                     for (int i = 0; i < n; i++) {
1772                         IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
1773                         BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
1774                         if (!isEnabledProfileOf(cookie.user, mUser, "onLoadingProgressChanged")) {
1775                             continue;
1776                         }
1777                         if (!isPackageVisibleToListener(mPackageName, cookie)) {
1778                             continue;
1779                         }
1780                         try {
1781                             listener.onPackageLoadingProgressChanged(mUser, mPackageName, progress);
1782                         } catch (RemoteException re) {
1783                             Slog.d(TAG, "Callback failed ", re);
1784                         }
1785                     }
1786                 } finally {
1787                     mListeners.finishBroadcast();
1788                 }
1789             }
1790         }
1791     }
1792 }
1793