diff options
Diffstat (limited to 'services/core/java/com/android/server/pm')
4 files changed, 146 insertions, 69 deletions
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index a406175..09096ff 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -969,8 +969,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub { public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) { + boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING); Notification notification = buildSuccessNotification(mContext, - mContext.getResources().getString(R.string.package_installed_device_owner), + mContext.getResources() + .getString(update ? R.string.package_updated_device_owner : + R.string.package_installed_device_owner), basePackageName, mUserId); if (notification != null) { @@ -980,6 +983,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } final Intent fillIn = new Intent(); + fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.installStatusToPublicStatus(returnCode)); @@ -1030,6 +1034,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { R.color.system_notification_accent_color)) .setContentTitle(packageLabel) .setContentText(contentText) + .setStyle(new Notification.BigTextStyle().bigText(contentText)) .setLargeIcon(packageIcon) .build(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8a19056..11ab042 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -155,6 +155,7 @@ import android.os.storage.IMountService; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import android.os.storage.VolumeRecord; import android.security.KeyStore; import android.security.SystemKeyStore; import android.system.ErrnoException; @@ -298,7 +299,6 @@ public class PackageManagerService extends IPackageManager.Stub { static final int SCAN_BOOTING = 1<<8; static final int SCAN_TRUSTED_OVERLAY = 1<<9; static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10; - static final int SCAN_REPLACING = 1<<11; static final int SCAN_REQUIRE_KNOWN = 1<<12; static final int REMOVE_CHATTY = 1<<16; @@ -1558,6 +1558,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } } + + @Override + public void onVolumeForgotten(String fsUuid) { + // TODO: remove all packages hosted on this uuid + } }; private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId) { @@ -1597,6 +1602,12 @@ public class PackageManagerService extends IPackageManager.Stub { res.origPackage); break; } + case PackageManager.INSTALL_SUCCEEDED: { + extras = new Bundle(); + extras.putBoolean(Intent.EXTRA_REPLACING, + res.removedInfo != null && res.removedInfo.removedPackage != null); + break; + } } return extras; } @@ -2374,6 +2385,18 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public boolean isPackageFrozen(String packageName) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + return ps.frozen; + } + } + Slog.w(TAG, "Package " + packageName + " is missing; assuming frozen"); + return true; + } + + @Override public boolean isPackageAvailable(String packageName, int userId) { if (!sUserManager.exists(userId)) return false; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available"); @@ -6476,14 +6499,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - // Request the ActivityManager to kill the process(only for existing packages) - // so that we do not end up in a confused state while the user is still using the older - // version of the application while the new one gets installed. - if ((scanFlags & SCAN_REPLACING) != 0) { - killApplication(pkg.applicationInfo.packageName, - pkg.applicationInfo.uid, "update pkg"); - } - // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { @@ -10791,16 +10806,17 @@ public class PackageManagerService extends IPackageManager.Stub { private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res) { - PackageParser.Package oldPackage; - String pkgName = pkg.packageName; - int[] allUsers; - boolean[] perUserInstalled; + final PackageParser.Package oldPackage; + final String pkgName = pkg.packageName; + final int[] allUsers; + final boolean[] perUserInstalled; + final boolean weFroze; // First find the old package info and check signatures synchronized(mPackages) { oldPackage = mPackages.get(pkgName); if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage); - PackageSetting ps = mSettings.mPackages.get(pkgName); + final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps == null || !ps.keySetData.isUsingUpgradeKeySets() || ps.sharedUser != null) { // default to original signature matching if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures) @@ -10824,15 +10840,35 @@ public class PackageManagerService extends IPackageManager.Stub { for (int i = 0; i < allUsers.length; i++) { perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false; } + + // Mark the app as frozen to prevent launching during the upgrade + // process, and then kill all running instances + if (!ps.frozen) { + ps.frozen = true; + weFroze = true; + } else { + weFroze = false; + } } - boolean sysPkg = (isSystemApp(oldPackage)); - if (sysPkg) { - replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, - user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); - } else { - replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, - user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + // Now that we're guarded by frozen state, kill app during upgrade + killApplication(pkgName, oldPackage.applicationInfo.uid, "replace pkg"); + + try { + boolean sysPkg = (isSystemApp(oldPackage)); + if (sysPkg) { + replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, + user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + } else { + replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, + user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + } + } finally { + // Regardless of success or failure of upgrade steps above, always + // unfreeze the package if we froze it + if (weFroze) { + unfreezePackage(pkgName); + } } } @@ -10962,8 +10998,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg"); - res.removedInfo.uid = oldPkg.applicationInfo.uid; res.removedInfo.removedPackage = packageName; // Remove existing system package @@ -11308,7 +11342,7 @@ public class PackageManagerService extends IPackageManager.Stub { startIntentFilterVerifications(args.user.getIdentifier(), pkg); if (replace) { - replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user, + replacePackageLI(pkg, parseFlags, scanFlags, args.user, installerPackageName, volumeUuid, res); } else { installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, @@ -14194,6 +14228,15 @@ public class PackageManagerService extends IPackageManager.Stub { sendResourcesChangedBroadcast(false, false, unloaded, null); } + private void unfreezePackage(String packageName) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + ps.frozen = false; + } + } + } + @Override public int movePackage(final String packageName, final String volumeUuid) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); @@ -14203,7 +14246,7 @@ public class PackageManagerService extends IPackageManager.Stub { movePackageInternal(packageName, volumeUuid, moveId); } catch (PackageManagerException e) { Slog.d(TAG, "Failed to move " + packageName, e); - mMoveCallbacks.notifyStatusChanged(moveId, null, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR); } return moveId; @@ -14221,7 +14264,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String packageAbiOverride; final int appId; final String seinfo; - final String moveTitle; + final String label; // reader synchronized (mPackages) { @@ -14234,14 +14277,19 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.applicationInfo.isSystemApp()) { throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, "Cannot move system application"); - } else if (pkg.mOperationPending) { - throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, - "Attempt to move package which has pending operations"); } - // TODO: yell if already in desired location + if (Objects.equals(ps.volumeUuid, volumeUuid)) { + throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, + "Package already moved to " + volumeUuid); + } - pkg.mOperationPending = true; + if (ps.frozen) { + throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, + "Failed to move already frozen package"); + } + + ps.frozen = true; currentAsec = pkg.applicationInfo.isForwardLocked() || pkg.applicationInfo.isExternalAsec(); @@ -14251,9 +14299,17 @@ public class PackageManagerService extends IPackageManager.Stub { packageAbiOverride = ps.cpuAbiOverrideString; appId = UserHandle.getAppId(pkg.applicationInfo.uid); seinfo = pkg.applicationInfo.seinfo; - moveTitle = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); + label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); } + // Now that we're guarded by frozen state, kill app during upgrade + killApplication(packageName, appId, "move pkg"); + + final Bundle extras = new Bundle(); + extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + extras.putString(Intent.EXTRA_TITLE, label); + mMoveCallbacks.notifyCreated(moveId, extras); + int installFlags; final boolean moveData; @@ -14268,6 +14324,7 @@ public class PackageManagerService extends IPackageManager.Stub { final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid); if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE || !volume.isMountedWritable()) { + unfreezePackage(packageName); throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move location not mounted private volume"); } @@ -14279,27 +14336,21 @@ public class PackageManagerService extends IPackageManager.Stub { } Slog.d(TAG, "Moving " + packageName + " from " + currentVolumeUuid + " to " + volumeUuid); - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 10); + mMoveCallbacks.notifyStatusChanged(moveId, 10); if (moveData) { synchronized (mInstallLock) { // TODO: split this into separate copy and delete operations if (mInstaller.moveUserDataDirs(currentVolumeUuid, volumeUuid, packageName, appId, seinfo) != 0) { - synchronized (mPackages) { - final PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null) { - pkg.mOperationPending = false; - } - } - + unfreezePackage(packageName); throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, - "Failed to move private data"); + "Failed to move private data to " + volumeUuid); } } } - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 50); + mMoveCallbacks.notifyStatusChanged(moveId, 50); final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() { @Override @@ -14313,28 +14364,22 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.d(TAG, "Install result for move: " + PackageManager.installStatusToString(returnCode, msg)); - // We usually have a new package now after the install, but if - // we failed we need to clear the pending flag on the original - // package object. - synchronized (mPackages) { - final PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null) { - pkg.mOperationPending = false; - } - } + // Regardless of success or failure of the move operation, + // always unfreeze the package + unfreezePackage(packageName); final int status = PackageManager.installStatusToPublicStatus(returnCode); switch (status) { case PackageInstaller.STATUS_SUCCESS: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_SUCCEEDED); break; case PackageInstaller.STATUS_FAILURE_STORAGE: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE); break; default: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR); break; } @@ -14357,12 +14402,19 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); final int realMoveId = mNextMoveId.getAndIncrement(); - final String realTitle = null; + final Bundle extras = new Bundle(); + extras.putString(VolumeRecord.EXTRA_FS_UUID, volumeUuid); + mMoveCallbacks.notifyCreated(realMoveId, extras); final IPackageMoveObserver callback = new IPackageMoveObserver.Stub() { @Override - public void onStatusChanged(int moveId, String title, int status, long estMillis) { - mMoveCallbacks.notifyStatusChanged(realMoveId, realTitle, status, estMillis); + public void onCreated(int moveId, Bundle extras) { + // Ignored + } + + @Override + public void onStatusChanged(int moveId, int status, long estMillis) { + mMoveCallbacks.notifyStatusChanged(realMoveId, status, estMillis); } }; @@ -14717,6 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private static class MoveCallbacks extends Handler { + private static final int MSG_CREATED = 1; private static final int MSG_STATUS_CHANGED = 2; private final RemoteCallbackList<IPackageMoveObserver> @@ -14754,26 +14807,37 @@ public class PackageManagerService extends IPackageManager.Stub { private void invokeCallback(IPackageMoveObserver callback, int what, SomeArgs args) throws RemoteException { switch (what) { + case MSG_CREATED: { + callback.onCreated(args.argi1, (Bundle) args.arg2); + break; + } case MSG_STATUS_CHANGED: { - callback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3, - (long) args.arg4); + callback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3); break; } } } - private void notifyStatusChanged(int moveId, String moveTitle, int status) { - notifyStatusChanged(moveId, moveTitle, status, -1); + private void notifyCreated(int moveId, Bundle extras) { + Slog.v(TAG, "Move " + moveId + " created " + extras.toString()); + + final SomeArgs args = SomeArgs.obtain(); + args.argi1 = moveId; + args.arg2 = extras; + obtainMessage(MSG_CREATED, args).sendToTarget(); + } + + private void notifyStatusChanged(int moveId, int status) { + notifyStatusChanged(moveId, status, -1); } - private void notifyStatusChanged(int moveId, String moveTitle, int status, long estMillis) { + private void notifyStatusChanged(int moveId, int status, long estMillis) { Slog.v(TAG, "Move " + moveId + " status " + status); final SomeArgs args = SomeArgs.obtain(); args.argi1 = moveId; - args.arg2 = moveTitle; - args.argi3 = status; - args.arg4 = estMillis; + args.argi2 = status; + args.arg3 = estMillis; obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget(); synchronized (mLastStatus) { diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 5429517..f62c00c 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -108,6 +108,13 @@ abstract class PackageSettingBase extends SettingBase { int installStatus = PKG_INSTALL_COMPLETE; + /** + * Non-persisted value indicating this package has been temporarily frozen, + * usually during a critical section of the package update pipeline. The + * platform will refuse to launch packages in a frozen state. + */ + boolean frozen = false; + PackageSettingBase origPackage; /** Package name of the app that installed this package */ diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 252c16a..f9c248d 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3759,6 +3759,10 @@ final class Settings { pw.print(Integer.toHexString(System.identityHashCode(ps))); pw.println("):"); + if (ps.frozen) { + pw.print(prefix); pw.println(" FROZEN!"); + } + if (ps.realName != null) { pw.print(prefix); pw.print(" compat name="); pw.println(ps.name); @@ -3790,9 +3794,6 @@ final class Settings { pw.print(prefix); pw.print(" priavateFlags="); printFlags(pw, ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println(); pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); - if (ps.pkg.mOperationPending) { - pw.print(prefix); pw.println(" mOperationPending=true"); - } pw.print(prefix); pw.print(" supportsScreens=["); boolean first = true; if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { |