diff options
author | Jeff Sharkey <jsharkey@android.com> | 2014-07-16 11:32:08 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2014-07-16 13:38:09 -0700 |
commit | 9a445771f57dd15b06db0dbefd66c368d84eec2d (patch) | |
tree | d418591835aec7c22724e49e0a8681efea5fc39c | |
parent | 4990e4f0e3d493036e99e1f5fb893635a9b66eb1 (diff) | |
download | frameworks_base-9a445771f57dd15b06db0dbefd66c368d84eec2d.zip frameworks_base-9a445771f57dd15b06db0dbefd66c368d84eec2d.tar.gz frameworks_base-9a445771f57dd15b06db0dbefd66c368d84eec2d.tar.bz2 |
Install sessions only inherit APK files.
Also track historical install sessions for debugging purposes. Hide
signature verification API for now. Clear code cache only after
killing the app being upgraded.
Bug: 14975160
Change-Id: I52fc7f11d2506f792236d8a365c8cfed21b46c30
4 files changed, 46 insertions, 38 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index b7f1ff9..d6c17ae 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -998,8 +998,8 @@ public final class Pm { final InstallSessionParams params = new InstallSessionParams(); params.installFlags = PackageManager.INSTALL_ALL_USERS; - params.mode = InstallSessionParams.MODE_FULL_INSTALL; - params.progressMax = -1; + params.setModeFullInstall(); + params.setProgressMax(-1); String opt; while ((opt = nextOption()) != null) { @@ -1021,10 +1021,11 @@ public final class Pm { } else if (opt.equals("-d")) { params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; } else if (opt.equals("-p")) { - params.mode = InstallSessionParams.MODE_INHERIT_EXISTING; + params.setModeInheritExisting(); } else if (opt.equals("-S")) { - params.deltaSize = Long.parseLong(nextOptionData()); - params.progressMax = (int) params.deltaSize; + final long deltaSize = Long.parseLong(nextOptionData()); + params.setDeltaSize(deltaSize); + params.setProgressMax((int) params.deltaSize); } else if (opt.equals("--abi")) { params.abiOverride = checkAbiArgument(nextOptionData()); } else { diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 190e87c..db915e2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -76,6 +76,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @GuardedBy("mSessions") private final SparseArray<PackageInstallerSession> mSessions = new SparseArray<>(); + /** Historical sessions kept around for debugging purposes */ + @GuardedBy("mSessions") + private final SparseArray<PackageInstallerSession> mHistoricalSessions = new SparseArray<>(); + private RemoteCallbackList<IPackageInstallerObserver> mObservers = new RemoteCallbackList<>(); private static final FilenameFilter sStageFilter = new FilenameFilter() { @@ -344,18 +348,29 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } void dump(IndentingPrintWriter pw) { - pw.println("Active install sessions:"); - pw.increaseIndent(); synchronized (mSessions) { - final int N = mSessions.size(); + pw.println("Active install sessions:"); + pw.increaseIndent(); + int N = mSessions.size(); for (int i = 0; i < N; i++) { final PackageInstallerSession session = mSessions.valueAt(i); session.dump(pw); pw.println(); } + pw.println(); + pw.decreaseIndent(); + + pw.println("Historical install sessions:"); + pw.increaseIndent(); + N = mHistoricalSessions.size(); + for (int i = 0; i < N; i++) { + final PackageInstallerSession session = mHistoricalSessions.valueAt(i); + session.dump(pw); + pw.println(); + } + pw.println(); + pw.decreaseIndent(); } - pw.println(); - pw.decreaseIndent(); } class Callback { @@ -367,6 +382,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { notifySessionFinished(session.sessionId, success); synchronized (mSessions) { mSessions.remove(session.sessionId); + mHistoricalSessions.put(session.sessionId, session); } writeSessionsAsync(); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 31d9704..0e6a3f0 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -65,6 +65,7 @@ import java.util.ArrayList; public class PackageInstallerSession extends IPackageInstallerSession.Stub { private static final String TAG = "PackageInstaller"; + private static final boolean LOGD = true; // TODO: enforce INSTALL_ALLOW_TEST // TODO: enforce INSTALL_ALLOW_DOWNGRADE @@ -435,35 +436,25 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { */ private void spliceExistingFilesIntoStage() throws PackageManagerException { final ApplicationInfo app = mPm.getApplicationInfo(mPackageName, 0, userId); - final File existingDir = new File(app.getBaseCodePath()); - try { - linkTreeIgnoringExisting(existingDir, sessionStageDir); - } catch (ErrnoException e) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Failed to splice into stage"); - } - } - - /** - * Recursively hard link all files from source directory tree to target. - * When a file already exists in the target tree, it leaves that file - * intact. - */ - private void linkTreeIgnoringExisting(File sourceDir, File targetDir) throws ErrnoException { - final File[] sourceContents = sourceDir.listFiles(); - if (ArrayUtils.isEmpty(sourceContents)) return; - - for (File sourceFile : sourceContents) { - final File targetFile = new File(targetDir, sourceFile.getName()); + int n = 0; + final File[] oldFiles = new File(app.getCodePath()).listFiles(); + if (!ArrayUtils.isEmpty(oldFiles)) { + for (File oldFile : oldFiles) { + if (!PackageParser.isApkFile(oldFile)) continue; - if (sourceFile.isDirectory()) { - targetFile.mkdir(); - linkTreeIgnoringExisting(sourceFile, targetFile); - } else { - Libcore.os.link(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath()); + final File newFile = new File(sessionStageDir, oldFile.getName()); + try { + Os.link(oldFile.getAbsolutePath(), newFile.getAbsolutePath()); + n++; + } catch (ErrnoException e) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Failed to splice into stage", e); + } } } + + if (LOGD) Slog.d(TAG, "Spliced " + n + " existing APKs into stage"); } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 0ad3a68..727cff0 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -10026,9 +10026,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - // Nuke any cached code - deleteCodeCacheDirsLI(pkgName); - boolean sysPkg = (isSystemApp(oldPackage)); if (sysPkg) { replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, @@ -10066,6 +10063,7 @@ public class PackageManagerService extends IPackageManager.Stub { deletedPkg = false; } else { // Successfully deleted the old package. Now proceed with re-installation + deleteCodeCacheDirsLI(pkgName); try { final PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME, System.currentTimeMillis(), user, abiOverride); @@ -10177,6 +10175,8 @@ public class PackageManagerService extends IPackageManager.Stub { } // Successfully disabled the old package. Now proceed with re-installation + deleteCodeCacheDirsLI(packageName); + res.returnCode = PackageManager.INSTALL_SUCCEEDED; pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; |