Loading core/java/android/content/pm/ILauncherApps.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -95,9 +95,9 @@ interface ILauncherApps { void registerShortcutChangeCallback(String callingPackage, long changedSince, String packageName, in List shortcutIds, in List<LocusId> locusIds, in ComponentName componentName, int flags, in IShortcutChangeCallback callback, int callbackId); void unregisterShortcutChangeCallback(String callingPackage, int callbackId); in ComponentName componentName, int flags, in IShortcutChangeCallback callback); void unregisterShortcutChangeCallback(String callingPackage, in IShortcutChangeCallback callback); void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds, in UserHandle user); Loading core/java/android/content/pm/LauncherApps.java +10 −13 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.content.pm; import static android.Manifest.permission; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; Loading Loading @@ -161,7 +162,7 @@ public class LauncherApps { private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>(); private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>(); private final Map<Integer, Pair<Executor, ShortcutChangeCallback>> private final Map<ShortcutChangeCallback, Pair<Executor, IShortcutChangeCallback>> mShortcutChangeCallbacks = new HashMap<>(); /** Loading Loading @@ -549,8 +550,8 @@ public class LauncherApps { android.content.pm.IShortcutChangeCallback.Stub { private final WeakReference<Pair<Executor, ShortcutChangeCallback>> mRemoteReferences; ShortcutChangeCallbackProxy(Pair<Executor, ShortcutChangeCallback> remoteReferences) { mRemoteReferences = new WeakReference<>(remoteReferences); ShortcutChangeCallbackProxy(Executor executor, ShortcutChangeCallback callback) { mRemoteReferences = new WeakReference<>(new Pair<>(executor, callback)); } @Override Loading Loading @@ -1753,14 +1754,12 @@ public class LauncherApps { Objects.requireNonNull(executor, "Executor cannot be null"); synchronized (mShortcutChangeCallbacks) { final int callbackId = callback.hashCode(); final Pair<Executor, ShortcutChangeCallback> state = new Pair<>(executor, callback); mShortcutChangeCallbacks.put(callbackId, state); IShortcutChangeCallback proxy = new ShortcutChangeCallbackProxy(executor, callback); mShortcutChangeCallbacks.put(callback, new Pair<>(executor, proxy)); try { mService.registerShortcutChangeCallback(mContext.getPackageName(), query.mChangedSince, query.mPackage, query.mShortcutIds, query.mLocusIds, query.mActivity, query.mQueryFlags, new ShortcutChangeCallbackProxy(state), callbackId); query.mActivity, query.mQueryFlags, proxy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -1779,12 +1778,10 @@ public class LauncherApps { Objects.requireNonNull(callback, "Callback cannot be null"); synchronized (mShortcutChangeCallbacks) { final int callbackId = callback.hashCode(); if (mShortcutChangeCallbacks.containsKey(callbackId)) { mShortcutChangeCallbacks.remove(callbackId); if (mShortcutChangeCallbacks.containsKey(callback)) { IShortcutChangeCallback proxy = mShortcutChangeCallbacks.remove(callback).second; try { mService.unregisterShortcutChangeCallback(mContext.getPackageName(), callbackId); mService.unregisterShortcutChangeCallback(mContext.getPackageName(), proxy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading core/java/android/content/pm/ShortcutServiceInternal.java +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,9 @@ public abstract class ShortcutServiceInternal { public abstract void addListener(@NonNull ShortcutChangeListener listener); public abstract void addShortcutChangeCallback( @NonNull LauncherApps.ShortcutChangeCallback callback); public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId); Loading services/core/java/com/android/server/pm/LauncherAppsService.java +180 −3 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.parsing.pkg.AndroidPackage; Loading Loading @@ -134,6 +135,8 @@ public class LauncherAppsService extends SystemService { private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); private final ShortcutChangeHandler mShortcutChangeHandler; private final Handler mCallbackHandler; private PackageInstallerService mPackageInstallerService; Loading @@ -153,6 +156,8 @@ public class LauncherAppsService extends SystemService { mShortcutServiceInternal = Objects.requireNonNull( LocalServices.getService(ShortcutServiceInternal.class)); mShortcutServiceInternal.addListener(mPackageMonitor); mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal); mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler); mCallbackHandler = BackgroundThread.getHandler(); mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); } Loading Loading @@ -720,12 +725,37 @@ public class LauncherAppsService extends SystemService { @Override public void registerShortcutChangeCallback(String callingPackage, long changedSince, String packageName, List shortcutIds, List<LocusId> locusIds, ComponentName componentName, int flags, IShortcutChangeCallback callback, int callbackId) { ComponentName componentName, int flags, IShortcutChangeCallback callback) { ensureShortcutPermission(callingPackage); if (shortcutIds != null && packageName == null) { throw new IllegalArgumentException( "To query by shortcut ID, package name must also be set"); } if (locusIds != null && packageName == null) { throw new IllegalArgumentException( "To query by locus ID, package name must also be set"); } UserHandle user = UserHandle.of(injectCallingUserId()); if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED) { user = null; } // TODO: When ShortcutQueryWrapper (ag/10323729) is available, pass that directly. ShortcutChangeHandler.QueryInfo query = new ShortcutChangeHandler.QueryInfo( changedSince, packageName, shortcutIds, locusIds, componentName, flags, user); mShortcutChangeHandler.addShortcutChangeCallback(callback, query); } @Override public void unregisterShortcutChangeCallback(String callingPackage, int callbackId) { public void unregisterShortcutChangeCallback(String callingPackage, IShortcutChangeCallback callback) { ensureShortcutPermission(callingPackage); mShortcutChangeHandler.removeShortcutChangeCallback(callback); } @Override Loading Loading @@ -1005,6 +1035,153 @@ public class LauncherAppsService extends SystemService { mCallbackHandler.post(r); } public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback { static class QueryInfo { final long mChangedSince; final String mPackage; final List<String> mShortcutIds; final List<LocusId> mLocusIds; final ComponentName mActivity; final int mQueryFlags; final UserHandle mCallbackUser; QueryInfo(long changedSince, String packageName, List<String> shortcutIds, List<LocusId> locusIds, ComponentName activity, int flags, UserHandle callbackUser) { mChangedSince = changedSince; mPackage = packageName; mShortcutIds = shortcutIds; mLocusIds = locusIds; mActivity = activity; mQueryFlags = flags; mCallbackUser = callbackUser; } } private final UserManagerInternal mUserManagerInternal; ShortcutChangeHandler(UserManagerInternal userManager) { mUserManagerInternal = userManager; } private final RemoteCallbackList<IShortcutChangeCallback> mCallbacks = new RemoteCallbackList<>(); public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback, QueryInfo query) { mCallbacks.unregister(callback); mCallbacks.register(callback, query); } public synchronized void removeShortcutChangeCallback( IShortcutChangeCallback callback) { mCallbacks.unregister(callback); } @Override public void onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts, UserHandle user) { onShortcutEvent(packageName, shortcuts, user, false); } @Override public void onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts, UserHandle user) { onShortcutEvent(packageName, shortcuts, user, true); } private void onShortcutEvent(String packageName, List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved) { int count = mCallbacks.beginBroadcast(); for (int i = 0; i < count; i++) { final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i); final QueryInfo query = (QueryInfo) mCallbacks.getBroadcastCookie(i); if (query.mCallbackUser != null && !hasUserAccess(query.mCallbackUser, user)) { // Callback owner does not have access to the shortcuts' user. continue; } // Filter the list by query, if any matches exists, send via callback. List<ShortcutInfo> matchedList = filterShortcutsByQuery(packageName, shortcuts, query); if (!CollectionUtils.isEmpty(matchedList)) { try { if (shortcutsRemoved) { callback.onShortcutsRemoved(packageName, matchedList, user); } else { callback.onShortcutsAddedOrUpdated(packageName, matchedList, user); } } catch (RemoteException e) { // The RemoteCallbackList will take care of removing the dead object. } } } mCallbacks.finishBroadcast(); } public static List<ShortcutInfo> filterShortcutsByQuery(String packageName, List<ShortcutInfo> shortcuts, QueryInfo query) { if (query.mPackage != null && query.mPackage != packageName) { return null; } List<ShortcutInfo> matches = new ArrayList<>(); final boolean matchDynamic = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0; final boolean matchPinned = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0; final boolean matchManifest = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0; final boolean matchCached = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_CACHED) != 0; final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0) | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0) | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0) | (matchCached ? ShortcutInfo.FLAG_CACHED : 0); for (int i = 0; i < shortcuts.size(); i++) { final ShortcutInfo si = shortcuts.get(i); if (query.mActivity != null && !query.mActivity.equals(si.getActivity())) { continue; } if (query.mChangedSince != 0 && query.mChangedSince > si.getLastChangedTimestamp()) { continue; } if (query.mShortcutIds != null && !query.mShortcutIds.contains(si.getId())) { continue; } if (query.mLocusIds != null && !query.mLocusIds.contains(si.getLocusId())) { continue; } if ((shortcutFlags & si.getFlags()) != 0) { matches.add(si); } } return matches; } private boolean hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser) { final int callbackUserId = callbackUser.getIdentifier(); final int shortcutUserId = shortcutUser.getIdentifier(); if (shortcutUser == callbackUser) return true; return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId, null, false); } } private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { // TODO Simplify with lambdas. Loading services/core/java/com/android/server/pm/ShortcutPackage.java +25 −9 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.server.pm.ShortcutService.DumpFilter; Loading Loading @@ -365,9 +366,12 @@ class ShortcutPackage extends ShortcutPackageItem { /** * Remove all shortcuts that aren't pinned, cached nor dynamic. * * @return List of removed shortcuts. */ private void removeOrphans() { private List<ShortcutInfo> removeOrphans() { ArrayList<String> removeList = null; // Lazily initialize. List<ShortcutInfo> removedShortcuts = null; for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); Loading @@ -376,20 +380,26 @@ class ShortcutPackage extends ShortcutPackageItem { if (removeList == null) { removeList = new ArrayList<>(); removedShortcuts = new ArrayList<>(); } removeList.add(si.getId()); removedShortcuts.add(si); } if (removeList != null) { for (int i = removeList.size() - 1; i >= 0; i--) { forceDeleteShortcutInner(removeList.get(i)); } } return removedShortcuts; } /** * Remove all dynamic shortcuts. * * @return List of shortcuts that actually got removed. */ public void deleteAllDynamicShortcuts(boolean ignoreInvisible) { public List<ShortcutInfo> deleteAllDynamicShortcuts(boolean ignoreInvisible) { final long now = mShortcutUser.mService.injectCurrentTimeMillis(); boolean changed = false; Loading @@ -404,8 +414,9 @@ class ShortcutPackage extends ShortcutPackageItem { } } if (changed) { removeOrphans(); return removeOrphans(); } return null; } /** Loading Loading @@ -1028,7 +1039,8 @@ class ShortcutPackage extends ShortcutPackageItem { s.verifyStates(); // This will send a notification to the launcher, and also save . s.packageShortcutsChanged(getPackageName(), getPackageUserId()); // TODO: List changed and removed manifest shortcuts and pass to packageShortcutsChanged() s.packageShortcutsChanged(getPackageName(), getPackageUserId(), null, null); return true; // true means changed. } Loading Loading @@ -1299,15 +1311,14 @@ class ShortcutPackage extends ShortcutPackageItem { */ public void resolveResourceStrings() { final ShortcutService s = mShortcutUser.mService; boolean changed = false; List<ShortcutInfo> changedShortcuts = null; Resources publisherRes = null; for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); if (si.hasStringResources()) { changed = true; if (publisherRes == null) { publisherRes = getPackageResources(); if (publisherRes == null) { Loading @@ -1317,10 +1328,15 @@ class ShortcutPackage extends ShortcutPackageItem { si.resolveResourceStrings(publisherRes); si.setTimestamp(s.injectCurrentTimeMillis()); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } changedShortcuts.add(si); } if (changed) { s.packageShortcutsChanged(getPackageName(), getPackageUserId()); } if (!CollectionUtils.isEmpty(changedShortcuts)) { s.packageShortcutsChanged(getPackageName(), getPackageUserId(), changedShortcuts, null); } } Loading Loading
core/java/android/content/pm/ILauncherApps.aidl +3 −3 Original line number Diff line number Diff line Loading @@ -95,9 +95,9 @@ interface ILauncherApps { void registerShortcutChangeCallback(String callingPackage, long changedSince, String packageName, in List shortcutIds, in List<LocusId> locusIds, in ComponentName componentName, int flags, in IShortcutChangeCallback callback, int callbackId); void unregisterShortcutChangeCallback(String callingPackage, int callbackId); in ComponentName componentName, int flags, in IShortcutChangeCallback callback); void unregisterShortcutChangeCallback(String callingPackage, in IShortcutChangeCallback callback); void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds, in UserHandle user); Loading
core/java/android/content/pm/LauncherApps.java +10 −13 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.content.pm; import static android.Manifest.permission; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; Loading Loading @@ -161,7 +162,7 @@ public class LauncherApps { private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>(); private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>(); private final Map<Integer, Pair<Executor, ShortcutChangeCallback>> private final Map<ShortcutChangeCallback, Pair<Executor, IShortcutChangeCallback>> mShortcutChangeCallbacks = new HashMap<>(); /** Loading Loading @@ -549,8 +550,8 @@ public class LauncherApps { android.content.pm.IShortcutChangeCallback.Stub { private final WeakReference<Pair<Executor, ShortcutChangeCallback>> mRemoteReferences; ShortcutChangeCallbackProxy(Pair<Executor, ShortcutChangeCallback> remoteReferences) { mRemoteReferences = new WeakReference<>(remoteReferences); ShortcutChangeCallbackProxy(Executor executor, ShortcutChangeCallback callback) { mRemoteReferences = new WeakReference<>(new Pair<>(executor, callback)); } @Override Loading Loading @@ -1753,14 +1754,12 @@ public class LauncherApps { Objects.requireNonNull(executor, "Executor cannot be null"); synchronized (mShortcutChangeCallbacks) { final int callbackId = callback.hashCode(); final Pair<Executor, ShortcutChangeCallback> state = new Pair<>(executor, callback); mShortcutChangeCallbacks.put(callbackId, state); IShortcutChangeCallback proxy = new ShortcutChangeCallbackProxy(executor, callback); mShortcutChangeCallbacks.put(callback, new Pair<>(executor, proxy)); try { mService.registerShortcutChangeCallback(mContext.getPackageName(), query.mChangedSince, query.mPackage, query.mShortcutIds, query.mLocusIds, query.mActivity, query.mQueryFlags, new ShortcutChangeCallbackProxy(state), callbackId); query.mActivity, query.mQueryFlags, proxy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading @@ -1779,12 +1778,10 @@ public class LauncherApps { Objects.requireNonNull(callback, "Callback cannot be null"); synchronized (mShortcutChangeCallbacks) { final int callbackId = callback.hashCode(); if (mShortcutChangeCallbacks.containsKey(callbackId)) { mShortcutChangeCallbacks.remove(callbackId); if (mShortcutChangeCallbacks.containsKey(callback)) { IShortcutChangeCallback proxy = mShortcutChangeCallbacks.remove(callback).second; try { mService.unregisterShortcutChangeCallback(mContext.getPackageName(), callbackId); mService.unregisterShortcutChangeCallback(mContext.getPackageName(), proxy); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
core/java/android/content/pm/ShortcutServiceInternal.java +3 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,9 @@ public abstract class ShortcutServiceInternal { public abstract void addListener(@NonNull ShortcutChangeListener listener); public abstract void addShortcutChangeCallback( @NonNull LauncherApps.ShortcutChangeCallback callback); public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage, @NonNull String packageName, @NonNull String shortcutId, int userId); Loading
services/core/java/com/android/server/pm/LauncherAppsService.java +180 −3 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.parsing.pkg.AndroidPackage; Loading Loading @@ -134,6 +135,8 @@ public class LauncherAppsService extends SystemService { private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); private final ShortcutChangeHandler mShortcutChangeHandler; private final Handler mCallbackHandler; private PackageInstallerService mPackageInstallerService; Loading @@ -153,6 +156,8 @@ public class LauncherAppsService extends SystemService { mShortcutServiceInternal = Objects.requireNonNull( LocalServices.getService(ShortcutServiceInternal.class)); mShortcutServiceInternal.addListener(mPackageMonitor); mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal); mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler); mCallbackHandler = BackgroundThread.getHandler(); mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); } Loading Loading @@ -720,12 +725,37 @@ public class LauncherAppsService extends SystemService { @Override public void registerShortcutChangeCallback(String callingPackage, long changedSince, String packageName, List shortcutIds, List<LocusId> locusIds, ComponentName componentName, int flags, IShortcutChangeCallback callback, int callbackId) { ComponentName componentName, int flags, IShortcutChangeCallback callback) { ensureShortcutPermission(callingPackage); if (shortcutIds != null && packageName == null) { throw new IllegalArgumentException( "To query by shortcut ID, package name must also be set"); } if (locusIds != null && packageName == null) { throw new IllegalArgumentException( "To query by locus ID, package name must also be set"); } UserHandle user = UserHandle.of(injectCallingUserId()); if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) == PackageManager.PERMISSION_GRANTED) { user = null; } // TODO: When ShortcutQueryWrapper (ag/10323729) is available, pass that directly. ShortcutChangeHandler.QueryInfo query = new ShortcutChangeHandler.QueryInfo( changedSince, packageName, shortcutIds, locusIds, componentName, flags, user); mShortcutChangeHandler.addShortcutChangeCallback(callback, query); } @Override public void unregisterShortcutChangeCallback(String callingPackage, int callbackId) { public void unregisterShortcutChangeCallback(String callingPackage, IShortcutChangeCallback callback) { ensureShortcutPermission(callingPackage); mShortcutChangeHandler.removeShortcutChangeCallback(callback); } @Override Loading Loading @@ -1005,6 +1035,153 @@ public class LauncherAppsService extends SystemService { mCallbackHandler.post(r); } public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback { static class QueryInfo { final long mChangedSince; final String mPackage; final List<String> mShortcutIds; final List<LocusId> mLocusIds; final ComponentName mActivity; final int mQueryFlags; final UserHandle mCallbackUser; QueryInfo(long changedSince, String packageName, List<String> shortcutIds, List<LocusId> locusIds, ComponentName activity, int flags, UserHandle callbackUser) { mChangedSince = changedSince; mPackage = packageName; mShortcutIds = shortcutIds; mLocusIds = locusIds; mActivity = activity; mQueryFlags = flags; mCallbackUser = callbackUser; } } private final UserManagerInternal mUserManagerInternal; ShortcutChangeHandler(UserManagerInternal userManager) { mUserManagerInternal = userManager; } private final RemoteCallbackList<IShortcutChangeCallback> mCallbacks = new RemoteCallbackList<>(); public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback, QueryInfo query) { mCallbacks.unregister(callback); mCallbacks.register(callback, query); } public synchronized void removeShortcutChangeCallback( IShortcutChangeCallback callback) { mCallbacks.unregister(callback); } @Override public void onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts, UserHandle user) { onShortcutEvent(packageName, shortcuts, user, false); } @Override public void onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts, UserHandle user) { onShortcutEvent(packageName, shortcuts, user, true); } private void onShortcutEvent(String packageName, List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved) { int count = mCallbacks.beginBroadcast(); for (int i = 0; i < count; i++) { final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i); final QueryInfo query = (QueryInfo) mCallbacks.getBroadcastCookie(i); if (query.mCallbackUser != null && !hasUserAccess(query.mCallbackUser, user)) { // Callback owner does not have access to the shortcuts' user. continue; } // Filter the list by query, if any matches exists, send via callback. List<ShortcutInfo> matchedList = filterShortcutsByQuery(packageName, shortcuts, query); if (!CollectionUtils.isEmpty(matchedList)) { try { if (shortcutsRemoved) { callback.onShortcutsRemoved(packageName, matchedList, user); } else { callback.onShortcutsAddedOrUpdated(packageName, matchedList, user); } } catch (RemoteException e) { // The RemoteCallbackList will take care of removing the dead object. } } } mCallbacks.finishBroadcast(); } public static List<ShortcutInfo> filterShortcutsByQuery(String packageName, List<ShortcutInfo> shortcuts, QueryInfo query) { if (query.mPackage != null && query.mPackage != packageName) { return null; } List<ShortcutInfo> matches = new ArrayList<>(); final boolean matchDynamic = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0; final boolean matchPinned = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0; final boolean matchManifest = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0; final boolean matchCached = (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_CACHED) != 0; final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0) | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0) | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0) | (matchCached ? ShortcutInfo.FLAG_CACHED : 0); for (int i = 0; i < shortcuts.size(); i++) { final ShortcutInfo si = shortcuts.get(i); if (query.mActivity != null && !query.mActivity.equals(si.getActivity())) { continue; } if (query.mChangedSince != 0 && query.mChangedSince > si.getLastChangedTimestamp()) { continue; } if (query.mShortcutIds != null && !query.mShortcutIds.contains(si.getId())) { continue; } if (query.mLocusIds != null && !query.mLocusIds.contains(si.getLocusId())) { continue; } if ((shortcutFlags & si.getFlags()) != 0) { matches.add(si); } } return matches; } private boolean hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser) { final int callbackUserId = callbackUser.getIdentifier(); final int shortcutUserId = shortcutUser.getIdentifier(); if (shortcutUser == callbackUser) return true; return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId, null, false); } } private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener { // TODO Simplify with lambdas. Loading
services/core/java/com/android/server/pm/ShortcutPackage.java +25 −9 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.Preconditions; import com.android.internal.util.XmlUtils; import com.android.server.pm.ShortcutService.DumpFilter; Loading Loading @@ -365,9 +366,12 @@ class ShortcutPackage extends ShortcutPackageItem { /** * Remove all shortcuts that aren't pinned, cached nor dynamic. * * @return List of removed shortcuts. */ private void removeOrphans() { private List<ShortcutInfo> removeOrphans() { ArrayList<String> removeList = null; // Lazily initialize. List<ShortcutInfo> removedShortcuts = null; for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); Loading @@ -376,20 +380,26 @@ class ShortcutPackage extends ShortcutPackageItem { if (removeList == null) { removeList = new ArrayList<>(); removedShortcuts = new ArrayList<>(); } removeList.add(si.getId()); removedShortcuts.add(si); } if (removeList != null) { for (int i = removeList.size() - 1; i >= 0; i--) { forceDeleteShortcutInner(removeList.get(i)); } } return removedShortcuts; } /** * Remove all dynamic shortcuts. * * @return List of shortcuts that actually got removed. */ public void deleteAllDynamicShortcuts(boolean ignoreInvisible) { public List<ShortcutInfo> deleteAllDynamicShortcuts(boolean ignoreInvisible) { final long now = mShortcutUser.mService.injectCurrentTimeMillis(); boolean changed = false; Loading @@ -404,8 +414,9 @@ class ShortcutPackage extends ShortcutPackageItem { } } if (changed) { removeOrphans(); return removeOrphans(); } return null; } /** Loading Loading @@ -1028,7 +1039,8 @@ class ShortcutPackage extends ShortcutPackageItem { s.verifyStates(); // This will send a notification to the launcher, and also save . s.packageShortcutsChanged(getPackageName(), getPackageUserId()); // TODO: List changed and removed manifest shortcuts and pass to packageShortcutsChanged() s.packageShortcutsChanged(getPackageName(), getPackageUserId(), null, null); return true; // true means changed. } Loading Loading @@ -1299,15 +1311,14 @@ class ShortcutPackage extends ShortcutPackageItem { */ public void resolveResourceStrings() { final ShortcutService s = mShortcutUser.mService; boolean changed = false; List<ShortcutInfo> changedShortcuts = null; Resources publisherRes = null; for (int i = mShortcuts.size() - 1; i >= 0; i--) { final ShortcutInfo si = mShortcuts.valueAt(i); if (si.hasStringResources()) { changed = true; if (publisherRes == null) { publisherRes = getPackageResources(); if (publisherRes == null) { Loading @@ -1317,10 +1328,15 @@ class ShortcutPackage extends ShortcutPackageItem { si.resolveResourceStrings(publisherRes); si.setTimestamp(s.injectCurrentTimeMillis()); if (changedShortcuts == null) { changedShortcuts = new ArrayList<>(1); } changedShortcuts.add(si); } if (changed) { s.packageShortcutsChanged(getPackageName(), getPackageUserId()); } if (!CollectionUtils.isEmpty(changedShortcuts)) { s.packageShortcutsChanged(getPackageName(), getPackageUserId(), changedShortcuts, null); } } Loading