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

Commit 71f12a30 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow cross user SessionCallback support"

parents 3cdacf34 2b340a2e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -11233,6 +11233,7 @@ package android.content.pm {
  public class LauncherApps {
    method public java.util.List<android.content.pm.LauncherActivityInfo> getActivityList(String, android.os.UserHandle);
    method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllPackageInstallerSessions();
    method @Nullable public android.content.pm.LauncherApps.AppUsageLimit getAppUsageLimit(String, android.os.UserHandle);
    method public android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
    method public android.content.pm.LauncherApps.PinItemRequest getPinItemRequest(android.content.Intent);
@@ -11249,13 +11250,16 @@ package android.content.pm {
    method public void pinShortcuts(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull android.os.UserHandle);
    method public void registerCallback(android.content.pm.LauncherApps.Callback);
    method public void registerCallback(android.content.pm.LauncherApps.Callback, android.os.Handler);
    method public void registerPackageInstallerSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.content.pm.PackageInstaller.SessionCallback);
    method public android.content.pm.LauncherActivityInfo resolveActivity(android.content.Intent, android.os.UserHandle);
    method public boolean shouldHideFromSuggestions(@NonNull String, @NonNull android.os.UserHandle);
    method public void startAppDetailsActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle);
    method public void startPackageInstallerSessionDetailsActivity(android.content.pm.PackageInstaller.SessionInfo, android.graphics.Rect, android.os.Bundle);
    method public void startShortcut(@NonNull String, @NonNull String, @Nullable android.graphics.Rect, @Nullable android.os.Bundle, @NonNull android.os.UserHandle);
    method public void startShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.graphics.Rect, @Nullable android.os.Bundle);
    method public void unregisterCallback(android.content.pm.LauncherApps.Callback);
    method public void unregisterPackageInstallerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
    field public static final String ACTION_CONFIRM_PIN_APPWIDGET = "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
    field public static final String ACTION_CONFIRM_PIN_SHORTCUT = "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
    field public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST";
@@ -11445,6 +11449,7 @@ package android.content.pm {
    method public long getSize();
    method public int getStagedSessionErrorCode();
    method public String getStagedSessionErrorMessage();
    method public android.os.UserHandle getUser();
    method public boolean isActive();
    method public boolean isMultiPackage();
    method public boolean isSealed();
+10 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.LauncherApps;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.PackageInstaller;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
@@ -44,6 +46,9 @@ interface ILauncherApps {
            String callingPackage, String packageName, in UserHandle user);
    ActivityInfo resolveActivity(
            String callingPackage, in ComponentName component, in UserHandle user);
    void startSessionDetailsActivityAsUser(in IApplicationThread caller, String callingPackage,
                in PackageInstaller.SessionInfo sessionInfo, in Rect sourceBounds, in Bundle opts,
                in UserHandle user);
    void startActivityAsUser(in IApplicationThread caller, String callingPackage,
            in ComponentName component, in Rect sourceBounds,
            in Bundle opts, in UserHandle user);
@@ -79,4 +84,9 @@ interface ILauncherApps {
            String callingPackage, String packageName, in UserHandle user);
    IntentSender getShortcutConfigActivityIntent(String callingPackage, in ComponentName component,
            in UserHandle user);

    // Unregister is performed using package installer
    void registerPackageInstallerCallback(String callingPackage,
            in IPackageInstallerCallback callback);
    ParceledListSlice getAllSessions(String callingPackage);
}
+86 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.content.pm;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,6 +33,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageInstaller.SessionCallback;
import android.content.pm.PackageInstaller.SessionCallbackDelegate;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
@@ -65,7 +69,9 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Class for retrieving a list of launchable activities for the current user and any associated
@@ -154,8 +160,8 @@ public class LauncherApps {
    private final PackageManager mPm;
    private final UserManager mUserManager;

    private List<CallbackMessageHandler> mCallbacks
            = new ArrayList<CallbackMessageHandler>();
    private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
    private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();

    /**
     * Callbacks for package changes to this and related managed profiles.
@@ -571,6 +577,24 @@ public class LauncherApps {
        }
    }

    /**
     * Starts an activity to show the details of the specified session.
     *
     * @param sessionInfo The SessionInfo of the session
     * @param sourceBounds The Rect containing the source bounds of the clicked icon
     * @param opts Options to pass to startActivity
     */
    public void startPackageInstallerSessionDetailsActivity(SessionInfo sessionInfo,
            Rect sourceBounds, Bundle opts) {
        try {
            mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
                    mContext.getPackageName(), sessionInfo, sourceBounds, opts,
                    sessionInfo.getUser());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Starts the settings activity to show the application details for a
     * package in the specified profile.
@@ -1131,7 +1155,7 @@ public class LauncherApps {
    }

    /**
     * Registers a callback for changes to packages in current and managed profiles.
     * Registers a callback for changes to packages in this user and managed profiles.
     *
     * @param callback The callback to register.
     */
@@ -1140,7 +1164,7 @@ public class LauncherApps {
    }

    /**
     * Registers a callback for changes to packages in current and managed profiles.
     * Registers a callback for changes to packages in this user and managed profiles.
     *
     * @param callback The callback to register.
     * @param handler that should be used to post callbacks on, may be null.
@@ -1445,6 +1469,64 @@ public class LauncherApps {
        }
    }

    /**
     * Register a callback to watch for session lifecycle events in this user and managed profiles.
     * @param callback The callback to register.
     * @param executor {@link Executor} to handle the callbacks, cannot be null.
     *
     * @see PackageInstaller#registerSessionCallback(SessionCallback)
     */
    public void registerPackageInstallerSessionCallback(
            @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
        if (executor == null) {
            throw new NullPointerException("Executor must not be null");
        }

        synchronized (mDelegates) {
            final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                    executor);
            try {
                mService.registerPackageInstallerCallback(mContext.getPackageName(),
                        delegate);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            mDelegates.add(delegate);
        }
    }

    /**
     * Unregisters a callback that was previously registered.
     *
     * @param callback The callback to unregister.
     * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
     */
    public void unregisterPackageInstallerSessionCallback(SessionCallback callback) {
        synchronized (mDelegates) {
            for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
                final SessionCallbackDelegate delegate = i.next();
                if (delegate.mCallback == callback) {
                    mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
                    i.remove();
                }
            }
        }
    }

    /**
     * Return list of all known install sessions in this user and managed profiles, regardless
     * of the installer.
     *
     * @see PackageInstaller#getAllSessions()
     */
    public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
        try {
            return mService.getAllSessions(mContext.getPackageName()).getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * A helper method to extract a {@link PinItemRequest} set to
     * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
+30 −40
Original line number Diff line number Diff line
@@ -36,20 +36,21 @@ import android.net.Uri;
import android.os.Build;
import android.os.FileBridge;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.HandlerExecutor;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.util.ExceptionUtils;

import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;

import java.io.Closeable;
import java.io.IOException;
@@ -61,6 +62,7 @@ import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Offers the ability to install, upgrade, and remove applications on the
@@ -659,8 +661,7 @@ public class PackageInstaller {
    }

    /** {@hide} */
    private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
            Handler.Callback {
    static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub {
        private static final int MSG_SESSION_CREATED = 1;
        private static final int MSG_SESSION_BADGING_CHANGED = 2;
        private static final int MSG_SESSION_ACTIVE_CHANGED = 3;
@@ -668,63 +669,41 @@ public class PackageInstaller {
        private static final int MSG_SESSION_FINISHED = 5;

        final SessionCallback mCallback;
        final Handler mHandler;
        final Executor mExecutor;

        public SessionCallbackDelegate(SessionCallback callback, Looper looper) {
        SessionCallbackDelegate(SessionCallback callback, Executor executor) {
            mCallback = callback;
            mHandler = new Handler(looper, this);
        }

        @Override
        public boolean handleMessage(Message msg) {
            final int sessionId = msg.arg1;
            switch (msg.what) {
                case MSG_SESSION_CREATED:
                    mCallback.onCreated(sessionId);
                    return true;
                case MSG_SESSION_BADGING_CHANGED:
                    mCallback.onBadgingChanged(sessionId);
                    return true;
                case MSG_SESSION_ACTIVE_CHANGED:
                    final boolean active = msg.arg2 != 0;
                    mCallback.onActiveChanged(sessionId, active);
                    return true;
                case MSG_SESSION_PROGRESS_CHANGED:
                    mCallback.onProgressChanged(sessionId, (float) msg.obj);
                    return true;
                case MSG_SESSION_FINISHED:
                    mCallback.onFinished(sessionId, msg.arg2 != 0);
                    return true;
            }
            return false;
            mExecutor = executor;
        }

        @Override
        public void onSessionCreated(int sessionId) {
            mHandler.obtainMessage(MSG_SESSION_CREATED, sessionId, 0).sendToTarget();
            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onCreated, mCallback,
                    sessionId).recycleOnUse());
        }

        @Override
        public void onSessionBadgingChanged(int sessionId) {
            mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onBadgingChanged,
                    mCallback, sessionId).recycleOnUse());
        }

        @Override
        public void onSessionActiveChanged(int sessionId, boolean active) {
            mHandler.obtainMessage(MSG_SESSION_ACTIVE_CHANGED, sessionId, active ? 1 : 0)
                    .sendToTarget();
            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onActiveChanged,
                    mCallback, sessionId, active).recycleOnUse());
        }

        @Override
        public void onSessionProgressChanged(int sessionId, float progress) {
            mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress)
                    .sendToTarget();
            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onProgressChanged,
                    mCallback, sessionId, progress).recycleOnUse());
        }

        @Override
        public void onSessionFinished(int sessionId, boolean success) {
            mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0)
                    .sendToTarget();
            mExecutor.execute(PooledLambda.obtainRunnable(SessionCallback::onFinished,
                    mCallback, sessionId, success).recycleOnUse());
        }
    }

@@ -758,7 +737,7 @@ public class PackageInstaller {
    public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
        synchronized (mDelegates) {
            final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                    handler.getLooper());
                    new HandlerExecutor(handler));
            try {
                mInstaller.registerCallback(delegate, mUserId);
            } catch (RemoteException e) {
@@ -1649,6 +1628,8 @@ public class PackageInstaller {
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
        public int sessionId;
        /** {@hide} */
        public int userId;
        /** {@hide} */
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
        public String installerPackageName;
        /** {@hide} */
@@ -1720,6 +1701,7 @@ public class PackageInstaller {
        /** {@hide} */
        public SessionInfo(Parcel source) {
            sessionId = source.readInt();
            userId = source.readInt();
            installerPackageName = source.readString();
            resolvedBaseCodePath = source.readString();
            progress = source.readFloat();
@@ -1760,6 +1742,13 @@ public class PackageInstaller {
            return sessionId;
        }

        /**
         * Return the user associated with this session.
         */
        public UserHandle getUser() {
            return new UserHandle(userId);
        }

        /**
         * Return the package name of the app that owns this session.
         */
@@ -2091,6 +2080,7 @@ public class PackageInstaller {
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(sessionId);
            dest.writeInt(userId);
            dest.writeString(installerPackageName);
            dest.writeString(resolvedBaseCodePath);
            dest.writeFloat(progress);
+68 −4
Original line number Diff line number Diff line
@@ -34,9 +34,11 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ILauncherApps;
import android.content.pm.IOnAppsChangedListener;
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.LauncherApps;
import android.content.pm.LauncherApps.ShortcutQuery;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
@@ -56,6 +58,7 @@ import android.os.IInterface;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
@@ -153,6 +156,8 @@ public class LauncherAppsService extends SystemService {

        private final Object mVouchedSignaturesLocked = new Object();

        private PackageInstallerService mPackageInstallerService;

        public LauncherAppsImpl(Context context) {
            mContext = context;
            mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
@@ -204,8 +209,7 @@ public class LauncherAppsService extends SystemService {
        }

        /*
         * @see android.content.pm.ILauncherApps#addOnAppsChangedListener(
         *          android.content.pm.IOnAppsChangedListener)
         * @see android.content.pm.ILauncherApps#addOnAppsChangedListener
         */
        @Override
        public void addOnAppsChangedListener(String callingPackage, IOnAppsChangedListener listener)
@@ -228,8 +232,7 @@ public class LauncherAppsService extends SystemService {
        }

        /*
         * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener(
         *          android.content.pm.IOnAppsChangedListener)
         * @see android.content.pm.ILauncherApps#removeOnAppsChangedListener
         */
        @Override
        public void removeOnAppsChangedListener(IOnAppsChangedListener listener)
@@ -245,6 +248,44 @@ public class LauncherAppsService extends SystemService {
            }
        }

        /**
         * @see android.content.pm.ILauncherApps#registerPackageInstallerCallback
         */
        @Override
        public void registerPackageInstallerCallback(String callingPackage,
                IPackageInstallerCallback callback) {
            verifyCallingPackage(callingPackage);
            UserHandle callingIdUserHandle = new UserHandle(getCallingUserId());
            getPackageInstallerService().registerCallback(callback, eventUserId ->
                            isEnabledProfileOf(callingIdUserHandle,
                                    new UserHandle(eventUserId), "shouldReceiveEvent"));
        }

        @Override
        public ParceledListSlice<SessionInfo> getAllSessions(String callingPackage) {
            verifyCallingPackage(callingPackage);
            List<SessionInfo> sessionInfos = new ArrayList<>();
            int[] userIds = mUm.getEnabledProfileIds(getCallingUserId());
            long token = Binder.clearCallingIdentity();
            try {
                for (int userId : userIds) {
                    sessionInfos.addAll(getPackageInstallerService().getAllSessions(userId)
                            .getList());
                }
            } finally {
                Binder.restoreCallingIdentity(token);
            }
            return new ParceledListSlice<>(sessionInfos);
        }

        private PackageInstallerService getPackageInstallerService() {
            if (mPackageInstallerService == null) {
                mPackageInstallerService = ((PackageInstallerService) ((PackageManagerService)
                        ServiceManager.getService("package")).getPackageInstaller());
            }
            return mPackageInstallerService;
        }

        /**
         * Register a receiver to watch for package broadcasts
         */
@@ -868,6 +909,29 @@ public class LauncherAppsService extends SystemService {
            }
        }

        @Override
        public void startSessionDetailsActivityAsUser(IApplicationThread caller,
                String callingPackage, SessionInfo sessionInfo, Rect sourceBounds,
                Bundle opts, UserHandle userHandle) throws RemoteException {
            int userId = userHandle.getIdentifier();
            if (!canAccessProfile(userId, "Cannot start details activity")) {
                return;
            }

            Intent i = new Intent(Intent.ACTION_VIEW)
                    .setData(new Uri.Builder()
                            .scheme("market")
                            .authority("details")
                            .appendQueryParameter("id", sessionInfo.appPackageName)
                            .build())
                    .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
                            .authority(callingPackage).build());
            i.setSourceBounds(sourceBounds);

            mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, i, opts,
                    userId);
        }

        @Override
        public void startActivityAsUser(IApplicationThread caller, String callingPackage,
                ComponentName component, Rect sourceBounds,
Loading