LauncherAppsService.java revision b5fc2e6706dfa9884ee9d5ab802c9a66c370e9cb
14f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani/* 24f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * Copyright (C) 2014 The Android Open Source Project 34f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * 44f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 54f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * you may not use this file except in compliance with the License. 64f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * You may obtain a copy of the License at 74f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * 84f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 94f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * 104f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * Unless required by applicable law or agreed to in writing, software 114f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 124f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * See the License for the specific language governing permissions and 144f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * limitations under the License. 154f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani */ 164f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 174f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasanipackage com.android.server.pm; 184f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.annotation.NonNull; 206f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.annotation.UserIdInt; 2183f6d2da372de339dc563d6a7786be3facc52e76Makoto Onukiimport android.app.ActivityManager; 22ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onukiimport android.app.ActivityManagerInternal; 2353fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guyimport android.app.AppGlobals; 244f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.ComponentName; 254f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.Context; 264f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.Intent; 2753fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guyimport android.content.pm.ActivityInfo; 28772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guyimport android.content.pm.ApplicationInfo; 294f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.pm.ILauncherApps; 304f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.pm.IOnAppsChangedListener; 3153fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guyimport android.content.pm.IPackageManager; 324dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onukiimport android.content.pm.LauncherApps.ShortcutQuery; 3353fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guyimport android.content.pm.PackageInfo; 34cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkeyimport android.content.pm.PackageManager; 356f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.PackageManager.NameNotFoundException; 366cbc2fec91c8eae62b0ed578523af4f9765f9c17Sunny Goyalimport android.content.pm.ParceledListSlice; 374f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.pm.ResolveInfo; 386f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutInfo; 396f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutServiceInternal; 406f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; 414f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.content.pm.UserInfo; 424f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.graphics.Rect; 43466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guyimport android.net.Uri; 444f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.Binder; 454f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.Bundle; 46c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onukiimport android.os.Handler; 474f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.IInterface; 485504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onukiimport android.os.ParcelFileDescriptor; 494f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.RemoteCallbackList; 504f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.RemoteException; 514f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.UserHandle; 524f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.os.UserManager; 53466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guyimport android.provider.Settings; 54932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasaniimport android.util.Log; 554f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport android.util.Slog; 564f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 577a6a05f0ccc8c57496d0a1e2b0882ab7de3175e5Makoto Onukiimport com.android.internal.annotations.VisibleForTesting; 584f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport com.android.internal.content.PackageMonitor; 59c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onukiimport com.android.internal.os.BackgroundThread; 606f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.internal.util.Preconditions; 616f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onukiimport com.android.server.LocalServices; 62df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasaniimport com.android.server.SystemService; 634f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 64ac21497f174504472e92b99500709518b8ab2d71Makoto Onukiimport java.util.ArrayList; 654f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasaniimport java.util.List; 664f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 674f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani/** 684f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani * Service that manages requests and callbacks for launchers that support 696f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki * managed profiles. 704f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani */ 71df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasanipublic class LauncherAppsService extends SystemService { 72df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 73df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private final LauncherAppsImpl mLauncherAppsImpl; 744f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 754f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani public LauncherAppsService(Context context) { 76df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super(context); 77df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mLauncherAppsImpl = new LauncherAppsImpl(context); 784f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 794f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 804f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani @Override 81df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onStart() { 82df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani publishBinderService(Context.LAUNCHER_APPS_SERVICE, mLauncherAppsImpl); 83df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 84df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 854dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki static class BroadcastCookie { 864dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki public final UserHandle user; 874dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki public final String packageName; 884dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 894dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie(UserHandle userHandle, String packageName) { 904dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki this.user = userHandle; 914dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki this.packageName = packageName; 924dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 934dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 944dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 957a6a05f0ccc8c57496d0a1e2b0882ab7de3175e5Makoto Onuki @VisibleForTesting 966f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki static class LauncherAppsImpl extends ILauncherApps.Stub { 97df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private static final boolean DEBUG = false; 98df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private static final String TAG = "LauncherAppsService"; 99df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private final Context mContext; 100df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private final PackageManager mPm; 101df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private final UserManager mUm; 102ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki private final ActivityManagerInternal mActivityManagerInternal; 1036f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private final ShortcutServiceInternal mShortcutServiceInternal; 104df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private final PackageCallbackList<IOnAppsChangedListener> mListeners 105df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani = new PackageCallbackList<IOnAppsChangedListener>(); 106df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 1076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); 108df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 109c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki private final Handler mCallbackHandler; 110c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki 111df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public LauncherAppsImpl(Context context) { 112df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mContext = context; 113df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mPm = mContext.getPackageManager(); 114df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 115ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki mActivityManagerInternal = Preconditions.checkNotNull( 116ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki LocalServices.getService(ActivityManagerInternal.class)); 1176f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mShortcutServiceInternal = Preconditions.checkNotNull( 1186f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki LocalServices.getService(ShortcutServiceInternal.class)); 1196f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki mShortcutServiceInternal.addListener(mPackageMonitor); 120c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki mCallbackHandler = BackgroundThread.getHandler(); 121df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 122df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 1232d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki @VisibleForTesting 1242d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki int injectBinderCallingUid() { 1252d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return getCallingUid(); 1262d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 1272d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 128ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki final int injectCallingUserId() { 129ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki return UserHandle.getUserId(injectBinderCallingUid()); 130ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 131ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 132ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki @VisibleForTesting 133ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki long injectClearCallingIdentity() { 134ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki return Binder.clearCallingIdentity(); 135ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 136ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 137ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki // Injection point. 138ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki @VisibleForTesting 139ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki void injectRestoreCallingIdentity(long token) { 140ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki Binder.restoreCallingIdentity(token); 141ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 142ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 1432d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private int getCallingUserId() { 1442d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki return UserHandle.getUserId(injectBinderCallingUid()); 1452d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 1462d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 147df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /* 148df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * @see android.content.pm.ILauncherApps#addOnAppsChangedListener( 149df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * android.content.pm.IOnAppsChangedListener) 150df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 151df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 1524dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener) 1534dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki throws RemoteException { 1545ba0d3e3a3035b67d2ce3a59975145b1e0061ef4Makoto Onuki verifyCallingPackage(callingPackage); 155df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani synchronized (mListeners) { 156932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani if (DEBUG) { 157df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Log.d(TAG, "Adding listener from " + Binder.getCallingUserHandle()); 158932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } 159df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (mListeners.getRegisteredCallbackCount() == 0) { 160df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (DEBUG) { 161df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Log.d(TAG, "Starting package monitoring"); 162df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 163df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani startWatchingPackageBroadcasts(); 164df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 165df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.unregister(listener); 1664dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki mListeners.register(listener, new BroadcastCookie(UserHandle.of(getCallingUserId()), 1674dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki callingPackage)); 1684f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 1694f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 1704f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 171df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /* 172df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener( 173df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * android.content.pm.IOnAppsChangedListener) 174df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 175df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 176df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void removeOnAppsChangedListener(IOnAppsChangedListener listener) 177df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throws RemoteException { 178df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani synchronized (mListeners) { 179df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (DEBUG) { 180df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Log.d(TAG, "Removing listener from " + Binder.getCallingUserHandle()); 181df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 182df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.unregister(listener); 183df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (mListeners.getRegisteredCallbackCount() == 0) { 184df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani stopWatchingPackageBroadcasts(); 185df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 1864f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 1874f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 1884f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 189df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /** 190df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * Register a receiver to watch for package broadcasts 191df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 192df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private void startWatchingPackageBroadcasts() { 193c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki mPackageMonitor.register(mContext, UserHandle.ALL, true, mCallbackHandler); 194932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } 1954f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 196df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /** 197df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * Unregister package broadcast receiver 198df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 199df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private void stopWatchingPackageBroadcasts() { 200932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani if (DEBUG) { 201df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Log.d(TAG, "Stopped watching for packages"); 2024f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 203df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mPackageMonitor.unregister(); 2044f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 2054f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 206df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani void checkCallbackCount() { 207df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani synchronized (mListeners) { 208df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (DEBUG) { 209df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Log.d(TAG, "Callback count = " + mListeners.getRegisteredCallbackCount()); 210df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 211df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (mListeners.getRegisteredCallbackCount() == 0) { 212df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani stopWatchingPackageBroadcasts(); 213df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 2144f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 2154f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 2164f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 217df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /** 218df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * Checks if the caller is in the same group as the userToCheck. 219df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 220ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki private void ensureInUserProfiles(UserHandle userToCheck, String message) { 221abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureInUserProfiles(userToCheck.getIdentifier(), message); 222abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 223abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki 224abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki private void ensureInUserProfiles(int targetUserId, String message) { 225ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki final int callingUserId = injectCallingUserId(); 226cea2978737146485b88f06b24b5df5656f9586e1Alexandra Gherghina 227df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (targetUserId == callingUserId) return; 2284f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 229ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki long ident = injectClearCallingIdentity(); 230df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 231df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserInfo callingUserInfo = mUm.getUserInfo(callingUserId); 232df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserInfo targetUserInfo = mUm.getUserInfo(targetUserId); 233df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (targetUserInfo == null 234df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani || targetUserInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID 235df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani || targetUserInfo.profileGroupId != callingUserInfo.profileGroupId) { 236df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throw new SecurityException(message); 237df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 238df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 239ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki injectRestoreCallingIdentity(ident); 240df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 241cea2978737146485b88f06b24b5df5656f9586e1Alexandra Gherghina } 2424f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 2437a6a05f0ccc8c57496d0a1e2b0882ab7de3175e5Makoto Onuki @VisibleForTesting // We override it in unit tests 2447a6a05f0ccc8c57496d0a1e2b0882ab7de3175e5Makoto Onuki void verifyCallingPackage(String callingPackage) { 2456f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki int packageUid = -1; 2466f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki try { 2473ee7f71d5f1dc018fdafee9d890290909ad299dfMakoto Onuki packageUid = mPm.getPackageUidAsUser(callingPackage, 2488a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 2498a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE 2503ee7f71d5f1dc018fdafee9d890290909ad299dfMakoto Onuki | PackageManager.MATCH_UNINSTALLED_PACKAGES, 2513ee7f71d5f1dc018fdafee9d890290909ad299dfMakoto Onuki UserHandle.getUserId(getCallingUid())); 2526f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } catch (NameNotFoundException e) { 2536f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki Log.e(TAG, "Package not found: " + callingPackage); 2546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 2556f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki if (packageUid != Binder.getCallingUid()) { 2566f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki throw new SecurityException("Calling package name mismatch"); 2576f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 2586f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 2596f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 260df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani /** 261df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani * Checks if the user is enabled. 262df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani */ 263df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani private boolean isUserEnabled(UserHandle user) { 264abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki return isUserEnabled(user.getIdentifier()); 265abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 266abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki 267abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki private boolean isUserEnabled(int userId) { 268ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki long ident = injectClearCallingIdentity(); 269df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 270abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki UserInfo targetUserInfo = mUm.getUserInfo(userId); 271df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani return targetUserInfo != null && targetUserInfo.isEnabled(); 272df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 273ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki injectRestoreCallingIdentity(ident); 274df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 2754f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 2764f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 277df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 2786cbc2fec91c8eae62b0ed578523af4f9765f9c17Sunny Goyal public ParceledListSlice<ResolveInfo> getLauncherActivities(String packageName, UserHandle user) 279df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throws RemoteException { 280df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani ensureInUserProfiles(user, "Cannot retrieve activities for unrelated profile " + user); 281df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (!isUserEnabled(user)) { 2826cbc2fec91c8eae62b0ed578523af4f9765f9c17Sunny Goyal return null; 283df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 284cea2978737146485b88f06b24b5df5656f9586e1Alexandra Gherghina 285df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); 286df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); 287df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mainIntent.setPackage(packageName); 288df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani long ident = Binder.clearCallingIdentity(); 289df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 290cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 2918a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 2928a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 2938a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 2946cbc2fec91c8eae62b0ed578523af4f9765f9c17Sunny Goyal return new ParceledListSlice<>(apps); 295df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 296df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Binder.restoreCallingIdentity(ident); 297df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 29853fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guy } 29953fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guy 300df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 30145d3e977487da262a58bbfc5650c99a2d94aba9fSunny Goyal public ActivityInfo resolveActivity(ComponentName component, UserHandle user) 302df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throws RemoteException { 303df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani ensureInUserProfiles(user, "Cannot resolve activity for unrelated profile " + user); 304df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (!isUserEnabled(user)) { 305df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani return null; 306df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 307cea2978737146485b88f06b24b5df5656f9586e1Alexandra Gherghina 308df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani long ident = Binder.clearCallingIdentity(); 309df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 31045d3e977487da262a58bbfc5650c99a2d94aba9fSunny Goyal IPackageManager pm = AppGlobals.getPackageManager(); 31145d3e977487da262a58bbfc5650c99a2d94aba9fSunny Goyal return pm.getActivityInfo(component, 3128a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 3138a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 3148a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 315df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 316df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Binder.restoreCallingIdentity(ident); 317df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 31853fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guy } 31953fa4ec7f466e70fe3e33d15c4abfc9bb557eb10Kenny Guy 320df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 321df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public boolean isPackageEnabled(String packageName, UserHandle user) 322df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throws RemoteException { 323df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user); 324df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (!isUserEnabled(user)) { 325df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani return false; 326df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 3274f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 328df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani long ident = Binder.clearCallingIdentity(); 329df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 330df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IPackageManager pm = AppGlobals.getPackageManager(); 331cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey PackageInfo info = pm.getPackageInfo(packageName, 3328a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 3338a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 3348a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 335df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani return info != null && info.applicationInfo.enabled; 336df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 337df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Binder.restoreCallingIdentity(ident); 338df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 3394f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 3404f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 341df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 342772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy public ApplicationInfo getApplicationInfo(String packageName, int flags, UserHandle user) 343772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy throws RemoteException { 344772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user); 345772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy if (!isUserEnabled(user)) { 346772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy return null; 347772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 348772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 349772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy long ident = Binder.clearCallingIdentity(); 350772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy try { 351772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy IPackageManager pm = AppGlobals.getPackageManager(); 352772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy ApplicationInfo info = pm.getApplicationInfo(packageName, flags, 353772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy user.getIdentifier()); 354772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy return info; 355772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } finally { 356772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy Binder.restoreCallingIdentity(ident); 357772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 358772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 359772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 3602d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki private void ensureShortcutPermission(@NonNull String callingPackage, UserHandle user) { 361abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureShortcutPermission(callingPackage, user.getIdentifier()); 362abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 363abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki 364abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki private void ensureShortcutPermission(@NonNull String callingPackage, int userId) { 3652d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki verifyCallingPackage(callingPackage); 366b5fc2e6706dfa9884ee9d5ab802c9a66c370e9cbMakoto Onuki ensureInUserProfiles(userId, "Cannot access shortcuts for unrelated profile " + userId); 3672d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 368d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(), 369d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki callingPackage)) { 3702d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki throw new SecurityException("Caller can't access shortcut information"); 3712d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 3726f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 3736f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 3746f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 3756f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public ParceledListSlice getShortcuts(String callingPackage, long changedSince, 376abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki String packageName, List shortcutIds, ComponentName componentName, int flags, 377abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki UserHandle user) { 3782d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki ensureShortcutPermission(callingPackage, user); 379ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki if (!isUserEnabled(user)) { 380ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki return new ParceledListSlice<>(new ArrayList(0)); 381ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 382abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (shortcutIds != null && packageName == null) { 383abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki throw new IllegalArgumentException( 384abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki "To query by shortcut ID, package name must also be set"); 385abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki } 3866f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 387f93ce176dec4691165c78bf25fe36fbf3a93a096Felipe Leme // TODO(b/29399275): Eclipse compiler requires explicit List<ShortcutInfo> cast below. 388f93ce176dec4691165c78bf25fe36fbf3a93a096Felipe Leme return new ParceledListSlice<>((List<ShortcutInfo>) 389d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki mShortcutServiceInternal.getShortcuts(getCallingUserId(), 390abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki callingPackage, changedSince, packageName, shortcutIds, 391d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki componentName, flags, user.getIdentifier())); 3926f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 3936f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 3946f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 3956f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void pinShortcuts(String callingPackage, String packageName, List<String> ids, 396d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki UserHandle user) { 3972d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki ensureShortcutPermission(callingPackage, user); 398ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki if (!isUserEnabled(user)) { 399ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki throw new IllegalStateException("Cannot pin shortcuts for disabled profile " 400ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki + user); 401ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 4026f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 403d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki mShortcutServiceInternal.pinShortcuts(getCallingUserId(), 404d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki callingPackage, packageName, ids, user.getIdentifier()); 4056f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 4066f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 4076f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 408abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki public int getShortcutIconResId(String callingPackage, String packageName, String id, 409abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki int userId) { 410abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureShortcutPermission(callingPackage, userId); 411abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (!isUserEnabled(userId)) { 412ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki return 0; 413ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 4145504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 415d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(), 416abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki callingPackage, packageName, id, userId); 4175504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 4185504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 4195504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @Override 420abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki public ParcelFileDescriptor getShortcutIconFd(String callingPackage, 421abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki String packageName, String id, int userId) { 422abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureShortcutPermission(callingPackage, userId); 423abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (!isUserEnabled(userId)) { 424ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki return null; 425ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 4265504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 427d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(), 428abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki callingPackage, packageName, id, userId); 4295504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki } 4305504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki 4315504622fb01ab9774b5e73d05f86ee03a8b68ab7Makoto Onuki @Override 432d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki public boolean hasShortcutHostPermission(String callingPackage) { 4332d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki verifyCallingPackage(callingPackage); 434d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(), 435d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki callingPackage); 4362d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki } 4372d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki 4382d5b465fa9235e66ec176f6d6ffaaa0c18143e41Makoto Onuki @Override 43983f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki public boolean startShortcut(String callingPackage, String packageName, String shortcutId, 440abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki Rect sourceBounds, Bundle startActivityOptions, int userId) { 441d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki verifyCallingPackage(callingPackage); 442abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId); 443d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki 444abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki if (!isUserEnabled(userId)) { 445ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki throw new IllegalStateException("Cannot start a shortcut for disabled profile " 446abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki + userId); 447ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki } 448ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki 449d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki // Even without the permission, pinned shortcuts are always launchable. 450d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(), 451abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki callingPackage, packageName, shortcutId, userId)) { 452abe8442951ff88aa01ed882adb54fb1b3472ca3eMakoto Onuki ensureShortcutPermission(callingPackage, userId); 453d99c6f04bbb68f8be78f2c3ca625a3a8d5645275Makoto Onuki } 4546f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 455440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki final Intent[] intents = mShortcutServiceInternal.createShortcutIntents( 456440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki getCallingUserId(), callingPackage, packageName, shortcutId, userId); 457440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki if (intents == null || intents.length == 0) { 45883f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki return false; 45943204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki } 46043204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki // Note the target activity doesn't have to be exported. 46143204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki 4627e5c3e85420a255bd79242dd97b90340c6e3a4dfMakoto Onuki intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 4630eed441c0cf3bd03b8ac780e62fbeae5d7fcac4bMakoto Onuki intents[0].setSourceBounds(sourceBounds); 464440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki 465440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki return startShortcutIntentsAsPublisher( 466440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki intents, packageName, startActivityOptions, userId); 467ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki } 468ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki 469440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, 470ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki @NonNull String publisherPackage, Bundle startActivityOptions, int userId) { 47183f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki final int code; 47283f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki final long ident = injectClearCallingIdentity(); 47343204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki try { 474440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki code = mActivityManagerInternal.startActivitiesAsPackage(publisherPackage, 475440a1ea8e2204ecb171e0187318beb2f08f6012cMakoto Onuki userId, intents, startActivityOptions); 47683f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki if (code >= ActivityManager.START_SUCCESS) { 47783f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki return true; // Success 47883f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki } else { 47983f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki Log.e(TAG, "Couldn't start activity, code=" + code); 480ea11db15bd0cfe6ecbc44dd80a988ddf0e8c1ce7Makoto Onuki } 48183f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki return code >= ActivityManager.START_SUCCESS; 48283f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki } catch (SecurityException e) { 48383f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki if (DEBUG) { 48483f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki Slog.d(TAG, "SecurityException while launching intent", e); 48583f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki } 48683f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki return false; 48783f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki } finally { 48883f6d2da372de339dc563d6a7786be3facc52e76Makoto Onuki injectRestoreCallingIdentity(ident); 48943204b8357d781f284037fb8b7b7050ed04a2103Makoto Onuki } 4906f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 4916f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 492772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy @Override 493df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public boolean isActivityEnabled(ComponentName component, UserHandle user) 494df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throws RemoteException { 495df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani ensureInUserProfiles(user, "Cannot check component for unrelated profile " + user); 496df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (!isUserEnabled(user)) { 497df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani return false; 498932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } 499df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 500932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani long ident = Binder.clearCallingIdentity(); 501932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani try { 502df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IPackageManager pm = AppGlobals.getPackageManager(); 503cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey ActivityInfo info = pm.getActivityInfo(component, 5048a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 5058a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 5068a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 507dcf21d15456e5aca28d063aea73139e30842e6d1Winson Chung return info != null; 508932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } finally { 509932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani Binder.restoreCallingIdentity(ident); 510932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } 511932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani } 512932249db930d78131c4314ff46ec5fca76cb46cdAmith Yamasani 5134f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani @Override 514df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void startActivityAsUser(ComponentName component, Rect sourceBounds, 515df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Bundle opts, UserHandle user) throws RemoteException { 516df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user); 517df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani if (!isUserEnabled(user)) { 518df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani throw new IllegalStateException("Cannot start activity for disabled profile " + user); 5194f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 5204f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 521df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Intent launchIntent = new Intent(Intent.ACTION_MAIN); 522df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); 523347a6bd82059bc7581b1dcd229228f622c5cfca1Makoto Onuki launchIntent.setSourceBounds(sourceBounds); 524347a6bd82059bc7581b1dcd229228f622c5cfca1Makoto Onuki launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 525347a6bd82059bc7581b1dcd229228f622c5cfca1Makoto Onuki | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 5262df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy launchIntent.setPackage(component.getPackageName()); 527df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 528df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani long ident = Binder.clearCallingIdentity(); 529df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 5302df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy IPackageManager pm = AppGlobals.getPackageManager(); 531cd65448ccd13c4c2d0fe9e9623fec3a898ab9372Jeff Sharkey ActivityInfo info = pm.getActivityInfo(component, 5328a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 5338a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 5348a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 5352df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy if (!info.exported) { 5362df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy throw new SecurityException("Cannot launch non-exported components " 5372df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy + component); 5382df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy } 5392df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy 5402df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy // Check that the component actually has Intent.CATEGORY_LAUCNCHER 5412df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy // as calling startActivityAsUser ignores the category and just 5422df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy // resolves based on the component if present. 5432df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent, 5448a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey PackageManager.MATCH_DIRECT_BOOT_AWARE 5458a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, 5468a372a0a280127743ce9a7ce4b6198c7a02d2a4fJeff Sharkey user.getIdentifier()); 5472df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy final int size = apps.size(); 5482df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy for (int i = 0; i < size; ++i) { 5492df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy ActivityInfo activityInfo = apps.get(i).activityInfo; 5502df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy if (activityInfo.packageName.equals(component.getPackageName()) && 5512df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy activityInfo.name.equals(component.getClassName())) { 5522df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy // Found an activity with category launcher that matches 5532df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy // this component so ok to launch. 5542df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy launchIntent.setComponent(component); 5552df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy mContext.startActivityAsUser(launchIntent, opts, user); 5562df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy return; 5572df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy } 5582df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy } 5592df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy throw new SecurityException("Attempt to launch activity without " 5602df1892f411de6fa93ba487e3c4d23a079b74fcbKenny Guy + " category Intent.CATEGORY_LAUNCHER " + component); 561df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } finally { 562df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Binder.restoreCallingIdentity(ident); 563df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 5644f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 5654f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 566466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy @Override 567466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy public void showAppDetailsAsUser(ComponentName component, Rect sourceBounds, 568466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy Bundle opts, UserHandle user) throws RemoteException { 569466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy ensureInUserProfiles(user, "Cannot show app details for unrelated profile " + user); 570466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy if (!isUserEnabled(user)) { 571466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy throw new IllegalStateException("Cannot show app details for disabled profile " 572466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy + user); 573466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy } 574466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy 575466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy long ident = Binder.clearCallingIdentity(); 576466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy try { 577466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy String packageName = component.getPackageName(); 578466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, 579466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy Uri.fromParts("package", packageName, null)); 580369aad0e23a1ca1417018c540730915760fe2ed3Winson intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 581466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy intent.setSourceBounds(sourceBounds); 582466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy mContext.startActivityAsUser(intent, opts, user); 583466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy } finally { 584466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy Binder.restoreCallingIdentity(ident); 585466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy } 586466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy } 587466d203c4ff032477d9a6bdb077ce3cd9b4fe070Kenny Guy 5884dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki /** Checks if user is a profile of or same as listeningUser. 5894dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki * and the user is enabled. */ 590ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki private boolean isEnabledProfileOf(UserHandle user, UserHandle listeningUser, 5914dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki String debugMsg) { 5924dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (user.getIdentifier() == listeningUser.getIdentifier()) { 5934dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (DEBUG) Log.d(TAG, "Delivering msg to same user " + debugMsg); 5944dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki return true; 5954dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 596ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki long ident = injectClearCallingIdentity(); 5974dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki try { 5984dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki UserInfo userInfo = mUm.getUserInfo(user.getIdentifier()); 5994dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki UserInfo listeningUserInfo = mUm.getUserInfo(listeningUser.getIdentifier()); 6004dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (userInfo == null || listeningUserInfo == null 6014dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki || userInfo.profileGroupId == UserInfo.NO_PROFILE_GROUP_ID 6024dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki || userInfo.profileGroupId != listeningUserInfo.profileGroupId 6034dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki || !userInfo.isEnabled()) { 6044dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (DEBUG) { 6054dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki Log.d(TAG, "Not delivering msg from " + user + " to " + listeningUser + ":" 6064dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki + debugMsg); 607df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 6084dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki return false; 6094dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } else { 6104dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (DEBUG) { 6114dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki Log.d(TAG, "Delivering msg from " + user + " to " + listeningUser + ":" 6124dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki + debugMsg); 6134dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 6144dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki return true; 6154f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 6164dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } finally { 617ac21497f174504472e92b99500709518b8ab2d71Makoto Onuki injectRestoreCallingIdentity(ident); 6184f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 6194dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 6204dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 621c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki @VisibleForTesting 622aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki void postToPackageMonitorHandler(Runnable r) { 623c5475d42a45ba48477257879e7a5b2af54a23f98Makoto Onuki mCallbackHandler.post(r); 6244dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 6254dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 6264dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { 6274f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 6286f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki // TODO Simplify with lambdas. 6296f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki 630df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 631df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onPackageAdded(String packageName, int uid) { 632df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserHandle user = new UserHandle(getChangingUserId()); 633df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final int n = mListeners.beginBroadcast(); 634df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani for (int i = 0; i < n; i++) { 635df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 6364dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 6374dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackageAdded")) continue; 638df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 639df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani listener.onPackageAdded(user, packageName); 640df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } catch (RemoteException re) { 641df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Slog.d(TAG, "Callback failed ", re); 642df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 6434f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 644df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.finishBroadcast(); 645df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 646df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super.onPackageAdded(packageName, uid); 6474f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 6484f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 649df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 650df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onPackageRemoved(String packageName, int uid) { 651df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserHandle user = new UserHandle(getChangingUserId()); 652df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final int n = mListeners.beginBroadcast(); 653df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani for (int i = 0; i < n; i++) { 654df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 6554dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 6564dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackageRemoved")) continue; 657df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 658df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani listener.onPackageRemoved(user, packageName); 659df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } catch (RemoteException re) { 660df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Slog.d(TAG, "Callback failed ", re); 661df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 662df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 663df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.finishBroadcast(); 6644f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 665df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super.onPackageRemoved(packageName, uid); 666df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 667df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 668df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 669df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onPackageModified(String packageName) { 670df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserHandle user = new UserHandle(getChangingUserId()); 671df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final int n = mListeners.beginBroadcast(); 672df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani for (int i = 0; i < n; i++) { 673df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 6744dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 6754dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackageModified")) continue; 676df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 677df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani listener.onPackageChanged(user, packageName); 678df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } catch (RemoteException re) { 679df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Slog.d(TAG, "Callback failed ", re); 680df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 6814f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 682df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.finishBroadcast(); 683df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 684df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super.onPackageModified(packageName); 6854f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 6864f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 687df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 688df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onPackagesAvailable(String[] packages) { 689df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserHandle user = new UserHandle(getChangingUserId()); 690df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final int n = mListeners.beginBroadcast(); 691df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani for (int i = 0; i < n; i++) { 692df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 6934dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 6944dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackagesAvailable")) continue; 695df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 696df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani listener.onPackagesAvailable(user, packages, isReplacing()); 697df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } catch (RemoteException re) { 698df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Slog.d(TAG, "Callback failed ", re); 699df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 700df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 701df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.finishBroadcast(); 7024f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 703df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super.onPackagesAvailable(packages); 704df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 705df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 706df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 707df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onPackagesUnavailable(String[] packages) { 708df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani UserHandle user = new UserHandle(getChangingUserId()); 709df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani final int n = mListeners.beginBroadcast(); 710df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani for (int i = 0; i < n; i++) { 711df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 7124dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 7134dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnavailable")) continue; 714df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani try { 715df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani listener.onPackagesUnavailable(user, packages, isReplacing()); 716df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } catch (RemoteException re) { 717df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani Slog.d(TAG, "Callback failed ", re); 718df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 7194f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 720df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani mListeners.finishBroadcast(); 721df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani 722df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani super.onPackagesUnavailable(packages); 7234f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 7244f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 725772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy @Override 726772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy public void onPackagesSuspended(String[] packages) { 727772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy UserHandle user = new UserHandle(getChangingUserId()); 728772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy final int n = mListeners.beginBroadcast(); 729772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy for (int i = 0; i < n; i++) { 730772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 7314dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 7324dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackagesSuspended")) continue; 733772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy try { 734772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy listener.onPackagesSuspended(user, packages); 735772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } catch (RemoteException re) { 736772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy Slog.d(TAG, "Callback failed ", re); 737772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 738772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 739772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy mListeners.finishBroadcast(); 740772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 741772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy super.onPackagesSuspended(packages); 742772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 743772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 744772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy @Override 745772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy public void onPackagesUnsuspended(String[] packages) { 746772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy UserHandle user = new UserHandle(getChangingUserId()); 747772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy final int n = mListeners.beginBroadcast(); 748772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy for (int i = 0; i < n; i++) { 749772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 7504dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 7514dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onPackagesUnsuspended")) continue; 752772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy try { 753772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy listener.onPackagesUnsuspended(user, packages); 754772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } catch (RemoteException re) { 755772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy Slog.d(TAG, "Callback failed ", re); 756772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 757772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 758772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy mListeners.finishBroadcast(); 759772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 760772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy super.onPackagesUnsuspended(packages); 761772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy } 762772427555f2624b38124ab8e586ac0ccc451eb53Kenny Guy 7636f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki @Override 7646f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki public void onShortcutChanged(@NonNull String packageName, 7654dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki @UserIdInt int userId) { 766aa8b94aa79df94d77d0f7698ce532ac98f197a99Makoto Onuki postToPackageMonitorHandler(() -> onShortcutChangedInner(packageName, userId)); 7674dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki } 7684dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki 7694dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki private void onShortcutChangedInner(@NonNull String packageName, 7704dbe0ded4ae9faaef580be80184fca0749e27198Makoto Onuki @UserIdInt int userId) { 77102f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 77202f338e23d06499790c6948709afb1587416eb40Makoto Onuki final UserHandle user = UserHandle.of(userId); 77302f338e23d06499790c6948709afb1587416eb40Makoto Onuki 77402f338e23d06499790c6948709afb1587416eb40Makoto Onuki final int n = mListeners.beginBroadcast(); 77502f338e23d06499790c6948709afb1587416eb40Makoto Onuki for (int i = 0; i < n; i++) { 77602f338e23d06499790c6948709afb1587416eb40Makoto Onuki IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); 77702f338e23d06499790c6948709afb1587416eb40Makoto Onuki BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); 77802f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue; 77902f338e23d06499790c6948709afb1587416eb40Makoto Onuki 78002f338e23d06499790c6948709afb1587416eb40Makoto Onuki final int launcherUserId = cookie.user.getIdentifier(); 78102f338e23d06499790c6948709afb1587416eb40Makoto Onuki 78202f338e23d06499790c6948709afb1587416eb40Makoto Onuki // Make sure the caller has the permission. 78302f338e23d06499790c6948709afb1587416eb40Makoto Onuki if (!mShortcutServiceInternal.hasShortcutHostPermission( 78402f338e23d06499790c6948709afb1587416eb40Makoto Onuki launcherUserId, cookie.packageName)) { 78502f338e23d06499790c6948709afb1587416eb40Makoto Onuki continue; 78602f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 78702f338e23d06499790c6948709afb1587416eb40Makoto Onuki // Each launcher has a different set of pinned shortcuts, so we need to do a 78802f338e23d06499790c6948709afb1587416eb40Makoto Onuki // query in here. 78902f338e23d06499790c6948709afb1587416eb40Makoto Onuki // (As of now, only one launcher has the permission at a time, so it's bit 79002f338e23d06499790c6948709afb1587416eb40Makoto Onuki // moot, but we may change the permission model eventually.) 79102f338e23d06499790c6948709afb1587416eb40Makoto Onuki final List<ShortcutInfo> list = 79202f338e23d06499790c6948709afb1587416eb40Makoto Onuki mShortcutServiceInternal.getShortcuts(launcherUserId, 79302f338e23d06499790c6948709afb1587416eb40Makoto Onuki cookie.packageName, 79402f338e23d06499790c6948709afb1587416eb40Makoto Onuki /* changedSince= */ 0, packageName, /* shortcutIds=*/ null, 79502f338e23d06499790c6948709afb1587416eb40Makoto Onuki /* component= */ null, 79602f338e23d06499790c6948709afb1587416eb40Makoto Onuki ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY 79702f338e23d06499790c6948709afb1587416eb40Makoto Onuki | ShortcutQuery.FLAG_GET_ALL_KINDS 79802f338e23d06499790c6948709afb1587416eb40Makoto Onuki , userId); 79902f338e23d06499790c6948709afb1587416eb40Makoto Onuki try { 80002f338e23d06499790c6948709afb1587416eb40Makoto Onuki listener.onShortcutChanged(user, packageName, 80102f338e23d06499790c6948709afb1587416eb40Makoto Onuki new ParceledListSlice<>(list)); 80202f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (RemoteException re) { 80302f338e23d06499790c6948709afb1587416eb40Makoto Onuki Slog.d(TAG, "Callback failed ", re); 80402f338e23d06499790c6948709afb1587416eb40Makoto Onuki } 8056f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 80602f338e23d06499790c6948709afb1587416eb40Makoto Onuki mListeners.finishBroadcast(); 80702f338e23d06499790c6948709afb1587416eb40Makoto Onuki } catch (RuntimeException e) { 80802f338e23d06499790c6948709afb1587416eb40Makoto Onuki // When the user is locked we get IllegalState, so just catch all. 80902f338e23d06499790c6948709afb1587416eb40Makoto Onuki Log.w(TAG, e.getMessage(), e); 8106f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8116f7362d92573e4ae693bc513dca586d6a4eb087bMakoto Onuki } 8124f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 8134f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani 814df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> { 815df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani @Override 816df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani public void onCallbackDied(T callback, Object cookie) { 817df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani checkCallbackCount(); 818df7db074b5e6a19c8a33c2cc6be88f85eb5ee47cAmith Yamasani } 8194f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 8204f58263d02f296430a9653126d28501e95c7bb6cAmith Yamasani } 821b6830197450d5a2befaf0dc4f7e73850f4c55846Nicolas Prevot} 822