From 9a445771f57dd15b06db0dbefd66c368d84eec2d Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 16 Jul 2014 11:32:08 -0700 Subject: 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 --- cmds/pm/src/com/android/commands/pm/Pm.java | 11 +++--- .../android/server/pm/PackageInstallerService.java | 26 +++++++++++--- .../android/server/pm/PackageInstallerSession.java | 41 +++++++++------------- .../android/server/pm/PackageManagerService.java | 6 ++-- 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 mSessions = new SparseArray<>(); + /** Historical sessions kept around for debugging purposes */ + @GuardedBy("mSessions") + private final SparseArray mHistoricalSessions = new SparseArray<>(); + private RemoteCallbackList 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; -- cgit v1.1