blob: aa9bc2637fccbfbaf204f25fa299adbc8ffb4c96 [file] [log] [blame]
Amith Yamasani4f582632014-02-19 14:31:52 -08001/*
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
17package com.android.server.pm;
18
Makoto Onuki6f7362d92016-03-04 13:39:41 -080019import android.annotation.NonNull;
20import android.annotation.UserIdInt;
Makoto Onuki83f6d2d2016-07-11 14:30:19 -070021import android.app.ActivityManager;
Makoto Onukiea11db12016-06-24 15:17:44 -070022import android.app.ActivityManagerInternal;
Ricky Waicf134eb2018-10-10 09:26:32 +010023import android.app.AppDetailsActivity;
Kenny Guy53fa4ec2014-04-29 14:24:18 +010024import android.app.AppGlobals;
Makoto Onuki1a342742018-04-26 14:56:59 -070025import android.app.IApplicationThread;
Sunny Goyala6be88a2017-01-12 16:27:58 -080026import android.app.PendingIntent;
Amith Yamasani4f582632014-02-19 14:31:52 -080027import android.content.ComponentName;
28import android.content.Context;
29import android.content.Intent;
Sunny Goyala6be88a2017-01-12 16:27:58 -080030import android.content.IntentSender;
Kenny Guy53fa4ec2014-04-29 14:24:18 +010031import android.content.pm.ActivityInfo;
Kenny Guy77242752016-01-15 13:29:06 +000032import android.content.pm.ApplicationInfo;
Amith Yamasani4f582632014-02-19 14:31:52 -080033import android.content.pm.ILauncherApps;
34import android.content.pm.IOnAppsChangedListener;
Makoto Onuki4dbe0de2016-03-14 17:31:49 -070035import android.content.pm.LauncherApps.ShortcutQuery;
Kenny Guy53fa4ec2014-04-29 14:24:18 +010036import android.content.pm.PackageInfo;
Jeff Sharkeycd654482016-01-08 17:42:11 -070037import android.content.pm.PackageManager;
Todd Kennedy18211fd2017-06-06 09:15:46 -070038import android.content.pm.PackageManagerInternal;
Sunny Goyal6cbc2fe2015-11-24 09:34:20 -080039import android.content.pm.ParceledListSlice;
Amith Yamasani4f582632014-02-19 14:31:52 -080040import android.content.pm.ResolveInfo;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080041import android.content.pm.ShortcutInfo;
42import android.content.pm.ShortcutServiceInternal;
43import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
Makoto Onukie70b29e2018-04-03 16:44:39 -070044import android.content.pm.UserInfo;
Amith Yamasani4f582632014-02-19 14:31:52 -080045import android.graphics.Rect;
Kenny Guy466d2032014-07-23 12:23:35 +010046import android.net.Uri;
Amith Yamasani4f582632014-02-19 14:31:52 -080047import android.os.Binder;
48import android.os.Bundle;
Makoto Onukic5475d42016-03-25 10:54:07 -070049import android.os.Handler;
Amith Yamasani4f582632014-02-19 14:31:52 -080050import android.os.IInterface;
Makoto Onuki55046222016-03-08 10:49:47 -080051import android.os.ParcelFileDescriptor;
Amith Yamasani4f582632014-02-19 14:31:52 -080052import android.os.RemoteCallbackList;
53import android.os.RemoteException;
54import android.os.UserHandle;
Makoto Onukie70b29e2018-04-03 16:44:39 -070055import android.os.UserManager;
Sunny Goyal145c8f82018-02-15 14:27:09 -080056import android.os.UserManagerInternal;
Kenny Guy466d2032014-07-23 12:23:35 +010057import android.provider.Settings;
Amith Yamasani932249d2014-05-01 14:39:35 -070058import android.util.Log;
Amith Yamasani4f582632014-02-19 14:31:52 -080059import android.util.Slog;
60
Makoto Onuki7a6a05f2016-03-10 17:01:08 -080061import com.android.internal.annotations.VisibleForTesting;
Amith Yamasani4f582632014-02-19 14:31:52 -080062import com.android.internal.content.PackageMonitor;
Makoto Onukic5475d42016-03-25 10:54:07 -070063import com.android.internal.os.BackgroundThread;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080064import com.android.internal.util.Preconditions;
65import com.android.server.LocalServices;
Amith Yamasanidf7db072014-06-01 10:41:13 -070066import com.android.server.SystemService;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070067import com.android.server.wm.ActivityTaskManagerInternal;
Amith Yamasani4f582632014-02-19 14:31:52 -080068
Ricky Waicf134eb2018-10-10 09:26:32 +010069import java.util.ArrayList;
Makoto Onukide3c16c2017-01-26 11:39:31 -080070import java.util.Collections;
Ricky Waicf134eb2018-10-10 09:26:32 +010071import java.util.HashSet;
Amith Yamasani4f582632014-02-19 14:31:52 -080072import java.util.List;
73
74/**
75 * Service that manages requests and callbacks for launchers that support
Makoto Onuki6f7362d92016-03-04 13:39:41 -080076 * managed profiles.
Amith Yamasani4f582632014-02-19 14:31:52 -080077 */
Amith Yamasanidf7db072014-06-01 10:41:13 -070078public class LauncherAppsService extends SystemService {
79
80 private final LauncherAppsImpl mLauncherAppsImpl;
Amith Yamasani4f582632014-02-19 14:31:52 -080081
82 public LauncherAppsService(Context context) {
Amith Yamasanidf7db072014-06-01 10:41:13 -070083 super(context);
84 mLauncherAppsImpl = new LauncherAppsImpl(context);
Amith Yamasani4f582632014-02-19 14:31:52 -080085 }
86
Amith Yamasani4f582632014-02-19 14:31:52 -080087 @Override
Amith Yamasanidf7db072014-06-01 10:41:13 -070088 public void onStart() {
89 publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl);
90 }
91
Makoto Onuki4dbe0de2016-03-14 17:31:49 -070092 static class BroadcastCookie {
93 public final UserHandle user;
94 public final String packageName;
Makoto Onuki634cecb2017-10-13 17:10:48 -070095 public final int callingUid;
96 public final int callingPid;
Makoto Onuki4dbe0de2016-03-14 17:31:49 -070097
Makoto Onuki634cecb2017-10-13 17:10:48 -070098 BroadcastCookie(UserHandle userHandle, String packageName, int callingPid, int callingUid) {
Makoto Onuki4dbe0de2016-03-14 17:31:49 -070099 this.user = userHandle;
100 this.packageName = packageName;
Makoto Onuki634cecb2017-10-13 17:10:48 -0700101 this.callingUid = callingUid;
102 this.callingPid = callingPid;
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700103 }
104 }
105
Makoto Onuki7a6a05f2016-03-10 17:01:08 -0800106 @VisibleForTesting
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800107 static class LauncherAppsImpl extends ILauncherApps.Stub {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700108 private static final boolean DEBUG = false;
109 private static final String TAG = "LauncherAppsService";
110 private final Context mContext;
Makoto Onukie70b29e2018-04-03 16:44:39 -0700111 private final UserManager mUm;
Sunny Goyal145c8f82018-02-15 14:27:09 -0800112 private final UserManagerInternal mUserManagerInternal;
Makoto Onukiea11db12016-06-24 15:17:44 -0700113 private final ActivityManagerInternal mActivityManagerInternal;
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700114 private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800115 private final ShortcutServiceInternal mShortcutServiceInternal;
Amith Yamasanidf7db072014-06-01 10:41:13 -0700116 private final PackageCallbackList<IOnAppsChangedListener> mListeners
117 = new PackageCallbackList<IOnAppsChangedListener>();
118
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800119 private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700120
Makoto Onukic5475d42016-03-25 10:54:07 -0700121 private final Handler mCallbackHandler;
122
Amith Yamasanidf7db072014-06-01 10:41:13 -0700123 public LauncherAppsImpl(Context context) {
124 mContext = context;
Makoto Onukie70b29e2018-04-03 16:44:39 -0700125 mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800126 mUserManagerInternal = Preconditions.checkNotNull(
127 LocalServices.getService(UserManagerInternal.class));
Makoto Onukiea11db12016-06-24 15:17:44 -0700128 mActivityManagerInternal = Preconditions.checkNotNull(
129 LocalServices.getService(ActivityManagerInternal.class));
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700130 mActivityTaskManagerInternal = Preconditions.checkNotNull(
131 LocalServices.getService(ActivityTaskManagerInternal.class));
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800132 mShortcutServiceInternal = Preconditions.checkNotNull(
133 LocalServices.getService(ShortcutServiceInternal.class));
134 mShortcutServiceInternal.addListener(mPackageMonitor);
Makoto Onukic5475d42016-03-25 10:54:07 -0700135 mCallbackHandler = BackgroundThread.getHandler();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700136 }
137
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800138 @VisibleForTesting
139 int injectBinderCallingUid() {
140 return getCallingUid();
141 }
142
Makoto Onuki634cecb2017-10-13 17:10:48 -0700143 @VisibleForTesting
144 int injectBinderCallingPid() {
145 return getCallingPid();
146 }
147
Makoto Onukiac214972016-04-04 10:19:45 -0700148 final int injectCallingUserId() {
149 return UserHandle.getUserId(injectBinderCallingUid());
150 }
151
152 @VisibleForTesting
153 long injectClearCallingIdentity() {
154 return Binder.clearCallingIdentity();
155 }
156
157 // Injection point.
158 @VisibleForTesting
159 void injectRestoreCallingIdentity(long token) {
160 Binder.restoreCallingIdentity(token);
161 }
162
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800163 private int getCallingUserId() {
164 return UserHandle.getUserId(injectBinderCallingUid());
165 }
166
Amith Yamasanidf7db072014-06-01 10:41:13 -0700167 /*
168 * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
169 * android.content.pm.IOnAppsChangedListener)
170 */
171 @Override
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700172 public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
173 throws RemoteException {
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -0700174 verifyCallingPackage(callingPackage);
Amith Yamasanidf7db072014-06-01 10:41:13 -0700175 synchronized (mListeners) {
Amith Yamasani932249d2014-05-01 14:39:35 -0700176 if (DEBUG) {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700177 Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle());
Amith Yamasani932249d2014-05-01 14:39:35 -0700178 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700179 if (mListeners.getRegisteredCallbackCount() == 0) {
180 if (DEBUG) {
181 Log.d(TAG, "Starting package monitoring");
182 }
183 startWatchingPackageBroadcasts();
184 }
185 mListeners.unregister(listener);
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700186 mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()),
Makoto Onuki634cecb2017-10-13 17:10:48 -0700187 callingPackage, injectBinderCallingPid(), injectBinderCallingUid()));
Amith Yamasani4f582632014-02-19 14:31:52 -0800188 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800189 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800190
Amith Yamasanidf7db072014-06-01 10:41:13 -0700191 /*
192 * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
193 * android.content.pm.IOnAppsChangedListener)
194 */
195 @Override
196 public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
197 throws RemoteException {
198 synchronized (mListeners) {
199 if (DEBUG) {
200 Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle());
201 }
202 mListeners.unregister(listener);
203 if (mListeners.getRegisteredCallbackCount() == 0) {
204 stopWatchingPackageBroadcasts();
205 }
206 }
207 }
208
209 /**
210 * Register a receiver to watch for package broadcasts
211 */
212 private void startWatchingPackageBroadcasts() {
Makoto Onukic5475d42016-03-25 10:54:07 -0700213 mPackageMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler);
Amith Yamasanidf7db072014-06-01 10:41:13 -0700214 }
215
216 /**
217 * Unregister package broadcast receiver
218 */
219 private void stopWatchingPackageBroadcasts() {
Amith Yamasani932249d2014-05-01 14:39:35 -0700220 if (DEBUG) {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700221 Log.d(TAG, "Stopped watching for packages");
Amith Yamasani932249d2014-05-01 14:39:35 -0700222 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700223 mPackageMonitor.unregister();
224 }
225
226 void checkCallbackCount() {
227 synchronized (mListeners) {
228 if (DEBUG) {
229 Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount());
230 }
231 if (mListeners.getRegisteredCallbackCount() == 0) {
232 stopWatchingPackageBroadcasts();
233 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800234 }
235 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800236
Makoto Onukide3c16c2017-01-26 11:39:31 -0800237 /**
238 * Checks if the calling user is in the same group as {@code targetUser}, and allowed
239 * to access it.
240 *
241 * @return TRUE if the calling user can access {@code targetUserId}. FALSE if not *but
242 * they're still in the same profile group*.
243 *
244 * @throws SecurityException if the calling user and {@code targetUser} are not in the same
245 * group.
246 */
Sunny Goyal145c8f82018-02-15 14:27:09 -0800247 private boolean canAccessProfile(int targetUserId, String message) {
Makoto Onukie70b29e2018-04-03 16:44:39 -0700248 final int callingUserId = injectCallingUserId();
249
250 if (targetUserId == callingUserId) return true;
251
252 long ident = injectClearCallingIdentity();
253 try {
254 final UserInfo callingUserInfo = mUm.getUserInfo(callingUserId);
255 if (callingUserInfo != null && callingUserInfo.isManagedProfile()) {
256 Slog.w(TAG, message + " for another profile "
257 + targetUserId + " from " + callingUserId + " not allowed");
258 return false;
259 }
260 } finally {
261 injectRestoreCallingIdentity(ident);
262 }
263
Sunny Goyal145c8f82018-02-15 14:27:09 -0800264 return mUserManagerInternal.isProfileAccessible(injectCallingUserId(), targetUserId,
265 message, true);
Amith Yamasani932249d2014-05-01 14:39:35 -0700266 }
267
Makoto Onuki7a6a05f2016-03-10 17:01:08 -0800268 @VisibleForTesting // We override it in unit tests
269 void verifyCallingPackage(String callingPackage) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800270 int packageUid = -1;
271 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700272 packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600273 PackageManager.MATCH_DIRECT_BOOT_AWARE
274 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
Makoto Onuki3ee7f712016-03-10 17:28:55 -0800275 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
276 UserHandle.getUserId(getCallingUid()));
Todd Kennedy18211fd2017-06-06 09:15:46 -0700277 } catch (RemoteException ignore) {
278 }
279 if (packageUid < 0) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800280 Log.e(TAG, "Package not found: " + callingPackage);
281 }
Todd Kennedy18211fd2017-06-06 09:15:46 -0700282 if (packageUid != injectBinderCallingUid()) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800283 throw new SecurityException("Calling package name mismatch");
284 }
285 }
286
Ricky Waicf134eb2018-10-10 09:26:32 +0100287 private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
288 UserHandle user) {
289 Intent intent = new Intent();
290 intent.setComponent(new ComponentName(packageName, AppDetailsActivity.class.getName()));
291 final PackageManagerInternal pmInt =
292 LocalServices.getService(PackageManagerInternal.class);
293 List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
294 PackageManager.MATCH_DIRECT_BOOT_AWARE
295 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
296 callingUid, user.getIdentifier());
297 if (apps.size() > 0) {
298 return apps.get(0);
299 }
300 return null;
301 }
302
Amith Yamasani4f582632014-02-19 14:31:52 -0800303 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800304 public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
Ricky Waicf134eb2018-10-10 09:26:32 +0100305 String packageName, UserHandle user) throws RemoteException {
306 ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser(
307 callingPackage,
Sunny Goyala6be88a2017-01-12 16:27:58 -0800308 new Intent(Intent.ACTION_MAIN)
309 .addCategory(Intent.CATEGORY_LAUNCHER)
310 .setPackage(packageName),
311 user);
Ricky Wai13b0abe2018-10-23 11:03:02 +0100312 if (Settings.Global.getInt(mContext.getContentResolver(),
Michal Karpinski217d5972018-11-07 15:18:21 +0000313 Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) {
Ricky Waicf134eb2018-10-10 09:26:32 +0100314 return launcherActivities;
315 }
Ricky Wai10ceaf92019-01-14 10:39:40 +0000316 if (launcherActivities == null) {
317 // Cannot access profile, so we don't even return any hidden apps.
318 return null;
319 }
Ricky Waicf134eb2018-10-10 09:26:32 +0100320
321 final int callingUid = injectBinderCallingUid();
322 final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
Michal Karpinski6d5795f2018-11-06 15:18:30 +0000323 final PackageManagerInternal pmInt =
324 LocalServices.getService(PackageManagerInternal.class);
Ricky Waicf134eb2018-10-10 09:26:32 +0100325 if (packageName != null) {
Michal Karpinski6d5795f2018-11-06 15:18:30 +0000326 // If this hidden app should not be shown, return the original list.
327 // Otherwise, inject hidden activity that forwards user to app details page.
Ricky Waicf134eb2018-10-10 09:26:32 +0100328 if (result.size() > 0) {
329 return launcherActivities;
330 }
Michal Karpinski6d5795f2018-11-06 15:18:30 +0000331 ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0,
332 callingUid, user.getIdentifier());
333 if (shouldShowHiddenApp(appInfo)) {
334 ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
335 if (info != null) {
336 result.add(info);
337 }
Ricky Waicf134eb2018-10-10 09:26:32 +0100338 }
339 return new ParceledListSlice<>(result);
340 }
341
342 long ident = injectClearCallingIdentity();
343 try {
344 final HashSet<String> visiblePackages = new HashSet<>();
345 for (ResolveInfo info : result) {
346 visiblePackages.add(info.activityInfo.packageName);
347 }
Ricky Waicf134eb2018-10-10 09:26:32 +0100348 List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
349 user.getIdentifier(), callingUid);
350 for (ApplicationInfo applicationInfo : installedPackages) {
351 if (!visiblePackages.contains(applicationInfo.packageName)) {
352 if (!shouldShowHiddenApp(applicationInfo)) {
353 continue;
354 }
355 ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName,
356 callingUid, user);
357 if (info != null) {
358 result.add(info);
359 }
360 }
361 }
362 return new ParceledListSlice<>(result);
363 } finally {
364 injectRestoreCallingIdentity(ident);
365 }
366 }
367
368 private static boolean shouldShowHiddenApp(ApplicationInfo appInfo) {
Michal Karpinski08404a952018-11-15 17:46:00 +0000369 if (appInfo == null || appInfo.isSystemApp() || appInfo.isUpdatedSystemApp()) {
Ricky Waicf134eb2018-10-10 09:26:32 +0100370 return false;
371 }
372 return true;
Amith Yamasani4f582632014-02-19 14:31:52 -0800373 }
374
375 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800376 public ActivityInfo resolveActivity(
377 String callingPackage, ComponentName component, UserHandle user)
Amith Yamasanidf7db072014-06-01 10:41:13 -0700378 throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800379 if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700380 return null;
Amith Yamasani4f582632014-02-19 14:31:52 -0800381 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800382
Todd Kennedy18211fd2017-06-06 09:15:46 -0700383 final int callingUid = injectBinderCallingUid();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700384 long ident = Binder.clearCallingIdentity();
385 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700386 final PackageManagerInternal pmInt =
387 LocalServices.getService(PackageManagerInternal.class);
388 return pmInt.getActivityInfo(component,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600389 PackageManager.MATCH_DIRECT_BOOT_AWARE
390 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Todd Kennedy18211fd2017-06-06 09:15:46 -0700391 callingUid, user.getIdentifier());
Amith Yamasanidf7db072014-06-01 10:41:13 -0700392 } finally {
393 Binder.restoreCallingIdentity(ident);
394 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800395 }
396
397 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800398 public ParceledListSlice getShortcutConfigActivities(
399 String callingPackage, String packageName, UserHandle user)
Sunny Goyala6be88a2017-01-12 16:27:58 -0800400 throws RemoteException {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800401 return queryActivitiesForUser(callingPackage,
Sunny Goyala6be88a2017-01-12 16:27:58 -0800402 new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user);
403 }
404
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800405 private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage,
406 Intent intent, UserHandle user) {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800407 if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
Sunny Goyala6be88a2017-01-12 16:27:58 -0800408 return null;
409 }
410
Todd Kennedy18211fd2017-06-06 09:15:46 -0700411 final int callingUid = injectBinderCallingUid();
Sunny Goyala6be88a2017-01-12 16:27:58 -0800412 long ident = injectClearCallingIdentity();
413 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700414 final PackageManagerInternal pmInt =
415 LocalServices.getService(PackageManagerInternal.class);
416 List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
Sunny Goyala6be88a2017-01-12 16:27:58 -0800417 PackageManager.MATCH_DIRECT_BOOT_AWARE
418 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Todd Kennedy18211fd2017-06-06 09:15:46 -0700419 callingUid, user.getIdentifier());
Sunny Goyala6be88a2017-01-12 16:27:58 -0800420 return new ParceledListSlice<>(apps);
421 } finally {
422 injectRestoreCallingIdentity(ident);
423 }
424 }
425
426 @Override
427 public IntentSender getShortcutConfigActivityIntent(String callingPackage,
428 ComponentName component, UserHandle user) throws RemoteException {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800429 ensureShortcutPermission(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800430 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800431 return null;
432 }
Sunny Goyala6be88a2017-01-12 16:27:58 -0800433 Preconditions.checkNotNull(component);
Sunny Goyala6be88a2017-01-12 16:27:58 -0800434
435 // All right, create the sender.
436 Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(component);
437 final long identity = Binder.clearCallingIdentity();
438 try {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800439 final PendingIntent pi = PendingIntent.getActivityAsUser(
Sunny Goyala6be88a2017-01-12 16:27:58 -0800440 mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT
441 | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_CANCEL_CURRENT,
Makoto Onukide3c16c2017-01-26 11:39:31 -0800442 null, user);
443 return pi == null ? null : pi.getIntentSender();
Sunny Goyala6be88a2017-01-12 16:27:58 -0800444 } finally {
445 Binder.restoreCallingIdentity(identity);
446 }
447 }
448
449 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800450 public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
Amith Yamasanidf7db072014-06-01 10:41:13 -0700451 throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800452 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700453 return false;
Amith Yamasani4f582632014-02-19 14:31:52 -0800454 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800455
Todd Kennedy18211fd2017-06-06 09:15:46 -0700456 final int callingUid = injectBinderCallingUid();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700457 long ident = Binder.clearCallingIdentity();
458 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700459 final PackageManagerInternal pmInt =
460 LocalServices.getService(PackageManagerInternal.class);
461 PackageInfo info = pmInt.getPackageInfo(packageName,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600462 PackageManager.MATCH_DIRECT_BOOT_AWARE
463 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Todd Kennedy18211fd2017-06-06 09:15:46 -0700464 callingUid, user.getIdentifier());
Amith Yamasanidf7db072014-06-01 10:41:13 -0700465 return info != null && info.applicationInfo.enabled;
466 } finally {
467 Binder.restoreCallingIdentity(ident);
468 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800469 }
470
471 @Override
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700472 public Bundle getSuspendedPackageLauncherExtras(String packageName,
473 UserHandle user) {
474 if (!canAccessProfile(user.getIdentifier(), "Cannot get launcher extras")) {
475 return null;
476 }
477 final PackageManagerInternal pmi =
478 LocalServices.getService(PackageManagerInternal.class);
479 return pmi.getSuspendedPackageLauncherExtras(packageName, user.getIdentifier());
480 }
481
482 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800483 public ApplicationInfo getApplicationInfo(
484 String callingPackage, String packageName, int flags, UserHandle user)
Kenny Guy77242752016-01-15 13:29:06 +0000485 throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800486 if (!canAccessProfile(user.getIdentifier(), "Cannot check package")) {
Kenny Guy77242752016-01-15 13:29:06 +0000487 return null;
488 }
489
Todd Kennedy18211fd2017-06-06 09:15:46 -0700490 final int callingUid = injectBinderCallingUid();
Kenny Guy77242752016-01-15 13:29:06 +0000491 long ident = Binder.clearCallingIdentity();
492 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700493 final PackageManagerInternal pmInt =
494 LocalServices.getService(PackageManagerInternal.class);
495 ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags,
496 callingUid, user.getIdentifier());
Kenny Guy77242752016-01-15 13:29:06 +0000497 return info;
498 } finally {
499 Binder.restoreCallingIdentity(ident);
500 }
501 }
502
Makoto Onukide3c16c2017-01-26 11:39:31 -0800503 private void ensureShortcutPermission(@NonNull String callingPackage) {
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800504 verifyCallingPackage(callingPackage);
Makoto Onukid99c6f02016-03-28 11:02:54 -0700505 if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
Makoto Onuki634cecb2017-10-13 17:10:48 -0700506 callingPackage, injectBinderCallingPid(), injectBinderCallingUid())) {
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800507 throw new SecurityException("Caller can't access shortcut information");
508 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800509 }
510
511 @Override
512 public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
Makoto Onuki99302b52017-03-29 12:42:26 -0700513 String packageName, List shortcutIds, ComponentName componentName, int flags,
514 UserHandle targetUser) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800515 ensureShortcutPermission(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800516 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800517 return new ParceledListSlice<>(Collections.EMPTY_LIST);
Makoto Onukiac214972016-04-04 10:19:45 -0700518 }
Makoto Onukiabe84422016-04-07 09:41:19 -0700519 if (shortcutIds != null && packageName == null) {
520 throw new IllegalArgumentException(
521 "To query by shortcut ID, package name must also be set");
522 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800523
Felipe Lemef93ce172016-06-13 14:19:40 -0700524 // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below.
525 return new ParceledListSlice<>((List<ShortcutInfo>)
Makoto Onukid99c6f02016-03-28 11:02:54 -0700526 mShortcutServiceInternal.getShortcuts(getCallingUserId(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700527 callingPackage, changedSince, packageName, shortcutIds,
Makoto Onuki634cecb2017-10-13 17:10:48 -0700528 componentName, flags, targetUser.getIdentifier(),
529 injectBinderCallingPid(), injectBinderCallingUid()));
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800530 }
531
532 @Override
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800533 public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
Makoto Onukide3c16c2017-01-26 11:39:31 -0800534 UserHandle targetUser) {
535 ensureShortcutPermission(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800536 if (!canAccessProfile(targetUser.getIdentifier(), "Cannot pin shortcuts")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800537 return;
538 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800539
Makoto Onukid99c6f02016-03-28 11:02:54 -0700540 mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
Makoto Onukide3c16c2017-01-26 11:39:31 -0800541 callingPackage, packageName, ids, targetUser.getIdentifier());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800542 }
543
544 @Override
Makoto Onukiabe84422016-04-07 09:41:19 -0700545 public int getShortcutIconResId(String callingPackage, String packageName, String id,
Makoto Onukide3c16c2017-01-26 11:39:31 -0800546 int targetUserId) {
547 ensureShortcutPermission(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800548 if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
Makoto Onukiac214972016-04-04 10:19:45 -0700549 return 0;
550 }
Makoto Onuki55046222016-03-08 10:49:47 -0800551
Makoto Onukid99c6f02016-03-28 11:02:54 -0700552 return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
Makoto Onukide3c16c2017-01-26 11:39:31 -0800553 callingPackage, packageName, id, targetUserId);
Makoto Onuki55046222016-03-08 10:49:47 -0800554 }
555
556 @Override
Makoto Onukiabe84422016-04-07 09:41:19 -0700557 public ParcelFileDescriptor getShortcutIconFd(String callingPackage,
Makoto Onukide3c16c2017-01-26 11:39:31 -0800558 String packageName, String id, int targetUserId) {
559 ensureShortcutPermission(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800560 if (!canAccessProfile(targetUserId, "Cannot access shortcuts")) {
Makoto Onukiac214972016-04-04 10:19:45 -0700561 return null;
562 }
Makoto Onuki55046222016-03-08 10:49:47 -0800563
Makoto Onukid99c6f02016-03-28 11:02:54 -0700564 return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
Makoto Onukide3c16c2017-01-26 11:39:31 -0800565 callingPackage, packageName, id, targetUserId);
Makoto Onuki55046222016-03-08 10:49:47 -0800566 }
567
568 @Override
Makoto Onukid99c6f02016-03-28 11:02:54 -0700569 public boolean hasShortcutHostPermission(String callingPackage) {
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800570 verifyCallingPackage(callingPackage);
Makoto Onukid99c6f02016-03-28 11:02:54 -0700571 return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
Makoto Onuki634cecb2017-10-13 17:10:48 -0700572 callingPackage, injectBinderCallingPid(), injectBinderCallingUid());
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800573 }
574
575 @Override
Makoto Onuki83f6d2d2016-07-11 14:30:19 -0700576 public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
Makoto Onukide3c16c2017-01-26 11:39:31 -0800577 Rect sourceBounds, Bundle startActivityOptions, int targetUserId) {
Makoto Onukid99c6f02016-03-28 11:02:54 -0700578 verifyCallingPackage(callingPackage);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800579 if (!canAccessProfile(targetUserId, "Cannot start activity")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800580 return false;
581 }
Makoto Onukiac214972016-04-04 10:19:45 -0700582
Makoto Onukid99c6f02016-03-28 11:02:54 -0700583 // Even without the permission, pinned shortcuts are always launchable.
584 if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
Makoto Onukide3c16c2017-01-26 11:39:31 -0800585 callingPackage, packageName, shortcutId, targetUserId)) {
586 ensureShortcutPermission(callingPackage);
Makoto Onukid99c6f02016-03-28 11:02:54 -0700587 }
588
Makoto Onuki440a1ea2016-07-20 14:21:18 -0700589 final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
Makoto Onuki634cecb2017-10-13 17:10:48 -0700590 getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId,
591 injectBinderCallingPid(), injectBinderCallingUid());
Makoto Onuki440a1ea2016-07-20 14:21:18 -0700592 if (intents == null || intents.length == 0) {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -0700593 return false;
Makoto Onuki43204b82016-03-08 16:16:44 -0800594 }
595 // Note the target activity doesn't have to be exported.
596
Makoto Onuki7e5c3e82016-07-22 11:57:05 -0700597 intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Makoto Onuki0eed4412016-07-21 11:21:59 -0700598 intents[0].setSourceBounds(sourceBounds);
Makoto Onuki440a1ea2016-07-20 14:21:18 -0700599
600 return startShortcutIntentsAsPublisher(
Makoto Onukide3c16c2017-01-26 11:39:31 -0800601 intents, packageName, startActivityOptions, targetUserId);
Makoto Onukiea11db12016-06-24 15:17:44 -0700602 }
603
Makoto Onuki440a1ea2016-07-20 14:21:18 -0700604 private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents,
Makoto Onukiea11db12016-06-24 15:17:44 -0700605 @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -0700606 final int code;
Makoto Onuki43204b82016-03-08 16:16:44 -0800607 try {
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700608 code = mActivityTaskManagerInternal.startActivitiesAsPackage(publisherPackage,
Makoto Onuki440a1ea2016-07-20 14:21:18 -0700609 userId, intents, startActivityOptions);
Bryce Lee7f936862017-05-09 15:33:18 -0700610 if (ActivityManager.isStartResultSuccessful(code)) {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -0700611 return true; // Success
612 } else {
613 Log.e(TAG, "Couldn't start activity, code=" + code);
Makoto Onukiea11db12016-06-24 15:17:44 -0700614 }
Bryce Lee7f936862017-05-09 15:33:18 -0700615 return false;
Makoto Onuki83f6d2d2016-07-11 14:30:19 -0700616 } catch (SecurityException e) {
617 if (DEBUG) {
618 Slog.d(TAG, "SecurityException while launching intent", e);
619 }
620 return false;
Makoto Onuki43204b82016-03-08 16:16:44 -0800621 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800622 }
623
Kenny Guy77242752016-01-15 13:29:06 +0000624 @Override
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800625 public boolean isActivityEnabled(
626 String callingPackage, ComponentName component, UserHandle user)
Amith Yamasanidf7db072014-06-01 10:41:13 -0700627 throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800628 if (!canAccessProfile(user.getIdentifier(), "Cannot check component")) {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700629 return false;
Amith Yamasani4f582632014-02-19 14:31:52 -0800630 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800631
Todd Kennedy18211fd2017-06-06 09:15:46 -0700632 final int callingUid = injectBinderCallingUid();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700633 long ident = Binder.clearCallingIdentity();
634 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700635 final PackageManagerInternal pmInt =
636 LocalServices.getService(PackageManagerInternal.class);
637 ActivityInfo info = pmInt.getActivityInfo(component,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600638 PackageManager.MATCH_DIRECT_BOOT_AWARE
639 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Todd Kennedy18211fd2017-06-06 09:15:46 -0700640 callingUid, user.getIdentifier());
Winson Chungdcf21d152014-10-01 14:30:05 -0700641 return info != null;
Amith Yamasanidf7db072014-06-01 10:41:13 -0700642 } finally {
643 Binder.restoreCallingIdentity(ident);
644 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800645 }
646
Amith Yamasani4f582632014-02-19 14:31:52 -0800647 @Override
Makoto Onuki1a342742018-04-26 14:56:59 -0700648 public void startActivityAsUser(IApplicationThread caller, String callingPackage,
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800649 ComponentName component, Rect sourceBounds,
Amith Yamasanidf7db072014-06-01 10:41:13 -0700650 Bundle opts, UserHandle user) throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800651 if (!canAccessProfile(user.getIdentifier(), "Cannot start activity")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800652 return;
653 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700654
655 Intent launchIntent = new Intent(Intent.ACTION_MAIN);
656 launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700657 launchIntent.setSourceBounds(sourceBounds);
658 launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
659 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Kenny Guy2df18922014-07-17 13:01:25 +0100660 launchIntent.setPackage(component.getPackageName());
Amith Yamasanidf7db072014-06-01 10:41:13 -0700661
Makoto Onuki1a342742018-04-26 14:56:59 -0700662 boolean canLaunch = false;
663
Todd Kennedy18211fd2017-06-06 09:15:46 -0700664 final int callingUid = injectBinderCallingUid();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700665 long ident = Binder.clearCallingIdentity();
666 try {
Todd Kennedy18211fd2017-06-06 09:15:46 -0700667 final PackageManagerInternal pmInt =
668 LocalServices.getService(PackageManagerInternal.class);
Kenny Guy2df18922014-07-17 13:01:25 +0100669 // Check that the component actually has Intent.CATEGORY_LAUCNCHER
670 // as calling startActivityAsUser ignores the category and just
671 // resolves based on the component if present.
Todd Kennedy18211fd2017-06-06 09:15:46 -0700672 List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
Jeff Sharkey8a372a02016-03-16 16:25:45 -0600673 PackageManager.MATCH_DIRECT_BOOT_AWARE
674 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
Todd Kennedy18211fd2017-06-06 09:15:46 -0700675 callingUid, user.getIdentifier());
Kenny Guy2df18922014-07-17 13:01:25 +0100676 final int size = apps.size();
677 for (int i = 0; i < size; ++i) {
678 ActivityInfo activityInfo = apps.get(i).activityInfo;
679 if (activityInfo.packageName.equals(component.getPackageName()) &&
680 activityInfo.name.equals(component.getClassName())) {
Sunny Goyal06ef5af2018-10-16 15:32:41 -0700681 if (!activityInfo.exported) {
682 throw new SecurityException("Cannot launch non-exported components "
683 + component);
684 }
685
Kenny Guy2df18922014-07-17 13:01:25 +0100686 // Found an activity with category launcher that matches
687 // this component so ok to launch.
Tony Mak12917c62018-01-15 15:17:13 +0000688 launchIntent.setPackage(null);
Kenny Guy2df18922014-07-17 13:01:25 +0100689 launchIntent.setComponent(component);
Makoto Onuki1a342742018-04-26 14:56:59 -0700690 canLaunch = true;
691 break;
Kenny Guy2df18922014-07-17 13:01:25 +0100692 }
693 }
Makoto Onuki1a342742018-04-26 14:56:59 -0700694 if (!canLaunch) {
695 throw new SecurityException("Attempt to launch activity without "
696 + " category Intent.CATEGORY_LAUNCHER " + component);
697 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700698 } finally {
699 Binder.restoreCallingIdentity(ident);
700 }
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700701 mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,
Makoto Onuki1a342742018-04-26 14:56:59 -0700702 launchIntent, opts, user.getIdentifier());
Amith Yamasanidf7db072014-06-01 10:41:13 -0700703 }
704
Kenny Guy466d2032014-07-23 12:23:35 +0100705 @Override
Makoto Onuki1a342742018-04-26 14:56:59 -0700706 public void showAppDetailsAsUser(IApplicationThread caller,
707 String callingPackage, ComponentName component,
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800708 Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800709 if (!canAccessProfile(user.getIdentifier(), "Cannot show app details")) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800710 return;
711 }
Kenny Guy466d2032014-07-23 12:23:35 +0100712
Makoto Onuki1a342742018-04-26 14:56:59 -0700713 final Intent intent;
Kenny Guy466d2032014-07-23 12:23:35 +0100714 long ident = Binder.clearCallingIdentity();
715 try {
716 String packageName = component.getPackageName();
Makoto Onuki1a342742018-04-26 14:56:59 -0700717 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Kenny Guy466d2032014-07-23 12:23:35 +0100718 Uri.fromParts("package", packageName, null));
Winson369aad02016-02-17 10:35:47 -0800719 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Kenny Guy466d2032014-07-23 12:23:35 +0100720 intent.setSourceBounds(sourceBounds);
Kenny Guy466d2032014-07-23 12:23:35 +0100721 } finally {
722 Binder.restoreCallingIdentity(ident);
723 }
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700724 mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage,
Makoto Onuki1a342742018-04-26 14:56:59 -0700725 intent, opts, user.getIdentifier());
Kenny Guy466d2032014-07-23 12:23:35 +0100726 }
727
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700728 /** Checks if user is a profile of or same as listeningUser.
729 * and the user is enabled. */
Sunny Goyal145c8f82018-02-15 14:27:09 -0800730 private boolean isEnabledProfileOf(UserHandle listeningUser, UserHandle user,
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700731 String debugMsg) {
Sunny Goyal145c8f82018-02-15 14:27:09 -0800732 return mUserManagerInternal.isProfileAccessible(listeningUser.getIdentifier(),
733 user.getIdentifier(), debugMsg, false);
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700734 }
735
Makoto Onukic5475d42016-03-25 10:54:07 -0700736 @VisibleForTesting
Makoto Onukiaa8b94a2016-03-17 13:14:05 -0700737 void postToPackageMonitorHandler(Runnable r) {
Makoto Onukic5475d42016-03-25 10:54:07 -0700738 mCallbackHandler.post(r);
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700739 }
740
741 private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
Amith Yamasanidf7db072014-06-01 10:41:13 -0700742
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800743 // TODO Simplify with lambdas.
744
Amith Yamasanidf7db072014-06-01 10:41:13 -0700745 @Override
746 public void onPackageAdded(String packageName, int uid) {
747 UserHandle user = new UserHandle(getChangingUserId());
748 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700749 try {
750 for (int i = 0; i < n; i++) {
751 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
752 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800753 if (!isEnabledProfileOf(cookie.user, user, "onPackageAdded")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700754 try {
755 listener.onPackageAdded(user, packageName);
756 } catch (RemoteException re) {
757 Slog.d(TAG, "Callback failed ", re);
758 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700759 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700760 } finally {
761 mListeners.finishBroadcast();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700762 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700763
764 super.onPackageAdded(packageName, uid);
765 }
766
767 @Override
768 public void onPackageRemoved(String packageName, int uid) {
769 UserHandle user = new UserHandle(getChangingUserId());
770 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700771 try {
772 for (int i = 0; i < n; i++) {
773 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
774 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800775 if (!isEnabledProfileOf(cookie.user, user, "onPackageRemoved")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700776 try {
777 listener.onPackageRemoved(user, packageName);
778 } catch (RemoteException re) {
779 Slog.d(TAG, "Callback failed ", re);
780 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700781 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700782 } finally {
783 mListeners.finishBroadcast();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700784 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700785
786 super.onPackageRemoved(packageName, uid);
787 }
788
789 @Override
790 public void onPackageModified(String packageName) {
791 UserHandle user = new UserHandle(getChangingUserId());
792 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700793 try {
794 for (int i = 0; i < n; i++) {
795 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
796 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800797 if (!isEnabledProfileOf(cookie.user, user, "onPackageModified")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700798 try {
799 listener.onPackageChanged(user, packageName);
800 } catch (RemoteException re) {
801 Slog.d(TAG, "Callback failed ", re);
802 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700803 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700804 } finally {
805 mListeners.finishBroadcast();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700806 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700807
808 super.onPackageModified(packageName);
809 }
810
811 @Override
812 public void onPackagesAvailable(String[] packages) {
813 UserHandle user = new UserHandle(getChangingUserId());
814 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700815 try {
816 for (int i = 0; i < n; i++) {
817 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
818 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800819 if (!isEnabledProfileOf(cookie.user, user, "onPackagesAvailable")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700820 try {
821 listener.onPackagesAvailable(user, packages, isReplacing());
822 } catch (RemoteException re) {
823 Slog.d(TAG, "Callback failed ", re);
824 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700825 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700826 } finally {
827 mListeners.finishBroadcast();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700828 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700829
830 super.onPackagesAvailable(packages);
831 }
832
833 @Override
834 public void onPackagesUnavailable(String[] packages) {
835 UserHandle user = new UserHandle(getChangingUserId());
836 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700837 try {
838 for (int i = 0; i < n; i++) {
839 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
840 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800841 if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnavailable")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700842 try {
843 listener.onPackagesUnavailable(user, packages, isReplacing());
844 } catch (RemoteException re) {
845 Slog.d(TAG, "Callback failed ", re);
846 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700847 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700848 } finally {
849 mListeners.finishBroadcast();
Amith Yamasanidf7db072014-06-01 10:41:13 -0700850 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700851
852 super.onPackagesUnavailable(packages);
853 }
854
Kenny Guy77242752016-01-15 13:29:06 +0000855 @Override
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700856 public void onPackagesSuspended(String[] packages, Bundle launcherExtras) {
Kenny Guy77242752016-01-15 13:29:06 +0000857 UserHandle user = new UserHandle(getChangingUserId());
858 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700859 try {
860 for (int i = 0; i < n; i++) {
861 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
862 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800863 if (!isEnabledProfileOf(cookie.user, user, "onPackagesSuspended")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700864 try {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700865 listener.onPackagesSuspended(user, packages, launcherExtras);
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700866 } catch (RemoteException re) {
867 Slog.d(TAG, "Callback failed ", re);
868 }
Kenny Guy77242752016-01-15 13:29:06 +0000869 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700870 } finally {
871 mListeners.finishBroadcast();
Kenny Guy77242752016-01-15 13:29:06 +0000872 }
Kenny Guy77242752016-01-15 13:29:06 +0000873
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700874 super.onPackagesSuspended(packages, launcherExtras);
Kenny Guy77242752016-01-15 13:29:06 +0000875 }
876
877 @Override
878 public void onPackagesUnsuspended(String[] packages) {
879 UserHandle user = new UserHandle(getChangingUserId());
880 final int n = mListeners.beginBroadcast();
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700881 try {
882 for (int i = 0; i < n; i++) {
883 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
884 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800885 if (!isEnabledProfileOf(cookie.user, user, "onPackagesUnsuspended")) continue;
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700886 try {
887 listener.onPackagesUnsuspended(user, packages);
888 } catch (RemoteException re) {
889 Slog.d(TAG, "Callback failed ", re);
890 }
Kenny Guy77242752016-01-15 13:29:06 +0000891 }
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700892 } finally {
893 mListeners.finishBroadcast();
Kenny Guy77242752016-01-15 13:29:06 +0000894 }
Kenny Guy77242752016-01-15 13:29:06 +0000895
896 super.onPackagesUnsuspended(packages);
897 }
898
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800899 @Override
900 public void onShortcutChanged(@NonNull String packageName,
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700901 @UserIdInt int userId) {
Makoto Onukiaa8b94a2016-03-17 13:14:05 -0700902 postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId));
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700903 }
904
905 private void onShortcutChangedInner(@NonNull String packageName,
906 @UserIdInt int userId) {
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700907 final int n = mListeners.beginBroadcast();
Makoto Onuki02f338e2016-07-29 09:40:40 -0700908 try {
909 final UserHandle user = UserHandle.of(userId);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800910
Makoto Onuki02f338e2016-07-29 09:40:40 -0700911 for (int i = 0; i < n; i++) {
912 IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
913 BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
Sunny Goyal145c8f82018-02-15 14:27:09 -0800914 if (!isEnabledProfileOf(cookie.user, user, "onShortcutChanged")) continue;
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800915
Makoto Onuki02f338e2016-07-29 09:40:40 -0700916 final int launcherUserId = cookie.user.getIdentifier();
Makoto Onukid99c6f02016-03-28 11:02:54 -0700917
Makoto Onuki02f338e2016-07-29 09:40:40 -0700918 // Make sure the caller has the permission.
919 if (!mShortcutServiceInternal.hasShortcutHostPermission(
Makoto Onuki634cecb2017-10-13 17:10:48 -0700920 launcherUserId, cookie.packageName,
921 cookie.callingPid, cookie.callingUid)) {
Makoto Onuki02f338e2016-07-29 09:40:40 -0700922 continue;
923 }
924 // Each launcher has a different set of pinned shortcuts, so we need to do a
925 // query in here.
926 // (As of now, only one launcher has the permission at a time, so it's bit
927 // moot, but we may change the permission model eventually.)
928 final List<ShortcutInfo> list =
929 mShortcutServiceInternal.getShortcuts(launcherUserId,
930 cookie.packageName,
931 /* changedSince= */ 0, packageName, /* shortcutIds=*/ null,
932 /* component= */ null,
933 ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
Makoto Onuki634cecb2017-10-13 17:10:48 -0700934 | ShortcutQuery.FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED
935 , userId, cookie.callingPid, cookie.callingUid);
Makoto Onuki02f338e2016-07-29 09:40:40 -0700936 try {
937 listener.onShortcutChanged(user, packageName,
938 new ParceledListSlice<>(list));
939 } catch (RemoteException re) {
940 Slog.d(TAG, "Callback failed ", re);
941 }
Makoto Onuki4dbe0de2016-03-14 17:31:49 -0700942 }
Makoto Onuki02f338e2016-07-29 09:40:40 -0700943 } catch (RuntimeException e) {
944 // When the user is locked we get IllegalState, so just catch all.
945 Log.w(TAG, e.getMessage(), e);
Makoto Onuki7bdb9ce2016-09-15 12:52:57 -0700946 } finally {
947 mListeners.finishBroadcast();
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800948 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800949 }
Amith Yamasanidf7db072014-06-01 10:41:13 -0700950 }
951
952 class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
953 @Override
954 public void onCallbackDied(T callback, Object cookie) {
955 checkCallbackCount();
956 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800957 }
958 }
Nicolas Prevotb6830192015-06-26 13:45:12 -0700959}