Infrastructure to report running services to developer.

Change-Id: Id1aae61323e7b8357c5fcc4bc641aaa57f3b6fde
This commit is contained in:
Dianne Hackborn
2010-07-24 19:58:06 -07:00
parent 3ac8eb7278
commit 14bfa398a4
2 changed files with 93 additions and 8 deletions

View File

@@ -78,6 +78,11 @@ public class ApplicationErrorReport implements Parcelable {
*/ */
public static final int TYPE_STRICT_MODE_VIOLATION = 4; public static final int TYPE_STRICT_MODE_VIOLATION = 4;
/**
* An error report about a StrictMode violation.
*/
public static final int TYPE_RUNNING_SERVICE = 5;
/** /**
* Type of this report. Can be one of {@link #TYPE_NONE}, * Type of this report. Can be one of {@link #TYPE_NONE},
* {@link #TYPE_CRASH}, {@link #TYPE_ANR}, or {@link #TYPE_BATTERY}. * {@link #TYPE_CRASH}, {@link #TYPE_ANR}, or {@link #TYPE_BATTERY}.
@@ -129,6 +134,12 @@ public class ApplicationErrorReport implements Parcelable {
*/ */
public BatteryInfo batteryInfo; public BatteryInfo batteryInfo;
/**
* If this report is of type {@link #TYPE_RUNNING_SERVICE}, contains an instance
* of RunningServiceInfo; otherwise null.
*/
public RunningServiceInfo runningServiceInfo;
/** /**
* Create an uninitialized instance of {@link ApplicationErrorReport}. * Create an uninitialized instance of {@link ApplicationErrorReport}.
*/ */
@@ -223,6 +234,9 @@ public class ApplicationErrorReport implements Parcelable {
case TYPE_BATTERY: case TYPE_BATTERY:
batteryInfo.writeToParcel(dest, flags); batteryInfo.writeToParcel(dest, flags);
break; break;
case TYPE_RUNNING_SERVICE:
runningServiceInfo.writeToParcel(dest, flags);
break;
} }
} }
@@ -239,16 +253,25 @@ public class ApplicationErrorReport implements Parcelable {
crashInfo = new CrashInfo(in); crashInfo = new CrashInfo(in);
anrInfo = null; anrInfo = null;
batteryInfo = null; batteryInfo = null;
runningServiceInfo = null;
break; break;
case TYPE_ANR: case TYPE_ANR:
anrInfo = new AnrInfo(in); anrInfo = new AnrInfo(in);
crashInfo = null; crashInfo = null;
batteryInfo = null; batteryInfo = null;
runningServiceInfo = null;
break; break;
case TYPE_BATTERY: case TYPE_BATTERY:
batteryInfo = new BatteryInfo(in); batteryInfo = new BatteryInfo(in);
anrInfo = null; anrInfo = null;
crashInfo = null; crashInfo = null;
runningServiceInfo = null;
break;
case TYPE_RUNNING_SERVICE:
batteryInfo = null;
anrInfo = null;
crashInfo = null;
runningServiceInfo = new RunningServiceInfo(in);
break; break;
} }
} }
@@ -494,6 +517,51 @@ public class ApplicationErrorReport implements Parcelable {
} }
} }
/**
* Describes a running service report.
*/
public static class RunningServiceInfo {
/**
* Duration in milliseconds that the service has been running.
*/
public long durationMillis;
/**
* Dump of debug information about the service.
*/
public String serviceDetails;
/**
* Create an uninitialized instance of RunningServiceInfo.
*/
public RunningServiceInfo() {
}
/**
* Create an instance of RunningServiceInfo initialized from a Parcel.
*/
public RunningServiceInfo(Parcel in) {
durationMillis = in.readLong();
serviceDetails = in.readString();
}
/**
* Save a RunningServiceInfo instance to a parcel.
*/
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(durationMillis);
dest.writeString(serviceDetails);
}
/**
* Dump a BatteryInfo instance to a Printer.
*/
public void dump(Printer pw, String prefix) {
pw.println(prefix + "durationMillis: " + durationMillis);
pw.println(prefix + "serviceDetails: " + serviceDetails);
}
}
public static final Parcelable.Creator<ApplicationErrorReport> CREATOR public static final Parcelable.Creator<ApplicationErrorReport> CREATOR
= new Parcelable.Creator<ApplicationErrorReport>() { = new Parcelable.Creator<ApplicationErrorReport>() {
public ApplicationErrorReport createFromParcel(Parcel source) { public ApplicationErrorReport createFromParcel(Parcel source) {

View File

@@ -6752,7 +6752,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
} }
return; return;
} else if ("service".equals(cmd)) { } else if ("service".equals(cmd)) {
dumpService(fd, pw, args, opti, true); dumpService(fd, pw, args, opti, dumpAll);
return; return;
} else if ("services".equals(cmd) || "s".equals(cmd)) { } else if ("services".equals(cmd) || "s".equals(cmd)) {
synchronized (this) { synchronized (this) {
@@ -7058,29 +7058,45 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
componentNameString = args[opti]; componentNameString = args[opti];
opti++; opti++;
ComponentName componentName = ComponentName.unflattenFromString(componentNameString); ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
synchronized (this) {
r = componentName != null ? mServices.get(componentName) : null; r = componentName != null ? mServices.get(componentName) : null;
}
newArgs = new String[args.length - opti]; newArgs = new String[args.length - opti];
if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti); if (args.length > 2) System.arraycopy(args, opti, newArgs, 0, args.length - opti);
} }
if (r != null) { if (r != null) {
dumpService(fd, pw, r, newArgs); dumpService(fd, pw, r, newArgs, dumpAll);
} else { } else {
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
synchronized (this) {
for (ServiceRecord r1 : mServices.values()) { for (ServiceRecord r1 : mServices.values()) {
if (componentNameString == null if (componentNameString == null
|| r1.name.flattenToString().contains(componentNameString)) { || r1.name.flattenToString().contains(componentNameString)) {
dumpService(fd, pw, r1, newArgs); services.add(r1);
} }
} }
} }
for (int i=0; i<services.size(); i++) {
dumpService(fd, pw, services.get(i), newArgs, dumpAll);
}
}
} }
/** /**
* Invokes IApplicationThread.dumpService() on the thread of the specified service if * Invokes IApplicationThread.dumpService() on the thread of the specified service if
* there is a thread associated with the service. * there is a thread associated with the service.
*/ */
private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) { private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
boolean dumpAll) {
pw.println(" Service " + r.name.flattenToString()); pw.println(" Service " + r.name.flattenToString());
if (dumpAll) {
synchronized (this) {
pw.print(" * "); pw.println(r);
r.dump(pw, " ");
}
pw.println("");
}
if (r.app != null && r.app.thread != null) { if (r.app != null && r.app.thread != null) {
try { try {
// flush anything that is already in the PrintWriter since the thread is going // flush anything that is already in the PrintWriter since the thread is going
@@ -7088,6 +7104,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
pw.flush(); pw.flush();
r.app.thread.dumpService(fd, r, args); r.app.thread.dumpService(fd, r, args);
pw.print("\n"); pw.print("\n");
pw.flush();
} catch (RemoteException e) { } catch (RemoteException e) {
pw.println("got a RemoteException while dumping the service"); pw.println("got a RemoteException while dumping the service");
} }