diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-06-11 14:26:53 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2013-06-11 14:26:53 -0700 |
commit | cbfd23ee6f14445c3e17c5169abbc80c216fa137 (patch) | |
tree | 9e5063fe418c4df345b371a0678faa4a1fcb0c48 | |
parent | be4e6aaa0252dd7da28b7aa85beba982538efa46 (diff) | |
download | frameworks_base-cbfd23ee6f14445c3e17c5169abbc80c216fa137.zip frameworks_base-cbfd23ee6f14445c3e17c5169abbc80c216fa137.tar.gz frameworks_base-cbfd23ee6f14445c3e17c5169abbc80c216fa137.tar.bz2 |
Add new API to retrieve a dumpsys of a single package.
Adds a platform API, and pm command. Fixes some issues with
dumping per-package data in package manager, makes battery
stats able to dump per-package state.
Change-Id: I76ee6d059f0ba17f7a7061886792b1b716d46d2d
-rw-r--r-- | cmds/pm/src/com/android/commands/pm/Pm.java | 23 | ||||
-rw-r--r-- | core/java/android/app/ActivityManager.java | 57 | ||||
-rw-r--r-- | core/java/android/os/BatteryStats.java | 6 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 4 | ||||
-rw-r--r-- | core/java/com/android/internal/os/TransferPipe.java (renamed from services/java/com/android/server/am/TransferPipe.java) | 16 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActiveServices.java | 1 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 1 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityStackSupervisor.java | 1 | ||||
-rw-r--r-- | services/java/com/android/server/am/BatteryStatsService.java | 20 | ||||
-rw-r--r-- | services/java/com/android/server/am/ProviderMap.java | 1 | ||||
-rw-r--r-- | services/java/com/android/server/pm/KeySetManager.java | 44 | ||||
-rw-r--r-- | services/java/com/android/server/pm/PackageManagerService.java | 32 | ||||
-rw-r--r-- | services/java/com/android/server/pm/Settings.java | 10 |
13 files changed, 169 insertions, 47 deletions
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 224945a..6f57ae0 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -16,8 +16,7 @@ package com.android.commands.pm; -import com.android.internal.content.PackageHelper; - +import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.pm.ApplicationInfo; @@ -46,6 +45,7 @@ import android.os.UserHandle; import android.os.UserManager; import java.io.File; +import java.io.FileDescriptor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.security.InvalidAlgorithmParameterException; @@ -59,6 +59,8 @@ import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; +import com.android.internal.content.PackageHelper; + public final class Pm { IPackageManager mPm; IUserManager mUm; @@ -105,6 +107,11 @@ public final class Pm { return; } + if ("dump".equals(op)) { + runDump(); + return; + } + if ("install".equals(op)) { runInstall(); return; @@ -672,6 +679,15 @@ public final class Pm { displayPackageFilePath(pkg); } + private void runDump() { + String pkg = nextArg(); + if (pkg == null) { + System.err.println("Error: no package specified"); + return; + } + ActivityManager.dumpPackageStateStatic(FileDescriptor.out, pkg); + } + class PackageInstallObserver extends IPackageInstallObserver.Stub { boolean finished; int result; @@ -1456,6 +1472,7 @@ public final class Pm { System.err.println(" pm list libraries"); System.err.println(" pm list users"); System.err.println(" pm path PACKAGE"); + System.err.println(" pm dump PACKAGE"); System.err.println(" pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]"); System.err.println(" [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>]"); System.err.println(" [--originating-uri <URI>] [--referrer <URI>] PATH"); @@ -1506,6 +1523,8 @@ public final class Pm { System.err.println(""); System.err.println("pm path: print the path to the .apk of the given PACKAGE."); System.err.println(""); + System.err.println("pm dump: print system state associated w ith the given PACKAGE."); + System.err.println(""); System.err.println("pm install: installs a package to the system. Options:"); System.err.println(" -l: install the package with FORWARD_LOCK."); System.err.println(" -r: reinstall an exisiting app, keeping its data."); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 63ac42e..f523b55 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -16,8 +16,10 @@ package android.app; +import android.os.IBinder; import com.android.internal.app.IUsageStats; import com.android.internal.os.PkgUsageStats; +import com.android.internal.os.TransferPipe; import com.android.internal.util.MemInfoReader; import android.content.ComponentName; @@ -49,6 +51,9 @@ import android.util.Log; import android.util.Slog; import android.view.Display; +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1709,7 +1714,7 @@ public class ActivityManager { public ComponentName importanceReasonComponent; /** - * When {@link importanceReasonPid} is non-0, this is the importance + * When {@link #importanceReasonPid} is non-0, this is the importance * of the other pid. @hide */ public int importanceReasonImportance; @@ -2181,4 +2186,54 @@ public class ActivityManager { return false; } } + + /** + * Perform a system dump of various state associated with the given application + * package name. This call blocks while the dump is being performed, so should + * not be done on a UI thread. The data will be written to the given file + * descriptor as text. An application must hold the + * {@link android.Manifest.permission#DUMP} permission to make this call. + * @param fd The file descriptor that the dump should be written to. + * @param packageName The name of the package that is to be dumped. + */ + public void dumpPackageState(FileDescriptor fd, String packageName) { + dumpPackageStateStatic(fd, packageName); + } + + /** + * @hide + */ + public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) { + FileOutputStream fout = new FileOutputStream(fd); + PrintWriter pw = new PrintWriter(fout); + dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName}); + pw.println(); + dumpService(pw, fd, "package", new String[] { packageName}); + pw.println(); + dumpService(pw, fd, "batteryinfo", new String[] { packageName}); + pw.flush(); + } + + private static void dumpService(PrintWriter pw, FileDescriptor fd, String name, String[] args) { + pw.print("DUMP OF SERVICE "); pw.print(name); pw.println(":"); + IBinder service = ServiceManager.checkService(name); + if (service == null) { + pw.println(" (Service not found)"); + return; + } + TransferPipe tp = null; + try { + pw.flush(); + tp = new TransferPipe(); + tp.setBufferPrefix(" "); + service.dump(tp.getWriteFd().getFileDescriptor(), args); + tp.go(fd); + } catch (Throwable e) { + if (tp != null) { + tp.kill(); + } + pw.println("Failure dumping service:"); + e.printStackTrace(pw); + } + } } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 32bbfbd..fef1818 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -2279,7 +2279,7 @@ public abstract class BatteryStats implements Parcelable { * @param pw a Printer to receive the dump output. */ @SuppressWarnings("unused") - public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly) { + public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) { prepareForDumpLocked(); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); @@ -2336,11 +2336,11 @@ public abstract class BatteryStats implements Parcelable { pw.println("Statistics since last charge:"); pw.println(" System starts: " + getStartCount() + ", currently on battery: " + getIsOnBattery()); - dumpLocked(pw, "", STATS_SINCE_CHARGED, -1); + dumpLocked(pw, "", STATS_SINCE_CHARGED, reqUid); pw.println(""); } pw.println("Statistics since last unplugged:"); - dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, -1); + dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, reqUid); } @SuppressWarnings("unused") diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 38a8c19..949a499 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -6038,7 +6038,7 @@ public final class BatteryStatsImpl extends BatteryStats { updateNetworkActivityLocked(); } - public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly) { + public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) { if (DEBUG) { Printer pr = new PrintWriterPrinter(pw); pr.println("*** Screen timer:"); @@ -6068,6 +6068,6 @@ public final class BatteryStatsImpl extends BatteryStats { pr.println("*** Bluetooth timer:"); mBluetoothOnTimer.logState(pr, " "); } - super.dumpLocked(pw, isUnpluggedOnly); + super.dumpLocked(pw, isUnpluggedOnly, reqUid); } } diff --git a/services/java/com/android/server/am/TransferPipe.java b/core/java/com/android/internal/os/TransferPipe.java index 055c577..068d914 100644 --- a/services/java/com/android/server/am/TransferPipe.java +++ b/core/java/com/android/internal/os/TransferPipe.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.am; +package com.android.internal.os; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -32,7 +32,7 @@ import android.util.Slog; /** * Helper for transferring data through a pipe from a client app. */ -final class TransferPipe implements Runnable { +public final class TransferPipe implements Runnable { static final String TAG = "TransferPipe"; static final boolean DEBUG = false; @@ -53,7 +53,7 @@ final class TransferPipe implements Runnable { String[] args) throws RemoteException; } - TransferPipe() throws IOException { + public TransferPipe() throws IOException { mThread = new Thread(this, "TransferPipe"); mFds = ParcelFileDescriptor.createPipe(); } @@ -62,11 +62,11 @@ final class TransferPipe implements Runnable { return mFds[0]; } - ParcelFileDescriptor getWriteFd() { + public ParcelFileDescriptor getWriteFd() { return mFds[1]; } - void setBufferPrefix(String prefix) { + public void setBufferPrefix(String prefix) { mBufferPrefix = prefix; } @@ -120,11 +120,11 @@ final class TransferPipe implements Runnable { } } - void go(FileDescriptor out) throws IOException { + public void go(FileDescriptor out) throws IOException { go(out, DEFAULT_TIMEOUT); } - void go(FileDescriptor out, long timeout) throws IOException { + public void go(FileDescriptor out, long timeout) throws IOException { try { synchronized (this) { mOutFd = out; @@ -173,7 +173,7 @@ final class TransferPipe implements Runnable { } } - void kill() { + public void kill() { closeFd(0); closeFd(1); } diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 98c4352..a5d64b2 100644 --- a/services/java/com/android/server/am/ActiveServices.java +++ b/services/java/com/android/server/am/ActiveServices.java @@ -27,6 +27,7 @@ import java.util.Iterator; import java.util.List; import com.android.internal.os.BatteryStatsImpl; +import com.android.internal.os.TransferPipe; import com.android.server.am.ActivityManagerService.ItemMatcher; import com.android.server.am.ActivityManagerService.NeededUriGrants; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index f06b9a6..fc3183f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -32,6 +32,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IAppOpsService; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.ProcessStats; +import com.android.internal.os.TransferPipe; import com.android.internal.util.FastXmlSerializer; import com.android.server.AppOpsService; import com.android.server.AttributeCache; diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java index af61bfb..6fe28f4 100644 --- a/services/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/java/com/android/server/am/ActivityStackSupervisor.java @@ -69,6 +69,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.app.HeavyWeightSwitcherActivity; +import com.android.internal.os.TransferPipe; import com.android.server.am.ActivityManagerService.PendingActivityLaunch; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.StackBox; diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 5a15f0b..f143feb 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -27,6 +27,7 @@ import android.os.IBinder; import android.os.Parcel; import android.os.Process; import android.os.ServiceManager; +import android.os.UserHandle; import android.os.WorkSource; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; @@ -479,12 +480,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub { private void dumpHelp(PrintWriter pw) { pw.println("Battery stats (batteryinfo) dump options:"); - pw.println(" [--checkin] [--unplugged] [--reset] [--write] [-h]"); + pw.println(" [--checkin] [--unplugged] [--reset] [--write] [-h] [<package.name>]"); pw.println(" --checkin: format output for a checkin report."); pw.println(" --unplugged: only output data since last unplugged."); pw.println(" --reset: reset the stats, clearing all current data."); pw.println(" --write: force write current collected stats to disk."); pw.println(" -h: print this help text."); + pw.println(" <package.name>: optional name of package to filter output by."); } @Override @@ -500,6 +502,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { boolean isCheckin = false; boolean isUnpluggedOnly = false; boolean noOutput = false; + int reqUid = -1; if (args != null) { for (String arg : args) { if ("--checkin".equals(arg)) { @@ -523,9 +526,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub { return; } else if ("-a".equals(arg)) { // fall through - } else { + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ pw.println("Unknown option: " + arg); dumpHelp(pw); + return; + } else { + // Not an option, last argument must be a package name. + try { + reqUid = mContext.getPackageManager().getPackageUid(arg, + UserHandle.getCallingUserId()); + } catch (PackageManager.NameNotFoundException e) { + pw.println("Unknown package: " + arg); + dumpHelp(pw); + return; + } } } } @@ -539,7 +553,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } else { synchronized (mStats) { - mStats.dumpLocked(pw, isUnpluggedOnly); + mStats.dumpLocked(pw, isUnpluggedOnly, reqUid); } } } diff --git a/services/java/com/android/server/am/ProviderMap.java b/services/java/com/android/server/am/ProviderMap.java index 5759a44..7da8c48 100644 --- a/services/java/com/android/server/am/ProviderMap.java +++ b/services/java/com/android/server/am/ProviderMap.java @@ -22,6 +22,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; +import com.android.internal.os.TransferPipe; import java.io.FileDescriptor; import java.io.IOException; diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/java/com/android/server/pm/KeySetManager.java index f154ab3..8272c15 100644 --- a/services/java/com/android/server/pm/KeySetManager.java +++ b/services/java/com/android/server/pm/KeySetManager.java @@ -399,24 +399,50 @@ public class KeySetManager { return new String(Base64.encode(k.getEncoded(), 0)); } - public void dump(PrintWriter pw) { + public void dump(PrintWriter pw, String packageName, + PackageManagerService.DumpState dumpState) { synchronized (mLockObject) { - pw.println(" Dumping KeySetManager"); + boolean printedHeader = false; for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) { - String packageName = e.getKey(); + String keySetPackage = e.getKey(); + if (packageName != null && !packageName.equals(keySetPackage)) { + continue; + } + if (!printedHeader) { + if (dumpState.onTitlePrinted()) + pw.println(); + pw.println("Key Set Manager:"); + printedHeader = true; + } PackageSetting pkg = e.getValue(); - pw.print(" ["); pw.print(packageName); pw.println("]"); + pw.print(" ["); pw.print(keySetPackage); pw.println("]"); if (pkg.keySetData != null) { - pw.print(" Defined KeySets:"); + boolean printedLabel = false; for (long keySetId : pkg.keySetData.getDefinedKeySets()) { - pw.print(" "); pw.print(Long.toString(keySetId)); + if (!printedLabel) { + pw.print(" Defined KeySets: "); + printedLabel = true; + } else { + pw.print(", "); + } + pw.print(Long.toString(keySetId)); + } + if (printedLabel) { + pw.println(""); } - pw.println(""); - pw.print(" Signing KeySets:"); + printedLabel = false; for (long keySetId : pkg.keySetData.getSigningKeySets()) { + if (!printedLabel) { + pw.print(" Signing KeySets:"); + printedLabel = true; + } else { + pw.print(", "); + } pw.print(" "); pw.print(Long.toString(keySetId)); } - pw.println(""); + if (printedLabel) { + pw.println(""); + } } } } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 07805f9..5e6e055 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -10041,6 +10041,9 @@ public class PackageManagerService extends IPackageManager.Stub { // Is this a package name? if ("android".equals(cmd) || cmd.contains(".")) { packageName = cmd; + // When dumping a single package, we always dump all of its + // filter information since the amount of data will be reasonable. + dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS); } else if ("l".equals(cmd) || "libraries".equals(cmd)) { dumpState.setDump(DumpState.DUMP_LIBS); } else if ("f".equals(cmd) || "features".equals(cmd)) { @@ -10076,7 +10079,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Verifiers:"); pw.print(" Required: "); pw.print(mRequiredVerifierPackage); @@ -10086,16 +10089,20 @@ public class PackageManagerService extends IPackageManager.Stub { } if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) { - if (dumpState.onTitlePrinted()) - pw.println(" "); - pw.println("Libraries:"); + boolean printedHeader = false; final Iterator<String> it = mSharedLibraries.keySet().iterator(); while (it.hasNext()) { String name = it.next(); + SharedLibraryEntry ent = mSharedLibraries.get(name); + if (!printedHeader) { + if (dumpState.onTitlePrinted()) + pw.println(); + pw.println("Libraries:"); + printedHeader = true; + } pw.print(" "); pw.print(name); pw.print(" -> "); - SharedLibraryEntry ent = mSharedLibraries.get(name); if (ent.path != null) { pw.print("(jar) "); pw.print(ent.path); @@ -10109,7 +10116,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (dumpState.isDumping(DumpState.DUMP_FEATURES) && packageName == null) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Features:"); Iterator<String> it = mAvailableFeatures.keySet().iterator(); while (it.hasNext()) { @@ -10185,7 +10192,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Registered ContentProviders:"); printedSomething = true; } @@ -10200,7 +10207,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("ContentProvider Authorities:"); printedSomething = true; } @@ -10214,10 +10221,7 @@ public class PackageManagerService extends IPackageManager.Stub { } if (dumpState.isDumping(DumpState.DUMP_KEYSETS)) { - if (dumpState.onTitlePrinted()) { - pw.println(" "); - } - mSettings.mKeySetManager.dump(pw); + mSettings.mKeySetManager.dump(pw, packageName, dumpState); } if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) { @@ -10230,10 +10234,10 @@ public class PackageManagerService extends IPackageManager.Stub { if (dumpState.isDumping(DumpState.DUMP_MESSAGES) && packageName == null) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); mSettings.dumpReadMessagesLPr(pw, dumpState); - pw.println(" "); + pw.println(); pw.println("Package warning messages:"); final File fname = getSettingsProblemFile(); FileInputStream in = null; diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index a9c2ea1..b7810ba 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -2893,7 +2893,7 @@ final class Settings { if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Packages:"); printedSomething = true; } @@ -2909,7 +2909,7 @@ final class Settings { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Renamed packages:"); printedSomething = true; } @@ -2929,7 +2929,7 @@ final class Settings { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Hidden system packages:"); printedSomething = true; } @@ -2946,7 +2946,7 @@ final class Settings { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Permissions:"); printedSomething = true; } @@ -2980,7 +2980,7 @@ final class Settings { } if (!printedSomething) { if (dumpState.onTitlePrinted()) - pw.println(" "); + pw.println(); pw.println("Shared users:"); printedSomething = true; } |