summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDan Egnor <egnor@google.com>2009-12-09 16:22:32 -0800
committerDan Egnor <egnor@google.com>2009-12-11 13:27:04 -0800
commitb7f0367cec1c744aa66ef397b0244e25d507491c (patch)
tree7b70d87b9886ea1567647aac00fccb3198accc8c /core/java
parentaf1255dab8fa3eab1caf9bae799f80de14a74470 (diff)
downloadframeworks_base-b7f0367cec1c744aa66ef397b0244e25d507491c.zip
frameworks_base-b7f0367cec1c744aa66ef397b0244e25d507491c.tar.gz
frameworks_base-b7f0367cec1c744aa66ef397b0244e25d507491c.tar.bz2
Eliminate CrashData and friends.
(CrashData was a custom-marshalled crash-info class used for a server crash reporting system I am deprecating). Use ApplicationErrorReport.CrashInfo instead to report crash details (mostly the stack trace) from RuntimeInfo to ActivityManagerService, since we're likely to need the crash information in that form anyway. Remove the (long-disabled) flags and support for the "Debug" button in the crash dialog. Further gut the ICheckinService interface by removing the crash-reporting APIs (and everything that calls them), plus the synchronous checkin() method (which has been stubbed out for a while now). A new dropbox-based crash reporting system is in the works, but not part of this change.
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/ActivityManager.java21
-rw-r--r--core/java/android/app/ActivityManagerNative.java25
-rw-r--r--core/java/android/app/ApplicationErrorReport.java27
-rw-r--r--core/java/android/app/IActivityController.aidl5
-rw-r--r--core/java/android/app/IActivityManager.java8
-rw-r--r--core/java/android/os/ICheckinService.aidl15
-rw-r--r--core/java/android/provider/Checkin.java56
-rw-r--r--core/java/android/server/data/BuildData.java89
-rw-r--r--core/java/android/server/data/CrashData.java145
-rw-r--r--core/java/android/server/data/StackTraceElementData.java80
-rw-r--r--core/java/android/server/data/ThrowableData.java138
-rwxr-xr-xcore/java/android/server/data/package.html5
-rw-r--r--core/java/android/util/Log.java4
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java123
14 files changed, 57 insertions, 684 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d709deb..676d6d5 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -621,9 +621,15 @@ public class ActivityManager {
public String longMsg;
/**
- * Raw data about the crash (typically a stack trace).
+ * The stack trace where the error originated. May be null.
+ * @pending
*/
- public byte[] crashData;
+ public String stackTrace;
+
+ /**
+ * to be deprecated: This value will always be null.
+ */
+ public byte[] crashData = null;
public ProcessErrorStateInfo() {
}
@@ -640,8 +646,7 @@ public class ActivityManager {
dest.writeString(tag);
dest.writeString(shortMsg);
dest.writeString(longMsg);
- dest.writeInt(crashData == null ? -1 : crashData.length);
- dest.writeByteArray(crashData);
+ dest.writeString(stackTrace);
}
public void readFromParcel(Parcel source) {
@@ -652,13 +657,7 @@ public class ActivityManager {
tag = source.readString();
shortMsg = source.readString();
longMsg = source.readString();
- int cdLen = source.readInt();
- if (cdLen == -1) {
- crashData = null;
- } else {
- crashData = new byte[cdLen];
- source.readByteArray(crashData);
- }
+ stackTrace = source.readString();
}
public static final Creator<ProcessErrorStateInfo> CREATOR =
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 3b8aee9..a0498aa 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -982,18 +982,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case HANDLE_APPLICATION_ERROR_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder app = data.readStrongBinder();
- int fl = data.readInt();
String tag = data.readString();
- String shortMsg = data.readString();
- String longMsg = data.readString();
- byte[] crashData = data.createByteArray();
- int res = handleApplicationError(app, fl, tag, shortMsg, longMsg,
- crashData);
+ ApplicationErrorReport.CrashInfo ci = new ApplicationErrorReport.CrashInfo(data);
+ handleApplicationError(app, tag, ci);
reply.writeNoException();
- reply.writeInt(res);
return true;
}
-
+
case SIGNAL_PERSISTENT_PROCESSES_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int sig = data.readInt();
@@ -2342,27 +2337,21 @@ class ActivityManagerProxy implements IActivityManager
/* this base class version is never called */
return true;
}
- public int handleApplicationError(IBinder app, int flags,
- String tag, String shortMsg, String longMsg,
- byte[] crashData) throws RemoteException
+ public void handleApplicationError(IBinder app, String tag,
+ ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app);
- data.writeInt(flags);
data.writeString(tag);
- data.writeString(shortMsg);
- data.writeString(longMsg);
- data.writeByteArray(crashData);
+ crashInfo.writeToParcel(data, 0);
mRemote.transact(HANDLE_APPLICATION_ERROR_TRANSACTION, data, reply, 0);
reply.readException();
- int res = reply.readInt();
reply.recycle();
data.recycle();
- return res;
}
-
+
public void signalPersistentProcesses(int sig) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index aeae5f9..e89b3ad0 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -19,6 +19,8 @@ package android.app;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Printer;
+import java.io.PrintWriter;
+import java.io.StringWriter;
/**
* Describes an application error.
@@ -187,6 +189,31 @@ public class ApplicationErrorReport implements Parcelable {
}
/**
+ * Create an instance of CrashInfo initialized from an exception.
+ */
+ public CrashInfo(Throwable tr) {
+ StringWriter sw = new StringWriter();
+ tr.printStackTrace(new PrintWriter(sw));
+ stackTrace = sw.toString();
+
+ // Populate fields with the "root cause" exception
+ while (tr.getCause() != null) {
+ tr = tr.getCause();
+ String msg = tr.getMessage();
+ if (msg != null && msg.length() > 0) {
+ exceptionMessage = msg;
+ }
+ }
+
+ exceptionClassName = tr.getClass().getName();
+ StackTraceElement trace = tr.getStackTrace()[0];
+ throwFileName = trace.getFileName();
+ throwClassName = trace.getClassName();
+ throwMethodName = trace.getMethodName();
+ throwLineNumber = trace.getLineNumber();
+ }
+
+ /**
* Create an instance of CrashInfo initialized from a Parcel.
*/
public CrashInfo(Parcel in) {
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
index 8f6b252..804dd61 100644
--- a/core/java/android/app/IActivityController.aidl
+++ b/core/java/android/app/IActivityController.aidl
@@ -43,8 +43,9 @@ interface IActivityController
* normal error recovery (app crash dialog) to occur, false to kill
* it immediately.
*/
- boolean appCrashed(String processName, int pid, String shortMsg,
- String longMsg, in byte[] crashData);
+ boolean appCrashed(String processName, int pid,
+ String tag, String shortMsg, String longMsg,
+ long timeMillis, String stackTrace);
/**
* An application process is not responding. Return 0 to show the "app
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9f505ac..c890c4c 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -242,11 +242,9 @@ public interface IActivityManager extends IInterface {
// Special low-level communication with activity manager.
public void startRunning(String pkg, String cls, String action,
String data) throws RemoteException;
- // Returns 1 if the user wants to debug.
- public int handleApplicationError(IBinder app,
- int flags, /* 1 == can debug */
- String tag, String shortMsg, String longMsg,
- byte[] crashData) throws RemoteException;
+
+ public void handleApplicationError(IBinder app, String tag,
+ ApplicationErrorReport.CrashInfo crashInfo) throws RemoteException;
/*
* This will deliver the specified signal to all the persistent processes. Currently only
diff --git a/core/java/android/os/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl
index e56b55d..619079a 100644
--- a/core/java/android/os/ICheckinService.aidl
+++ b/core/java/android/os/ICheckinService.aidl
@@ -26,21 +26,6 @@ import android.os.IParentalControlCallback;
* {@hide}
*/
interface ICheckinService {
- /** Synchronously attempt a checkin with the server, return true
- * on success.
- * @throws IllegalStateException whenever an error occurs. The
- * cause of the exception will be the real exception:
- * IOException for network errors, JSONException for invalid
- * server responses, etc.
- */
- boolean checkin();
-
- /** Direct submission of crash data; returns after writing the crash. */
- void reportCrashSync(in byte[] crashData);
-
- /** Asynchronous "fire and forget" version of crash reporting. */
- oneway void reportCrashAsync(in byte[] crashData);
-
/** Reboot into the recovery system and wipe all user data. */
void masterClear();
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index 84753ee..75936a1 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -23,7 +23,6 @@ import android.content.ContentValues;
import android.database.SQLException;
import android.net.Uri;
import android.os.SystemClock;
-import android.server.data.CrashData;
import android.util.Log;
import java.io.ByteArrayOutputStream;
@@ -267,59 +266,4 @@ public final class Checkin {
/** {@link SystemClock#elapsedRealtime} of the last time a crash report failed. */
static private volatile long sLastCrashFailureRealtime = -MIN_CRASH_FAILURE_RETRY;
-
- /**
- * Helper function to report a crash.
- *
- * @param resolver from {@link android.content.Context#getContentResolver}
- * @param crash data from {@link android.server.data.CrashData}
- * @return URI of the crash report that was added
- */
- static public Uri reportCrash(ContentResolver resolver, byte[] crash) {
- try {
- // If we are in a situation where crash reports fail (such as a full disk),
- // it's important that we don't get into a loop trying to report failures.
- // So discard all crash reports for a few seconds after reporting fails.
- long realtime = SystemClock.elapsedRealtime();
- if (realtime - sLastCrashFailureRealtime < MIN_CRASH_FAILURE_RETRY) {
- Log.e(TAG, "Crash logging skipped, too soon after logging failure");
- return null;
- }
-
- // HACK: we don't support BLOB values, so base64 encode it.
- byte[] encoded = Base64.encodeBase64(crash);
- ContentValues values = new ContentValues();
- values.put(Crashes.DATA, new String(encoded));
- Uri uri = resolver.insert(Crashes.CONTENT_URI, values);
- if (uri == null) {
- Log.e(TAG, "Error reporting crash");
- sLastCrashFailureRealtime = SystemClock.elapsedRealtime();
- }
- return uri;
- } catch (Throwable t) {
- // To avoid an infinite crash-reporting loop, swallow all errors and exceptions.
- Log.e(TAG, "Error reporting crash: " + t);
- sLastCrashFailureRealtime = SystemClock.elapsedRealtime();
- return null;
- }
- }
-
- /**
- * Report a crash in CrashData format.
- *
- * @param resolver from {@link android.content.Context#getContentResolver}
- * @param crash data to report
- * @return URI of the crash report that was added
- */
- static public Uri reportCrash(ContentResolver resolver, CrashData crash) {
- try {
- ByteArrayOutputStream data = new ByteArrayOutputStream();
- crash.write(new DataOutputStream(data));
- return reportCrash(resolver, data.toByteArray());
- } catch (Throwable t) {
- // Swallow all errors and exceptions when writing crash report
- Log.e(TAG, "Error writing crash: " + t);
- return null;
- }
- }
}
diff --git a/core/java/android/server/data/BuildData.java b/core/java/android/server/data/BuildData.java
deleted file mode 100644
index 53ffa3f..0000000
--- a/core/java/android/server/data/BuildData.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2007 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 android.server.data;
-
-import android.os.Build;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Build data transfer object. Keep in sync. with the server side version.
- */
-public class BuildData {
-
- /** The version of the data returned by write() and understood by the constructor. */
- private static final int VERSION = 0;
-
- private final String fingerprint;
- private final String incrementalVersion;
- private final long time; // in *seconds* since the epoch (not msec!)
-
- public BuildData() {
- this.fingerprint = "android:" + Build.FINGERPRINT;
- this.incrementalVersion = Build.VERSION.INCREMENTAL;
- this.time = Build.TIME / 1000; // msec -> sec
- }
-
- public BuildData(String fingerprint, String incrementalVersion, long time) {
- this.fingerprint = nonNull(fingerprint);
- this.incrementalVersion = incrementalVersion;
- this.time = time;
- }
-
- /*package*/ BuildData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != VERSION) {
- throw new IOException("Expected " + VERSION + ". Got: " + dataVersion);
- }
-
- this.fingerprint = in.readUTF();
- this.incrementalVersion = Long.toString(in.readLong());
- this.time = in.readLong();
- }
-
- /*package*/ void write(DataOutput out) throws IOException {
- out.writeInt(VERSION);
- out.writeUTF(fingerprint);
-
- // TODO: change the format/version to expect a string for this field.
- // Version 0, still used by the server side, expects a long.
- long changelist;
- try {
- changelist = Long.parseLong(incrementalVersion);
- } catch (NumberFormatException ex) {
- changelist = -1;
- }
- out.writeLong(changelist);
- out.writeLong(time);
- }
-
- public String getFingerprint() {
- return fingerprint;
- }
-
- public String getIncrementalVersion() {
- return incrementalVersion;
- }
-
- public long getTime() {
- return time;
- }
-}
diff --git a/core/java/android/server/data/CrashData.java b/core/java/android/server/data/CrashData.java
deleted file mode 100644
index d652bb3..0000000
--- a/core/java/android/server/data/CrashData.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-import static com.android.internal.util.Objects.nonNull;
-
-/**
- * Crash data transfer object. Keep in sync. with the server side version.
- */
-public class CrashData {
-
- final String id;
- final String activity;
- final long time;
- final BuildData buildData;
- final ThrowableData throwableData;
- final byte[] state;
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = null;
- }
-
- public CrashData(String id, String activity, BuildData buildData,
- ThrowableData throwableData, byte[] state) {
- this.id = nonNull(id);
- this.activity = nonNull(activity);
- this.buildData = nonNull(buildData);
- this.throwableData = nonNull(throwableData);
- this.time = System.currentTimeMillis();
- this.state = state;
- }
-
- public CrashData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0 && dataVersion != 1) {
- throw new IOException("Expected 0 or 1. Got: " + dataVersion);
- }
-
- this.id = in.readUTF();
- this.activity = in.readUTF();
- this.time = in.readLong();
- this.buildData = new BuildData(in);
- this.throwableData = new ThrowableData(in);
- if (dataVersion == 1) {
- int len = in.readInt();
- if (len == 0) {
- this.state = null;
- } else {
- this.state = new byte[len];
- in.readFully(this.state, 0, len);
- }
- } else {
- this.state = null;
- }
- }
-
- public CrashData(String tag, Throwable throwable) {
- id = "";
- activity = tag;
- buildData = new BuildData();
- throwableData = new ThrowableData(throwable);
- time = System.currentTimeMillis();
- state = null;
- }
-
- public void write(DataOutput out) throws IOException {
- // version
- if (this.state == null) {
- out.writeInt(0);
- } else {
- out.writeInt(1);
- }
-
- out.writeUTF(this.id);
- out.writeUTF(this.activity);
- out.writeLong(this.time);
- buildData.write(out);
- throwableData.write(out);
- if (this.state != null) {
- out.writeInt(this.state.length);
- out.write(this.state, 0, this.state.length);
- }
- }
-
- public BuildData getBuildData() {
- return buildData;
- }
-
- public ThrowableData getThrowableData() {
- return throwableData;
- }
-
- public String getId() {
- return id;
- }
-
- public String getActivity() {
- return activity;
- }
-
- public long getTime() {
- return time;
- }
-
- public byte[] getState() {
- return state;
- }
-
- /**
- * Return a brief description of this CrashData record. The details of the
- * representation are subject to change.
- *
- * @return Returns a String representing the contents of the object.
- */
- @Override
- public String toString() {
- return "[CrashData: id=" + id + " activity=" + activity + " time=" + time +
- " buildData=" + buildData.toString() +
- " throwableData=" + throwableData.toString() + "]";
- }
-}
diff --git a/core/java/android/server/data/StackTraceElementData.java b/core/java/android/server/data/StackTraceElementData.java
deleted file mode 100644
index 07185a0..0000000
--- a/core/java/android/server/data/StackTraceElementData.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Stack trace element data transfer object. Keep in sync. with the server side
- * version.
- */
-public class StackTraceElementData {
-
- final String className;
- final String fileName;
- final String methodName;
- final int lineNumber;
-
- public StackTraceElementData(StackTraceElement element) {
- this.className = element.getClassName();
-
- String fileName = element.getFileName();
- this.fileName = fileName == null ? "[unknown source]" : fileName;
-
- this.methodName = element.getMethodName();
- this.lineNumber = element.getLineNumber();
- }
-
- public StackTraceElementData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.className = in.readUTF();
- this.fileName = in.readUTF();
- this.methodName = in.readUTF();
- this.lineNumber = in.readInt();
- }
-
- void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(className);
- out.writeUTF(fileName);
- out.writeUTF(methodName);
- out.writeInt(lineNumber);
- }
-
- public String getClassName() {
- return className;
- }
-
- public String getFileName() {
- return fileName;
- }
-
- public String getMethodName() {
- return methodName;
- }
-
- public int getLineNumber() {
- return lineNumber;
- }
-}
diff --git a/core/java/android/server/data/ThrowableData.java b/core/java/android/server/data/ThrowableData.java
deleted file mode 100644
index e500aca..0000000
--- a/core/java/android/server/data/ThrowableData.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2006 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 android.server.data;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * Throwable data transfer object. Keep in sync. with the server side version.
- */
-public class ThrowableData {
-
- final String message;
- final String type;
- final StackTraceElementData[] stackTrace;
- final ThrowableData cause;
-
- public ThrowableData(Throwable throwable) {
- this.type = throwable.getClass().getName();
- String message = throwable.getMessage();
- this.message = message == null ? "" : message;
-
- StackTraceElement[] elements = throwable.getStackTrace();
- this.stackTrace = new StackTraceElementData[elements.length];
- for (int i = 0; i < elements.length; i++) {
- this.stackTrace[i] = new StackTraceElementData(elements[i]);
- }
-
- Throwable cause = throwable.getCause();
- this.cause = cause == null ? null : new ThrowableData(cause);
- }
-
- public ThrowableData(DataInput in) throws IOException {
- int dataVersion = in.readInt();
- if (dataVersion != 0) {
- throw new IOException("Expected 0. Got: " + dataVersion);
- }
-
- this.message = in.readUTF();
- this.type = in.readUTF();
-
- int count = in.readInt();
- this.stackTrace = new StackTraceElementData[count];
- for (int i = 0; i < count; i++) {
- this.stackTrace[i] = new StackTraceElementData(in);
- }
-
- this.cause = in.readBoolean() ? new ThrowableData(in) : null;
- }
-
- public void write(DataOutput out) throws IOException {
- out.writeInt(0); // version
-
- out.writeUTF(message);
- out.writeUTF(type);
-
- out.writeInt(stackTrace.length);
- for (StackTraceElementData elementData : stackTrace) {
- elementData.write(out);
- }
-
- out.writeBoolean(cause != null);
- if (cause != null) {
- cause.write(out);
- }
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getType() {
- return type;
- }
-
- public StackTraceElementData[] getStackTrace() {
- return stackTrace;
- }
-
- public ThrowableData getCause() {
- return cause;
- }
-
-
- public String toString() {
- return toString(null);
- }
-
- public String toString(String prefix) {
- StringBuilder builder = new StringBuilder();
- append(prefix, builder, this);
- return builder.toString();
- }
-
- private static void append(String prefix, StringBuilder builder,
- ThrowableData throwableData) {
- if (prefix != null) builder.append(prefix);
- builder.append(throwableData.getType())
- .append(": ")
- .append(throwableData.getMessage())
- .append('\n');
- for (StackTraceElementData element : throwableData.getStackTrace()) {
- if (prefix != null ) builder.append(prefix);
- builder.append(" at ")
- .append(element.getClassName())
- .append('.')
- .append(element.getMethodName())
- .append("(")
- .append(element.getFileName())
- .append(':')
- .append(element.getLineNumber())
- .append(")\n");
-
- }
-
- ThrowableData cause = throwableData.getCause();
- if (cause != null) {
- if (prefix != null ) builder.append(prefix);
- builder.append("Caused by: ");
- append(prefix, builder, cause);
- }
- }
-}
diff --git a/core/java/android/server/data/package.html b/core/java/android/server/data/package.html
deleted file mode 100755
index 1c9bf9d..0000000
--- a/core/java/android/server/data/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body>
- {@hide}
-</body>
-</html>
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 2572679..e95d0be 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -216,9 +216,7 @@ public final class Log {
* @param tr An exception to log
*/
public static int e(String tag, String msg, Throwable tr) {
- int r = println(ERROR, tag, msg + '\n' + getStackTraceString(tr));
- RuntimeInit.reportException(tag, tr, false); // asynchronous
- return r;
+ return println(ERROR, tag, msg + '\n' + getStackTraceString(tr));
}
/**
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index c782c8c..b7bb72d 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -17,7 +17,9 @@
package com.android.internal.os;
import android.app.ActivityManagerNative;
+import android.app.ApplicationErrorReport;
import android.app.IActivityManager;
+import android.os.Build;
import android.os.Debug;
import android.os.IBinder;
import android.os.ICheckinService;
@@ -25,8 +27,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
-import android.os.Build;
-import android.server.data.CrashData;
import android.util.Config;
import android.util.Log;
@@ -309,51 +309,18 @@ public class RuntimeInit {
*/
public static void crash(String tag, Throwable t) {
if (mApplicationObject != null) {
- byte[] crashData = null;
try {
// Log exception.
Log.e(TAG, Log.getStackTraceString(t));
- crashData = marshallException(tag, t);
- if (crashData == null) {
- throw new NullPointerException("Can't marshall crash data");
- }
- } catch (Throwable t2) {
- try {
- // Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Error reporting crash: "
- + Log.getStackTraceString(t2));
- } catch (Throwable t3) {
- // Do nothing, must be OOM so we can't format the message
- }
- }
-
- try {
- // Display user-visible error message.
- String msg = t.getMessage();
- if (msg == null) {
- msg = t.toString();
- }
+ // Show a message to the user.
IActivityManager am = ActivityManagerNative.getDefault();
- try {
- int res = am.handleApplicationError(mApplicationObject,
- 0, tag, msg, t.toString(), crashData);
- // Is waiting for the debugger the right thing?
- // For now I have turned off the Debug button, because
- // I'm not sure what we should do if it is actually
- // selected.
- //Log.i(TAG, "Got app error result: " + res);
- if (res == 1) {
- Debug.waitForDebugger();
- return;
- }
- } catch (RemoteException e) {
- }
+ am.handleApplicationError(mApplicationObject, tag,
+ new ApplicationErrorReport.CrashInfo(t));
} catch (Throwable t2) {
try {
// Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Error reporting crash: "
- + Log.getStackTraceString(t2));
+ Log.e(TAG, "Error reporting crash: " + Log.getStackTraceString(t2));
} catch (Throwable t3) {
// Do nothing, must be OOM so we can't format the message
}
@@ -366,7 +333,6 @@ public class RuntimeInit {
try {
Log.e(TAG, "*** EXCEPTION IN SYSTEM PROCESS. System will crash.");
Log.e(tag, Log.getStackTraceString(t));
- reportException(tag, t, true); // synchronous
} catch (Throwable t2) {
// Do nothing, must be OOM so we can't format the message
} finally {
@@ -381,82 +347,6 @@ public class RuntimeInit {
private static final AtomicInteger sInReportException = new AtomicInteger();
/**
- * Report an error in the current process. The exception information will
- * be handed off to the checkin service and eventually uploaded for analysis.
- * This is expensive! Only use this when the exception indicates a programming
- * error ("should not happen").
- *
- * @param tag to use when logging the error
- * @param t exception that was generated by the error
- * @param sync true to wait for the report, false to "fire and forget"
- */
- public static void reportException(String tag, Throwable t, boolean sync) {
- if (!initialized) {
- // Exceptions during, eg, zygote cannot use this mechanism
- return;
- }
-
- // It's important to prevent an infinite crash-reporting loop:
- // while this function is running, don't let it be called again.
- int reenter = sInReportException.getAndIncrement();
- if (reenter != 0) {
- sInReportException.decrementAndGet();
- Log.e(TAG, "Crash logging skipped, already logging another crash");
- return;
- }
-
- // TODO: Enable callers to specify a level (i.e. warn or error).
- try {
- // Submit crash data to statistics service.
- byte[] crashData = marshallException(tag, t);
- ICheckinService checkin = ICheckinService.Stub.asInterface(
- ServiceManager.getService("checkin"));
- if (checkin == null) {
- Log.e(TAG, "Crash logging skipped, no checkin service");
- } else if (sync) {
- checkin.reportCrashSync(crashData);
- } else {
- checkin.reportCrashAsync(crashData);
- }
- } catch (Throwable t2) {
- // Log exception as a string so we don't get in an infinite loop.
- Log.e(TAG, "Crash logging failed: " + t2);
- } finally {
- sInReportException.decrementAndGet();
- }
- }
-
- private static byte[] marshallException(String tag, Throwable t) {
- // Convert crash data to bytes.
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- DataOutputStream dout = new DataOutputStream(bout);
- try {
- new CrashData(tag, t).write(dout);
- dout.close();
- } catch (IOException e) {
- return null;
- }
- return bout.toByteArray();
- }
-
- /**
- * Replay an encoded CrashData record back into a useable CrashData record. This can be
- * helpful for providing debugging output after a process error.
- *
- * @param crashDataBytes The byte array containing the encoded crash record
- * @return new CrashData record, or null if could not create one.
- */
- public static CrashData unmarshallException(byte[] crashDataBytes) {
- try {
- ByteArrayInputStream bin = new ByteArrayInputStream(crashDataBytes);
- DataInputStream din = new DataInputStream(bin);
- return new CrashData(din);
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
* Set the object identifying this application/process, for reporting VM
* errors.
*/
@@ -473,5 +363,4 @@ public class RuntimeInit {
}
private static IBinder mApplicationObject;
-
}