diff options
7 files changed, 134 insertions, 90 deletions
diff --git a/api/current.txt b/api/current.txt index fb52648d296e..dab4f641100b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8681,15 +8681,17 @@ package android.content.pm { public class PackageInstaller { method public void abandonSession(int); - method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback); - method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler); method public int createSession(android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException; method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions(); method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions(); method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int); method public android.content.pm.PackageInstaller.Session openSession(int); - method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback); + method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback); + method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler); method public void uninstall(java.lang.String, android.content.IntentSender); + method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback); + method public void updateSessionAppIcon(int, android.graphics.Bitmap); + method public void updateSessionAppLabel(int, java.lang.CharSequence); field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME"; field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME"; @@ -8721,6 +8723,7 @@ package android.content.pm { public static abstract class PackageInstaller.SessionCallback { ctor public PackageInstaller.SessionCallback(); + method public abstract void onBadgingChanged(int); method public abstract void onClosed(int); method public abstract void onCreated(int); method public abstract void onFinished(int, boolean); diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl index c6c0ff6163d3..6daefc8b6350 100644 --- a/core/java/android/content/pm/IPackageInstaller.aidl +++ b/core/java/android/content/pm/IPackageInstaller.aidl @@ -22,14 +22,21 @@ import android.content.pm.IPackageInstallerSession; import android.content.pm.PackageInstaller; import android.content.IntentSender; +import android.graphics.Bitmap; + /** {@hide} */ interface IPackageInstaller { int createSession(in PackageInstaller.SessionParams params, String installerPackageName, int userId); + + void updateSessionAppIcon(int sessionId, in Bitmap appIcon); + void updateSessionAppLabel(int sessionId, String appLabel); + void abandonSession(int sessionId); IPackageInstallerSession openSession(int sessionId); PackageInstaller.SessionInfo getSessionInfo(int sessionId); + List<PackageInstaller.SessionInfo> getAllSessions(int userId); List<PackageInstaller.SessionInfo> getMySessions(String installerPackageName, int userId); diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl index 39ae1a050c3e..fe98ee77d159 100644 --- a/core/java/android/content/pm/IPackageInstallerCallback.aidl +++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl @@ -19,6 +19,7 @@ package android.content.pm; /** {@hide} */ oneway interface IPackageInstallerCallback { void onSessionCreated(int sessionId); + void onSessionBadgingChanged(int sessionId); void onSessionOpened(int sessionId); void onSessionProgressChanged(int sessionId, float progress); void onSessionClosed(int sessionId); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 44e24b14e158..7c34a6512b8e 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -312,6 +312,32 @@ public class PackageInstaller { } } + /** + * Update the icon representing the app being installed in a specific + * session. This should be roughly + * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions. + */ + public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) { + try { + mInstaller.updateSessionAppIcon(sessionId, appIcon); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** + * Update the label representing the app being installed in a specific + * session. + */ + public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) { + try { + final String val = (appLabel != null) ? appLabel.toString() : null; + mInstaller.updateSessionAppLabel(sessionId, val); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + public void abandonSession(int sessionId) { try { mInstaller.abandonSession(sessionId); @@ -321,8 +347,7 @@ public class PackageInstaller { } /** - * Return details for a specific session. To succeed, the caller must either - * own this session, or be the current home app. + * Return details for a specific session. */ public @Nullable SessionInfo getSessionInfo(int sessionId) { try { @@ -334,7 +359,6 @@ public class PackageInstaller { /** * Return list of all active install sessions, regardless of the installer. - * To succeed, the caller must be the current home app. */ public @NonNull List<SessionInfo> getAllSessions() { final ApplicationInfo info = mContext.getApplicationInfo(); @@ -406,6 +430,12 @@ public class PackageInstaller { public abstract void onCreated(int sessionId); /** + * Badging details for an existing session has changed. For example, the + * app icon or label has been updated. + */ + public abstract void onBadgingChanged(int sessionId); + + /** * Session has been opened. A session is usually opened when the * installer is actively writing data. */ @@ -436,10 +466,11 @@ public class PackageInstaller { private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements Handler.Callback { private static final int MSG_SESSION_CREATED = 1; - private static final int MSG_SESSION_OPENED = 2; - private static final int MSG_SESSION_PROGRESS_CHANGED = 3; - private static final int MSG_SESSION_CLOSED = 4; - private static final int MSG_SESSION_FINISHED = 5; + private static final int MSG_SESSION_BADGING_CHANGED = 2; + private static final int MSG_SESSION_OPENED = 3; + private static final int MSG_SESSION_PROGRESS_CHANGED = 4; + private static final int MSG_SESSION_CLOSED = 5; + private static final int MSG_SESSION_FINISHED = 6; final SessionCallback mCallback; final Handler mHandler; @@ -455,6 +486,9 @@ public class PackageInstaller { case MSG_SESSION_CREATED: mCallback.onCreated(msg.arg1); return true; + case MSG_SESSION_BADGING_CHANGED: + mCallback.onBadgingChanged(msg.arg1); + return true; case MSG_SESSION_OPENED: mCallback.onOpened(msg.arg1); return true; @@ -477,6 +511,11 @@ public class PackageInstaller { } @Override + public void onSessionBadgingChanged(int sessionId) { + mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget(); + } + + @Override public void onSessionOpened(int sessionId) { mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget(); } @@ -499,22 +538,32 @@ public class PackageInstaller { } } + /** {@hide} */ + @Deprecated + public void addSessionCallback(@NonNull SessionCallback callback) { + registerSessionCallback(callback); + } + /** - * Register to watch for session lifecycle events. To succeed, the caller - * must be the current home app. + * Register to watch for session lifecycle events. */ - public void addSessionCallback(@NonNull SessionCallback callback) { - addSessionCallback(callback, new Handler()); + public void registerSessionCallback(@NonNull SessionCallback callback) { + registerSessionCallback(callback, new Handler()); + } + + /** {@hide} */ + @Deprecated + public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { + registerSessionCallback(callback, handler); } /** - * Register to watch for session lifecycle events. To succeed, the caller - * must be the current home app. + * Register to watch for session lifecycle events. * * @param handler to dispatch callback events through, otherwise uses * calling thread. */ - public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { + public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) { // TODO: remove this temporary guard once we have new prebuilts final ApplicationInfo info = mContext.getApplicationInfo(); if ("com.google.android.googlequicksearchbox".equals(info.packageName) @@ -535,10 +584,16 @@ public class PackageInstaller { } } + /** {@hide} */ + @Deprecated + public void removeSessionCallback(@NonNull SessionCallback callback) { + unregisterSessionCallback(callback); + } + /** * Unregister an existing callback. */ - public void removeSessionCallback(@NonNull SessionCallback callback) { + public void unregisterSessionCallback(@NonNull SessionCallback callback) { synchronized (mDelegates) { for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) { final SessionCallbackDelegate delegate = i.next(); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 3f7a607efce3..9a00923effcb 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -47,12 +47,12 @@ import android.content.pm.IPackageInstaller; import android.content.pm.IPackageInstallerCallback; import android.content.pm.IPackageInstallerSession; import android.content.pm.PackageInstaller; -import android.content.pm.PackageParser; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageInstaller.SessionParams; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; -import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.net.Uri; import android.os.Binder; @@ -581,6 +581,30 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } @Override + public void updateSessionAppIcon(int sessionId, Bitmap appIcon) { + synchronized (mSessions) { + final PackageInstallerSession session = mSessions.get(sessionId); + if (session == null || !isCallingUidOwner(session)) { + throw new SecurityException("Caller has no access to session " + sessionId); + } + session.params.appIcon = appIcon; + mInternalCallback.onSessionBadgingChanged(session); + } + } + + @Override + public void updateSessionAppLabel(int sessionId, String appLabel) { + synchronized (mSessions) { + final PackageInstallerSession session = mSessions.get(sessionId); + if (session == null || !isCallingUidOwner(session)) { + throw new SecurityException("Caller has no access to session " + sessionId); + } + session.params.appLabel = appLabel; + mInternalCallback.onSessionBadgingChanged(session); + } + } + + @Override public void abandonSession(int sessionId) { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); @@ -681,9 +705,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub { public SessionInfo getSessionInfo(int sessionId) { synchronized (mSessions) { final PackageInstallerSession session = mSessions.get(sessionId); - if (!isCallingUidOwner(session)) { - enforceCallerCanReadSessions(); - } return session != null ? session.generateInfo() : null; } } @@ -691,7 +712,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public List<SessionInfo> getAllSessions(int userId) { mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions"); - enforceCallerCanReadSessions(); final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { @@ -755,8 +775,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public void registerCallback(IPackageInstallerCallback callback, int userId) { mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback"); - enforceCallerCanReadSessions(); - mCallbacks.register(callback, userId); } @@ -787,21 +805,6 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } - /** - * We allow those with permission, or the current home app. - */ - private void enforceCallerCanReadSessions() { - final boolean hasPermission = (mContext.checkCallingOrSelfPermission( - android.Manifest.permission.READ_INSTALL_SESSIONS) - == PackageManager.PERMISSION_GRANTED); - final boolean isHomeApp = mPm.checkCallerIsHomeApp(); - if (hasPermission || isHomeApp) { - return; - } else { - throw new SecurityException("Caller must be current home app to read install sessions"); - } - } - static class PackageDeleteObserverAdapter extends PackageDeleteObserver { private final Context mContext; private final IntentSender mTarget; @@ -893,10 +896,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub { private static class Callbacks extends Handler { private static final int MSG_SESSION_CREATED = 1; - private static final int MSG_SESSION_OPENED = 2; - private static final int MSG_SESSION_PROGRESS_CHANGED = 3; - private static final int MSG_SESSION_CLOSED = 4; - private static final int MSG_SESSION_FINISHED = 5; + private static final int MSG_SESSION_BADGING_CHANGED = 2; + private static final int MSG_SESSION_OPENED = 3; + private static final int MSG_SESSION_PROGRESS_CHANGED = 4; + private static final int MSG_SESSION_CLOSED = 5; + private static final int MSG_SESSION_FINISHED = 6; private final RemoteCallbackList<IPackageInstallerCallback> mCallbacks = new RemoteCallbackList<>(); @@ -938,6 +942,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub { case MSG_SESSION_CREATED: callback.onSessionCreated(sessionId); break; + case MSG_SESSION_BADGING_CHANGED: + callback.onSessionBadgingChanged(sessionId); + break; case MSG_SESSION_OPENED: callback.onSessionOpened(sessionId); break; @@ -957,6 +964,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub { obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget(); } + private void notifySessionBadgingChanged(int sessionId, int userId) { + obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget(); + } + private void notifySessionOpened(int sessionId, int userId) { obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget(); } @@ -1006,14 +1017,19 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } class InternalCallback { - public void onSessionProgressChanged(PackageInstallerSession session, float progress) { - mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); + public void onSessionBadgingChanged(PackageInstallerSession session) { + mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId); + writeSessionsAsync(); } public void onSessionOpened(PackageInstallerSession session) { mCallbacks.notifySessionOpened(session.sessionId, session.userId); } + public void onSessionProgressChanged(PackageInstallerSession session, float progress) { + mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress); + } + public void onSessionClosed(PackageInstallerSession session) { mCallbacks.notifySessionClosed(session.sessionId, session.userId); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 5264fc4b13fd..85ff54e444c2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -294,7 +294,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } private void computeProgressLocked() { - mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f); + if (mProgress <= 0.8f) { + mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f); + } } private void maybePublishProgress() { @@ -485,7 +487,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } // TODO: surface more granular state from dexopt - mCallback.onSessionProgressChanged(this, 0.9f); + mProgress = 0.9f; + maybePublishProgress(); // Unpack native libraries extractNativeLibraries(mResolvedStageDir, params.abiOverride); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a4d4914616d3..d2a627e32137 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -11746,47 +11746,6 @@ public class PackageManagerService extends IPackageManager.Stub { preferred.activityInfo.name); } - /** - * Check if calling UID is the current home app. This handles both the case - * where the user has selected a specific home app, and where there is only - * one home app. - */ - public boolean checkCallerIsHomeApp() { - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.addCategory(Intent.CATEGORY_HOME); - - final int callingUid = Binder.getCallingUid(); - final int callingUserId = UserHandle.getCallingUserId(); - final List<ResolveInfo> allHomes = queryIntentActivities(intent, null, 0, callingUserId); - final ResolveInfo preferredHome = findPreferredActivity(intent, null, 0, allHomes, 0, true, - false, false, callingUserId); - - if (preferredHome != null) { - if (callingUid == preferredHome.activityInfo.applicationInfo.uid) { - return true; - } - } else { - for (ResolveInfo info : allHomes) { - if (callingUid == info.activityInfo.applicationInfo.uid) { - return true; - } - } - } - - return false; - } - - /** - * Enforce that calling UID is the current home app. This handles both the - * case where the user has selected a specific home app, and where there is - * only one home app. - */ - public void enforceCallerIsHomeApp() { - if (!checkCallerIsHomeApp()) { - throw new SecurityException("Caller is not currently selected home app"); - } - } - @Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { |