Loading api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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"; Loading Loading @@ -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(); core/java/android/content/pm/ILauncherApps.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); } core/java/android/content/pm/LauncherApps.java +86 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.content.pm; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -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. Loading Loading @@ -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. Loading core/java/android/content/pm/PackageInstaller.java +30 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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; Loading @@ -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()); } } Loading Loading @@ -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) { Loading Loading @@ -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} */ Loading Loading @@ -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(); Loading Loading @@ -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. */ Loading Loading @@ -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); Loading services/core/java/com/android/server/pm/LauncherAppsService.java +68 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) Loading @@ -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) Loading @@ -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 */ Loading Loading @@ -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 Loading
api/current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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"; Loading Loading @@ -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();
core/java/android/content/pm/ILauncherApps.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); }
core/java/android/content/pm/LauncherApps.java +86 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.content.pm; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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. Loading Loading @@ -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. Loading Loading @@ -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. */ Loading @@ -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. Loading Loading @@ -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. Loading
core/java/android/content/pm/PackageInstaller.java +30 −40 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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; Loading @@ -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()); } } Loading Loading @@ -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) { Loading Loading @@ -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} */ Loading Loading @@ -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(); Loading Loading @@ -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. */ Loading Loading @@ -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); Loading
services/core/java/com/android/server/pm/LauncherAppsService.java +68 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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) Loading @@ -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) Loading @@ -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 */ Loading Loading @@ -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