Merge "Installer connection support for dump_profiles" into nyc-dev
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4bbbdee..11f0eb6 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -482,6 +482,11 @@
boolean performDexOptMode(String packageName, boolean checkProfiles,
String targetCompilerFilter, boolean force);
+ /**
+ * Ask the package manager to dump profiles associated with a package.
+ */
+ void dumpProfiles(String packageName);
+
void forceDexOpt(String packageName);
/**
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index a7a3cb5..419c3d8 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -157,9 +157,7 @@
sharedLibraries);
}
- public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
- final String[] res = execute("merge_profiles", uid, pkgName);
-
+ private boolean safeParseBooleanResult(String[] res) throws InstallerException {
if ((res == null) || (res.length != 2)) {
throw new InstallerException("Invalid size result: " + Arrays.toString(res));
}
@@ -172,6 +170,19 @@
return Boolean.parseBoolean(res[1]);
}
+ public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
+ final String[] res = execute("merge_profiles", uid, pkgName);
+
+ return safeParseBooleanResult(res);
+ }
+
+ public boolean dumpProfiles(String gid, String packageName, String codePaths)
+ throws InstallerException {
+ final String[] res = execute("dump_profiles", gid, packageName, codePaths);
+
+ return safeParseBooleanResult(res);
+ }
+
private boolean connect() {
if (mSocket != null) {
return true;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 913c824..7b85a4f 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -153,6 +153,11 @@
return mInstaller.mergeProfiles(uid, pkgName);
}
+ public boolean dumpProfiles(String gid, String packageName, String codePaths)
+ throws InstallerException {
+ return mInstaller.dumpProfiles(gid, packageName, codePaths);
+ }
+
public void idmap(String targetApkPath, String overlayApkPath, int uid)
throws InstallerException {
mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a5cb284..3999d18 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7459,6 +7459,45 @@
}
@Override
+ public void dumpProfiles(String packageName) {
+ PackageParser.Package pkg;
+ synchronized (mPackages) {
+ pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ throw new IllegalArgumentException("Unknown package: " + packageName);
+ }
+ }
+ /* Only the shell or the app user should be able to dump profiles. */
+ int callingUid = Binder.getCallingUid();
+ if (callingUid != Process.SHELL_UID && callingUid != pkg.applicationInfo.uid) {
+ throw new SecurityException("dumpProfiles");
+ }
+
+ synchronized (mInstallLock) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ try {
+ final File codeFile = new File(pkg.applicationInfo.getCodePath());
+ List<String> allCodePaths = Collections.EMPTY_LIST;
+ if (codeFile != null && codeFile.exists()) {
+ try {
+ final PackageLite codePkg = PackageParser.parsePackageLite(codeFile, 0);
+ allCodePaths = codePkg.getAllCodePaths();
+ } catch (PackageParserException e) {
+ // Well, we tried.
+ }
+ }
+ String gid = Integer.toString(sharedGid);
+ String codePaths = TextUtils.join(";", allCodePaths);
+ mInstaller.dumpProfiles(gid, packageName, codePaths);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to dump profiles", e);
+ }
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ @Override
public void forceDexOpt(String packageName) {
enforceSystemOrRoot("forceDexOpt");
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index beff8fc..05f5b8f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -105,6 +105,8 @@
return runInstallWrite();
case "compile":
return runCompile();
+ case "dump-profiles":
+ return runDumpProfiles();
case "list":
return runList();
case "uninstall":
@@ -387,6 +389,12 @@
}
}
+ private int runDumpProfiles() throws RemoteException {
+ String packageName = getNextArg();
+ mInterface.dumpProfiles(packageName);
+ return 0;
+ }
+
private int runList() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
final String type = getNextArg();