Infrastructure to report running services to developer.
Change-Id: Id1aae61323e7b8357c5fcc4bc641aaa57f3b6fde
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user