Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03127b01 authored by Mehdi Alizadeh's avatar Mehdi Alizadeh Committed by Android (Google) Code Review
Browse files

Merge "Adds LauncherApps#ShortcutChangeCallback"

parents de25f7f1 9f680190
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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);
}
+37 −0
Original line number Diff line number Diff line
/**
 * 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
+154 −0
Original line number Diff line number Diff line
@@ -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;
@@ -1559,6 +1657,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.
+11 −0
Original line number Diff line number Diff line
@@ -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;
@@ -680,6 +681,16 @@ public class LauncherAppsService extends SystemService {
                            injectBinderCallingPid(), injectBinderCallingUid()));
        }

        @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) {