blob: 954476dbeb488c0012a1e7dc792750c3add17cb6 [file] [log] [blame]
Jacek Surazskif5b9c722009-05-18 12:09:59 +02001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080019import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.ApplicationInfo;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020025import android.os.Parcel;
26import android.os.Parcelable;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070027import android.os.SystemClock;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080028import android.os.SystemProperties;
29import android.provider.Settings;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020030import android.util.Printer;
Brad Fitzpatrick5b747192010-07-12 11:05:38 -070031
Dan Egnorb7f03672009-12-09 16:22:32 -080032import java.io.PrintWriter;
33import java.io.StringWriter;
Jacek Surazskif5b9c722009-05-18 12:09:59 +020034
35/**
36 * Describes an application error.
37 *
38 * A report has a type, which is one of
39 * <ul>
Dianne Hackborn271c2fe2011-08-09 19:35:13 -070040 * <li> {@link #TYPE_NONE} uninitialized instance of {@link ApplicationErrorReport}.
Jacek Surazskif5b9c722009-05-18 12:09:59 +020041 * <li> {@link #TYPE_CRASH} application crash. Information about the crash
42 * is stored in {@link #crashInfo}.
43 * <li> {@link #TYPE_ANR} application not responding. Information about the
44 * ANR is stored in {@link #anrInfo}.
Dianne Hackborn271c2fe2011-08-09 19:35:13 -070045 * <li> {@link #TYPE_BATTERY} user reported application is using too much
46 * battery. Information about the battery use is stored in {@link #batteryInfo}.
47 * <li> {@link #TYPE_RUNNING_SERVICE} user reported application is leaving an
48 * unneeded serive running. Information about the battery use is stored in
49 * {@link #runningServiceInfo}.
Jacek Surazskif5b9c722009-05-18 12:09:59 +020050 * </ul>
Jacek Surazskif5b9c722009-05-18 12:09:59 +020051 */
52
53public class ApplicationErrorReport implements Parcelable {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080054 // System property defining error report receiver for system apps
55 static final String SYSTEM_APPS_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.system.apps";
56
57 // System property defining default error report receiver
58 static final String DEFAULT_ERROR_RECEIVER_PROPERTY = "ro.error.receiver.default";
59
Jacek Surazskif5b9c722009-05-18 12:09:59 +020060 /**
61 * Uninitialized error report.
62 */
63 public static final int TYPE_NONE = 0;
64
65 /**
66 * An error report about an application crash.
67 */
68 public static final int TYPE_CRASH = 1;
69
70 /**
71 * An error report about an application that's not responding.
72 */
73 public static final int TYPE_ANR = 2;
74
75 /**
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080076 * An error report about an application that's consuming too much battery.
77 */
78 public static final int TYPE_BATTERY = 3;
79
80 /**
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070081 * A report from a user to a developer about a running service that the
82 * user doesn't think should be running.
Dianne Hackborn14bfa392010-07-24 19:58:06 -070083 */
84 public static final int TYPE_RUNNING_SERVICE = 5;
85
86 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +020087 * Type of this report. Can be one of {@link #TYPE_NONE},
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -070088 * {@link #TYPE_CRASH}, {@link #TYPE_ANR}, {@link #TYPE_BATTERY},
89 * or {@link #TYPE_RUNNING_SERVICE}.
Jacek Surazskif5b9c722009-05-18 12:09:59 +020090 */
91 public int type;
92
93 /**
94 * Package name of the application.
95 */
96 public String packageName;
97
98 /**
99 * Package name of the application which installed the application this
100 * report pertains to.
Dirk Dougherty4d7bc6552012-01-27 17:56:49 -0800101 * This identifies which market the application came from.
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200102 */
103 public String installerPackageName;
104
105 /**
106 * Process name of the application.
107 */
108 public String processName;
109
110 /**
111 * Time at which the error occurred.
112 */
113 public long time;
114
115 /**
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +0100116 * Set if the app is on the system image.
117 */
118 public boolean systemApp;
119
120 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200121 * If this report is of type {@link #TYPE_CRASH}, contains an instance
122 * of CrashInfo describing the crash; otherwise null.
123 */
124 public CrashInfo crashInfo;
125
126 /**
127 * If this report is of type {@link #TYPE_ANR}, contains an instance
128 * of AnrInfo describing the ANR; otherwise null.
129 */
130 public AnrInfo anrInfo;
131
132 /**
Jacek Surazski151de3d2010-02-26 22:52:44 +0100133 * If this report is of type {@link #TYPE_BATTERY}, contains an instance
134 * of BatteryInfo; otherwise null.
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800135 */
Jacek Surazski151de3d2010-02-26 22:52:44 +0100136 public BatteryInfo batteryInfo;
Brad Fitzpatrickcb9ceb12010-07-29 14:29:02 -0700137
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800138 /**
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700139 * If this report is of type {@link #TYPE_RUNNING_SERVICE}, contains an instance
140 * of RunningServiceInfo; otherwise null.
141 */
142 public RunningServiceInfo runningServiceInfo;
143
144 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200145 * Create an uninitialized instance of {@link ApplicationErrorReport}.
146 */
147 public ApplicationErrorReport() {
148 }
149
150 /**
151 * Create an instance of {@link ApplicationErrorReport} initialized from
152 * a parcel.
153 */
154 ApplicationErrorReport(Parcel in) {
Jacek Surazski28b0e5d2009-05-25 17:56:41 +0200155 readFromParcel(in);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200156 }
157
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800158 public static ComponentName getErrorReportReceiver(Context context,
159 String packageName, int appFlags) {
160 // check if error reporting is enabled in secure settings
Jeff Sharkey625239a2012-09-26 22:03:49 -0700161 int enabled = Settings.Global.getInt(context.getContentResolver(),
162 Settings.Global.SEND_ACTION_APP_ERROR, 0);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800163 if (enabled == 0) {
164 return null;
165 }
166
167 PackageManager pm = context.getPackageManager();
168
169 // look for receiver in the installer package
170 String candidate = pm.getInstallerPackageName(packageName);
171 ComponentName result = getErrorReportReceiver(pm, packageName, candidate);
172 if (result != null) {
173 return result;
174 }
175
176 // if the error app is on the system image, look for system apps
177 // error receiver
178 if ((appFlags&ApplicationInfo.FLAG_SYSTEM) != 0) {
179 candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY);
180 result = getErrorReportReceiver(pm, packageName, candidate);
181 if (result != null) {
182 return result;
183 }
184 }
185
186 // if there is a default receiver, try that
187 candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY);
188 return getErrorReportReceiver(pm, packageName, candidate);
189 }
Jacek Surazski87d0b2f2010-08-02 13:03:35 +0200190
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800191 /**
192 * Return activity in receiverPackage that handles ACTION_APP_ERROR.
193 *
Madan Ankapuraae96f632010-06-18 18:16:58 -0700194 * @param pm PackageManager instance
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800195 * @param errorPackage package which caused the error
196 * @param receiverPackage candidate package to receive the error
197 * @return activity component within receiverPackage which handles
198 * ACTION_APP_ERROR, or null if not found
199 */
200 static ComponentName getErrorReportReceiver(PackageManager pm, String errorPackage,
201 String receiverPackage) {
202 if (receiverPackage == null || receiverPackage.length() == 0) {
203 return null;
204 }
205
206 // break the loop if it's the error report receiver package that crashed
207 if (receiverPackage.equals(errorPackage)) {
208 return null;
209 }
210
211 Intent intent = new Intent(Intent.ACTION_APP_ERROR);
212 intent.setPackage(receiverPackage);
213 ResolveInfo info = pm.resolveActivity(intent, 0);
214 if (info == null || info.activityInfo == null) {
215 return null;
216 }
217 return new ComponentName(receiverPackage, info.activityInfo.name);
218 }
219
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200220 public void writeToParcel(Parcel dest, int flags) {
221 dest.writeInt(type);
222 dest.writeString(packageName);
223 dest.writeString(installerPackageName);
224 dest.writeString(processName);
225 dest.writeLong(time);
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +0100226 dest.writeInt(systemApp ? 1 : 0);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200227
228 switch (type) {
229 case TYPE_CRASH:
230 crashInfo.writeToParcel(dest, flags);
231 break;
232 case TYPE_ANR:
233 anrInfo.writeToParcel(dest, flags);
234 break;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800235 case TYPE_BATTERY:
Jacek Surazski151de3d2010-02-26 22:52:44 +0100236 batteryInfo.writeToParcel(dest, flags);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800237 break;
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700238 case TYPE_RUNNING_SERVICE:
239 runningServiceInfo.writeToParcel(dest, flags);
240 break;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200241 }
242 }
243
Jacek Surazskifd0bdcc2009-05-27 14:45:48 +0200244 public void readFromParcel(Parcel in) {
Jacek Surazski28b0e5d2009-05-25 17:56:41 +0200245 type = in.readInt();
246 packageName = in.readString();
247 installerPackageName = in.readString();
248 processName = in.readString();
249 time = in.readLong();
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +0100250 systemApp = in.readInt() == 1;
Jacek Surazski28b0e5d2009-05-25 17:56:41 +0200251
252 switch (type) {
253 case TYPE_CRASH:
254 crashInfo = new CrashInfo(in);
255 anrInfo = null;
Jacek Surazski151de3d2010-02-26 22:52:44 +0100256 batteryInfo = null;
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700257 runningServiceInfo = null;
Jacek Surazski28b0e5d2009-05-25 17:56:41 +0200258 break;
259 case TYPE_ANR:
260 anrInfo = new AnrInfo(in);
261 crashInfo = null;
Jacek Surazski151de3d2010-02-26 22:52:44 +0100262 batteryInfo = null;
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700263 runningServiceInfo = null;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800264 break;
265 case TYPE_BATTERY:
Jacek Surazski151de3d2010-02-26 22:52:44 +0100266 batteryInfo = new BatteryInfo(in);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800267 anrInfo = null;
268 crashInfo = null;
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700269 runningServiceInfo = null;
270 break;
271 case TYPE_RUNNING_SERVICE:
272 batteryInfo = null;
273 anrInfo = null;
274 crashInfo = null;
275 runningServiceInfo = new RunningServiceInfo(in);
Jacek Surazski28b0e5d2009-05-25 17:56:41 +0200276 break;
277 }
278 }
279
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200280 /**
281 * Describes an application crash.
282 */
283 public static class CrashInfo {
284 /**
285 * Class name of the exception that caused the crash.
286 */
287 public String exceptionClassName;
288
289 /**
Jacek Surazskif829a782009-06-11 22:47:02 +0200290 * Message stored in the exception.
291 */
292 public String exceptionMessage;
293
294 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200295 * File which the exception was thrown from.
296 */
297 public String throwFileName;
298
299 /**
300 * Class which the exception was thrown from.
301 */
302 public String throwClassName;
303
304 /**
305 * Method which the exception was thrown from.
306 */
307 public String throwMethodName;
308
309 /**
Jacek Surazski5a123732009-06-23 14:57:08 +0200310 * Line number the exception was thrown from.
311 */
312 public int throwLineNumber;
313
314 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200315 * Stack trace.
316 */
317 public String stackTrace;
318
319 /**
320 * Create an uninitialized instance of CrashInfo.
321 */
322 public CrashInfo() {
323 }
324
325 /**
Dan Egnorb7f03672009-12-09 16:22:32 -0800326 * Create an instance of CrashInfo initialized from an exception.
327 */
328 public CrashInfo(Throwable tr) {
329 StringWriter sw = new StringWriter();
330 tr.printStackTrace(new PrintWriter(sw));
331 stackTrace = sw.toString();
Dan Egnor60d87622009-12-16 16:32:58 -0800332 exceptionMessage = tr.getMessage();
Dan Egnorb7f03672009-12-09 16:22:32 -0800333
334 // Populate fields with the "root cause" exception
Dianne Hackborn8e8d65f2011-08-11 19:36:18 -0700335 Throwable rootTr = tr;
Dan Egnorb7f03672009-12-09 16:22:32 -0800336 while (tr.getCause() != null) {
337 tr = tr.getCause();
Dianne Hackborn8e8d65f2011-08-11 19:36:18 -0700338 if (tr.getStackTrace() != null && tr.getStackTrace().length > 0) {
339 rootTr = tr;
340 }
Dan Egnorb7f03672009-12-09 16:22:32 -0800341 String msg = tr.getMessage();
342 if (msg != null && msg.length() > 0) {
343 exceptionMessage = msg;
344 }
345 }
346
Dianne Hackborn8e8d65f2011-08-11 19:36:18 -0700347 exceptionClassName = rootTr.getClass().getName();
348 if (rootTr.getStackTrace().length > 0) {
349 StackTraceElement trace = rootTr.getStackTrace()[0];
350 throwFileName = trace.getFileName();
351 throwClassName = trace.getClassName();
352 throwMethodName = trace.getMethodName();
353 throwLineNumber = trace.getLineNumber();
354 } else {
355 throwFileName = "unknown";
356 throwClassName = "unknown";
357 throwMethodName = "unknown";
358 throwLineNumber = 0;
359 }
Dan Egnorb7f03672009-12-09 16:22:32 -0800360 }
361
362 /**
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200363 * Create an instance of CrashInfo initialized from a Parcel.
364 */
365 public CrashInfo(Parcel in) {
366 exceptionClassName = in.readString();
Jacek Surazskif829a782009-06-11 22:47:02 +0200367 exceptionMessage = in.readString();
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200368 throwFileName = in.readString();
369 throwClassName = in.readString();
370 throwMethodName = in.readString();
Jacek Surazski5a123732009-06-23 14:57:08 +0200371 throwLineNumber = in.readInt();
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200372 stackTrace = in.readString();
373 }
374
375 /**
376 * Save a CrashInfo instance to a parcel.
377 */
378 public void writeToParcel(Parcel dest, int flags) {
379 dest.writeString(exceptionClassName);
Jacek Surazskif829a782009-06-11 22:47:02 +0200380 dest.writeString(exceptionMessage);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200381 dest.writeString(throwFileName);
382 dest.writeString(throwClassName);
383 dest.writeString(throwMethodName);
Jacek Surazski5a123732009-06-23 14:57:08 +0200384 dest.writeInt(throwLineNumber);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200385 dest.writeString(stackTrace);
386 }
387
388 /**
389 * Dump a CrashInfo instance to a Printer.
390 */
391 public void dump(Printer pw, String prefix) {
392 pw.println(prefix + "exceptionClassName: " + exceptionClassName);
Jacek Surazskif829a782009-06-11 22:47:02 +0200393 pw.println(prefix + "exceptionMessage: " + exceptionMessage);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200394 pw.println(prefix + "throwFileName: " + throwFileName);
395 pw.println(prefix + "throwClassName: " + throwClassName);
396 pw.println(prefix + "throwMethodName: " + throwMethodName);
Jacek Surazski5a123732009-06-23 14:57:08 +0200397 pw.println(prefix + "throwLineNumber: " + throwLineNumber);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200398 pw.println(prefix + "stackTrace: " + stackTrace);
399 }
400 }
401
402 /**
403 * Describes an application not responding error.
404 */
405 public static class AnrInfo {
406 /**
407 * Activity name.
408 */
409 public String activity;
410
411 /**
412 * Description of the operation that timed out.
413 */
414 public String cause;
415
416 /**
417 * Additional info, including CPU stats.
418 */
419 public String info;
420
421 /**
422 * Create an uninitialized instance of AnrInfo.
423 */
424 public AnrInfo() {
425 }
426
427 /**
428 * Create an instance of AnrInfo initialized from a Parcel.
429 */
430 public AnrInfo(Parcel in) {
431 activity = in.readString();
432 cause = in.readString();
433 info = in.readString();
434 }
435
436 /**
437 * Save an AnrInfo instance to a parcel.
438 */
439 public void writeToParcel(Parcel dest, int flags) {
440 dest.writeString(activity);
441 dest.writeString(cause);
442 dest.writeString(info);
443 }
444
445 /**
446 * Dump an AnrInfo instance to a Printer.
447 */
448 public void dump(Printer pw, String prefix) {
449 pw.println(prefix + "activity: " + activity);
450 pw.println(prefix + "cause: " + cause);
451 pw.println(prefix + "info: " + info);
452 }
453 }
454
Jacek Surazski151de3d2010-02-26 22:52:44 +0100455 /**
456 * Describes a battery usage report.
457 */
458 public static class BatteryInfo {
459 /**
460 * Percentage of the battery that was used up by the process.
461 */
462 public int usagePercent;
463
464 /**
465 * Duration in microseconds over which the process used the above
466 * percentage of battery.
467 */
468 public long durationMicros;
469
470 /**
471 * Dump of various info impacting battery use.
472 */
473 public String usageDetails;
474
475 /**
476 * Checkin details.
477 */
478 public String checkinDetails;
479
480 /**
481 * Create an uninitialized instance of BatteryInfo.
482 */
483 public BatteryInfo() {
484 }
485
486 /**
487 * Create an instance of BatteryInfo initialized from a Parcel.
488 */
489 public BatteryInfo(Parcel in) {
490 usagePercent = in.readInt();
491 durationMicros = in.readLong();
492 usageDetails = in.readString();
493 checkinDetails = in.readString();
494 }
495
496 /**
497 * Save a BatteryInfo instance to a parcel.
498 */
499 public void writeToParcel(Parcel dest, int flags) {
500 dest.writeInt(usagePercent);
501 dest.writeLong(durationMicros);
502 dest.writeString(usageDetails);
503 dest.writeString(checkinDetails);
504 }
505
506 /**
507 * Dump a BatteryInfo instance to a Printer.
508 */
509 public void dump(Printer pw, String prefix) {
510 pw.println(prefix + "usagePercent: " + usagePercent);
511 pw.println(prefix + "durationMicros: " + durationMicros);
512 pw.println(prefix + "usageDetails: " + usageDetails);
513 pw.println(prefix + "checkinDetails: " + checkinDetails);
514 }
515 }
516
Dianne Hackborn14bfa392010-07-24 19:58:06 -0700517 /**
518 * Describes a running service report.
519 */
520 public static class RunningServiceInfo {
521 /**
522 * Duration in milliseconds that the service has been running.
523 */
524 public long durationMillis;
525
526 /**
527 * Dump of debug information about the service.
528 */
529 public String serviceDetails;
530
531 /**
532 * Create an uninitialized instance of RunningServiceInfo.
533 */
534 public RunningServiceInfo() {
535 }
536
537 /**
538 * Create an instance of RunningServiceInfo initialized from a Parcel.
539 */
540 public RunningServiceInfo(Parcel in) {
541 durationMillis = in.readLong();
542 serviceDetails = in.readString();
543 }
544
545 /**
546 * Save a RunningServiceInfo instance to a parcel.
547 */
548 public void writeToParcel(Parcel dest, int flags) {
549 dest.writeLong(durationMillis);
550 dest.writeString(serviceDetails);
551 }
552
553 /**
554 * Dump a BatteryInfo instance to a Printer.
555 */
556 public void dump(Printer pw, String prefix) {
557 pw.println(prefix + "durationMillis: " + durationMillis);
558 pw.println(prefix + "serviceDetails: " + serviceDetails);
559 }
560 }
561
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200562 public static final Parcelable.Creator<ApplicationErrorReport> CREATOR
563 = new Parcelable.Creator<ApplicationErrorReport>() {
564 public ApplicationErrorReport createFromParcel(Parcel source) {
565 return new ApplicationErrorReport(source);
566 }
567
568 public ApplicationErrorReport[] newArray(int size) {
569 return new ApplicationErrorReport[size];
570 }
571 };
572
573 public int describeContents() {
574 return 0;
575 }
576
577 /**
578 * Dump the report to a Printer.
579 */
580 public void dump(Printer pw, String prefix) {
581 pw.println(prefix + "type: " + type);
582 pw.println(prefix + "packageName: " + packageName);
583 pw.println(prefix + "installerPackageName: " + installerPackageName);
584 pw.println(prefix + "processName: " + processName);
585 pw.println(prefix + "time: " + time);
Jacek Surazskie0ee6ef2010-01-07 16:23:03 +0100586 pw.println(prefix + "systemApp: " + systemApp);
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200587
588 switch (type) {
589 case TYPE_CRASH:
590 crashInfo.dump(pw, prefix);
591 break;
592 case TYPE_ANR:
593 anrInfo.dump(pw, prefix);
594 break;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800595 case TYPE_BATTERY:
Jacek Surazski151de3d2010-02-26 22:52:44 +0100596 batteryInfo.dump(pw, prefix);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800597 break;
Jacek Surazski87d0b2f2010-08-02 13:03:35 +0200598 case TYPE_RUNNING_SERVICE:
599 runningServiceInfo.dump(pw, prefix);
600 break;
Jacek Surazskif5b9c722009-05-18 12:09:59 +0200601 }
602 }
603}