diff options
| author | 2020-02-06 02:49:55 +0000 | |
|---|---|---|
| committer | 2020-02-06 02:49:55 +0000 | |
| commit | 03127b010fb9b89d15235d2ff8ef1c82026b5a4e (patch) | |
| tree | 2580838c75d49263734a4023aee061bc6f9c2177 | |
| parent | de25f7f1ffd305cadaefee22d800854ec63a3a34 (diff) | |
| parent | 9f680190662deec6cf83489a3af487b021c6bc71 (diff) | |
Merge "Adds LauncherApps#ShortcutChangeCallback"
4 files changed, 208 insertions, 0 deletions
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl index 50bb3c721763..173fa5f2b4ba 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -25,6 +25,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IOnAppsChangedListener; import android.content.pm.LauncherApps; import android.content.pm.IPackageInstallerCallback; +import android.content.pm.IShortcutChangeCallback; import android.content.pm.PackageInstaller; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; @@ -89,4 +90,9 @@ interface ILauncherApps { void registerPackageInstallerCallback(String callingPackage, in IPackageInstallerCallback callback); ParceledListSlice getAllSessions(String callingPackage); + + void registerShortcutChangeCallback(String callingPackage, long changedSince, + String packageName, in List shortcutIds, in ComponentName componentName, int flags, + in IShortcutChangeCallback callback, int callbackId); + void unregisterShortcutChangeCallback(String callingPackage, int callbackId); } diff --git a/core/java/android/content/pm/IShortcutChangeCallback.aidl b/core/java/android/content/pm/IShortcutChangeCallback.aidl new file mode 100644 index 000000000000..fed4e4a796f9 --- /dev/null +++ b/core/java/android/content/pm/IShortcutChangeCallback.aidl @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.pm; + +import android.content.pm.ParceledListSlice; +import android.content.pm.ShortcutInfo; +import android.os.UserHandle; + +import java.util.List; + +/** + * Interface for LauncherApps#ShortcutChangeCallbackProxy. + * + * @hide + */ +oneway interface IShortcutChangeCallback +{ + void onShortcutsAddedOrUpdated(String packageName, in List<ShortcutInfo> shortcuts, + in UserHandle user); + + void onShortcutsRemoved(String packageName, in List<ShortcutInfo> shortcuts, + in UserHandle user); +}
\ No newline at end of file diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index cea0b6b5f3ad..c647f6868021 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -61,15 +61,21 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Pair; + +import com.android.internal.util.function.pooled.PooledLambda; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; @@ -152,6 +158,9 @@ public class LauncherApps { private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>(); private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>(); + private final Map<Integer, Pair<Executor, ShortcutChangeCallback>> + mShortcutChangeCallbacks = new HashMap<>(); + /** * Callbacks for package changes to this and related managed profiles. */ @@ -469,6 +478,95 @@ public class LauncherApps { } } + /** + * Callbacks for shortcut changes to this and related managed profiles. + * + * @hide + */ + public interface ShortcutChangeCallback { + /** + * Indicates that one or more shortcuts, that match the {@link ShortcutQuery} used to + * register this callback, have been added or updated. + * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery) + * + * <p>Only the applications that are allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}, will receive it. + * + * @param packageName The name of the package that has the shortcuts. + * @param shortcuts Shortcuts from the package that have updated or added. Only "key" + * information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}. + * @param user The UserHandle of the profile that generated the change. + * + * @see ShortcutManager + */ + default void onShortcutsAddedOrUpdated(@NonNull String packageName, + @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {} + + /** + * Indicates that one or more shortcuts, that match the {@link ShortcutQuery} used to + * register this callback, have been removed. + * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery) + * + * <p>Only the applications that are allowed to access the shortcut information, + * as defined in {@link #hasShortcutHostPermission()}, will receive it. + * + * @param packageName The name of the package that has the shortcuts. + * @param shortcuts Shortcuts from the package that have been removed. Only "key" + * information will be provided, as defined in {@link ShortcutInfo#hasKeyFieldsOnly()}. + * @param user The UserHandle of the profile that generated the change. + * + * @see ShortcutManager + */ + default void onShortcutsRemoved(@NonNull String packageName, + @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {} + } + + /** + * Callback proxy class for {@link ShortcutChangeCallback} + * + * @hide + */ + private static class ShortcutChangeCallbackProxy extends + android.content.pm.IShortcutChangeCallback.Stub { + private final WeakReference<Pair<Executor, ShortcutChangeCallback>> mRemoteReferences; + + ShortcutChangeCallbackProxy(Pair<Executor, ShortcutChangeCallback> remoteReferences) { + mRemoteReferences = new WeakReference<>(remoteReferences); + } + + @Override + public void onShortcutsAddedOrUpdated(@NonNull String packageName, + @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) { + Pair<Executor, ShortcutChangeCallback> remoteReferences = mRemoteReferences.get(); + if (remoteReferences == null) { + // Binder is dead. + return; + } + + final Executor executor = remoteReferences.first; + final ShortcutChangeCallback callback = remoteReferences.second; + executor.execute( + PooledLambda.obtainRunnable(ShortcutChangeCallback::onShortcutsAddedOrUpdated, + callback, packageName, shortcuts, user).recycleOnUse()); + } + + @Override + public void onShortcutsRemoved(@NonNull String packageName, + @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) { + Pair<Executor, ShortcutChangeCallback> remoteReferences = mRemoteReferences.get(); + if (remoteReferences == null) { + // Binder is dead. + return; + } + + final Executor executor = remoteReferences.first; + final ShortcutChangeCallback callback = remoteReferences.second; + executor.execute( + PooledLambda.obtainRunnable(ShortcutChangeCallback::onShortcutsRemoved, + callback, packageName, shortcuts, user).recycleOnUse()); + } + } + /** @hide */ public LauncherApps(Context context, ILauncherApps service) { mContext = context; @@ -1560,6 +1658,62 @@ public class LauncherApps { } /** + * Register a callback to watch for shortcut change events in this user and managed profiles. + * + * @param callback The callback to register. + * @param query {@link ShortcutQuery} to match and filter the shortcut events. Only matching + * shortcuts will be returned by the callback. + * @param executor {@link Executor} to handle the callbacks. To dispatch callbacks to the main + * thread of your application, you can use {@link android.content.Context#getMainExecutor()}. + * + * @hide + */ + public void registerShortcutChangeCallback(@NonNull ShortcutChangeCallback callback, + @NonNull ShortcutQuery query, @NonNull @CallbackExecutor Executor executor) { + Objects.requireNonNull(callback, "Callback cannot be null"); + Objects.requireNonNull(query, "Query cannot be null"); + 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); + try { + mService.registerShortcutChangeCallback(mContext.getPackageName(), + query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity, + query.mQueryFlags, new ShortcutChangeCallbackProxy(state), callbackId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Unregisters a callback that was previously registered. + * @see #registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery, Executor) + * + * @param callback Callback to be unregistered. + * + * @hide + */ + public void unregisterShortcutChangeCallback(@NonNull ShortcutChangeCallback callback) { + Objects.requireNonNull(callback, "Callback cannot be null"); + + synchronized (mShortcutChangeCallbacks) { + final int callbackId = callback.hashCode(); + if (mShortcutChangeCallbacks.containsKey(callbackId)) { + mShortcutChangeCallbacks.remove(callbackId); + try { + mService.unregisterShortcutChangeCallback(mContext.getPackageName(), + callbackId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + + /** * A helper method to extract a {@link PinItemRequest} set to * the {@link #EXTRA_PIN_ITEM_REQUEST} extra. */ diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 7bb782b9fadc..7819cc6f9092 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -35,6 +35,7 @@ import android.content.pm.ILauncherApps; import android.content.pm.IOnAppsChangedListener; import android.content.pm.IPackageInstallerCallback; import android.content.pm.IPackageManager; +import android.content.pm.IShortcutChangeCallback; import android.content.pm.LauncherApps; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageInfo; @@ -681,6 +682,16 @@ public class LauncherAppsService extends SystemService { } @Override + public void registerShortcutChangeCallback(String callingPackage, long changedSince, + String packageName, List shortcutIds, ComponentName componentName, int flags, + IShortcutChangeCallback callback, int callbackId) { + } + + @Override + public void unregisterShortcutChangeCallback(String callingPackage, int callbackId) { + } + + @Override public void pinShortcuts(String callingPackage, String packageName, List<String> ids, UserHandle targetUser) { ensureShortcutPermission(callingPackage); |