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 /services/java | |
| parent | be4e6aaa0252dd7da28b7aa85beba982538efa46 (diff) | |
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
Diffstat (limited to 'services/java')
9 files changed, 79 insertions, 273 deletions
diff --git a/services/java/com/android/server/am/ActiveServices.java b/services/java/com/android/server/am/ActiveServices.java index 98c43521208e..a5d64b2c89de 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 f06b9a62fc78..fc3183f401cf 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 af61bfb5802f..6fe28f4c884e 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 5a15f0bb8846..f143feb83363 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 5759a4485e80..7da8c48dea35 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/am/TransferPipe.java b/services/java/com/android/server/am/TransferPipe.java deleted file mode 100644 index 055c577316fe..000000000000 --- a/services/java/com/android/server/am/TransferPipe.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.am; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import android.os.Binder; -import android.os.IBinder; -import android.os.IInterface; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.os.SystemClock; -import android.util.Slog; - -/** - * Helper for transferring data through a pipe from a client app. - */ -final class TransferPipe implements Runnable { - static final String TAG = "TransferPipe"; - static final boolean DEBUG = false; - - static final long DEFAULT_TIMEOUT = 5000; // 5 seconds - - final Thread mThread;; - final ParcelFileDescriptor[] mFds; - - FileDescriptor mOutFd; - long mEndTime; - String mFailure; - boolean mComplete; - - String mBufferPrefix; - - interface Caller { - void go(IInterface iface, FileDescriptor fd, String prefix, - String[] args) throws RemoteException; - } - - TransferPipe() throws IOException { - mThread = new Thread(this, "TransferPipe"); - mFds = ParcelFileDescriptor.createPipe(); - } - - ParcelFileDescriptor getReadFd() { - return mFds[0]; - } - - ParcelFileDescriptor getWriteFd() { - return mFds[1]; - } - - void setBufferPrefix(String prefix) { - mBufferPrefix = prefix; - } - - static void go(Caller caller, IInterface iface, FileDescriptor out, - String prefix, String[] args) throws IOException, RemoteException { - go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT); - } - - static void go(Caller caller, IInterface iface, FileDescriptor out, - String prefix, String[] args, long timeout) throws IOException, RemoteException { - if ((iface.asBinder()) instanceof Binder) { - // This is a local object... just call it directly. - try { - caller.go(iface, out, prefix, args); - } catch (RemoteException e) { - } - return; - } - - TransferPipe tp = new TransferPipe(); - try { - caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args); - tp.go(out, timeout); - } finally { - tp.kill(); - } - } - - static void goDump(IBinder binder, FileDescriptor out, - String[] args) throws IOException, RemoteException { - goDump(binder, out, args, DEFAULT_TIMEOUT); - } - - static void goDump(IBinder binder, FileDescriptor out, - String[] args, long timeout) throws IOException, RemoteException { - if (binder instanceof Binder) { - // This is a local object... just call it directly. - try { - binder.dump(out, args); - } catch (RemoteException e) { - } - return; - } - - TransferPipe tp = new TransferPipe(); - try { - binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); - tp.go(out, timeout); - } finally { - tp.kill(); - } - } - - void go(FileDescriptor out) throws IOException { - go(out, DEFAULT_TIMEOUT); - } - - void go(FileDescriptor out, long timeout) throws IOException { - try { - synchronized (this) { - mOutFd = out; - mEndTime = SystemClock.uptimeMillis() + timeout; - - if (DEBUG) Slog.i(TAG, "read=" + getReadFd() + " write=" + getWriteFd() - + " out=" + out); - - // Close the write fd, so we know when the other side is done. - closeFd(1); - - mThread.start(); - - while (mFailure == null && !mComplete) { - long waitTime = mEndTime - SystemClock.uptimeMillis(); - if (waitTime <= 0) { - if (DEBUG) Slog.i(TAG, "TIMEOUT!"); - mThread.interrupt(); - throw new IOException("Timeout"); - } - - try { - wait(waitTime); - } catch (InterruptedException e) { - } - } - - if (DEBUG) Slog.i(TAG, "Finished: " + mFailure); - if (mFailure != null) { - throw new IOException(mFailure); - } - } - } finally { - kill(); - } - } - - void closeFd(int num) { - if (mFds[num] != null) { - if (DEBUG) Slog.i(TAG, "Closing: " + mFds[num]); - try { - mFds[num].close(); - } catch (IOException e) { - } - mFds[num] = null; - } - } - - void kill() { - closeFd(0); - closeFd(1); - } - - @Override - public void run() { - final byte[] buffer = new byte[1024]; - final FileInputStream fis = new FileInputStream(getReadFd().getFileDescriptor()); - final FileOutputStream fos = new FileOutputStream(mOutFd); - - if (DEBUG) Slog.i(TAG, "Ready to read pipe..."); - byte[] bufferPrefix = null; - boolean needPrefix = true; - if (mBufferPrefix != null) { - bufferPrefix = mBufferPrefix.getBytes(); - } - - int size; - try { - while ((size=fis.read(buffer)) > 0) { - if (DEBUG) Slog.i(TAG, "Got " + size + " bytes"); - if (bufferPrefix == null) { - fos.write(buffer, 0, size); - } else { - int start = 0; - for (int i=0; i<size; i++) { - if (buffer[i] != '\n') { - if (i > start) { - fos.write(buffer, start, i-start); - } - start = i; - if (needPrefix) { - fos.write(bufferPrefix); - needPrefix = false; - } - do { - i++; - } while (i<size && buffer[i] != '\n'); - if (i < size) { - needPrefix = true; - } - } - } - if (size > start) { - fos.write(buffer, start, size-start); - } - } - } - if (DEBUG) Slog.i(TAG, "End of pipe: size=" + size); - if (mThread.isInterrupted()) { - if (DEBUG) Slog.i(TAG, "Interrupted!"); - } - } catch (IOException e) { - synchronized (this) { - mFailure = e.toString(); - notifyAll(); - return; - } - } - - synchronized (this) { - mComplete = true; - notifyAll(); - } - } -} diff --git a/services/java/com/android/server/pm/KeySetManager.java b/services/java/com/android/server/pm/KeySetManager.java index f154ab3a0d88..8272c1579768 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 07805f9d35c5..5e6e0553c3a1 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 a9c2ea17c174..b7810ba8d75a 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; } |
