Loading apct-tests/perftests/core/src/android/os/ParcelPerfTest.java +80 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @RunWith(AndroidJUnit4.class) @LargeTest public class ParcelPerfTest { Loading Loading @@ -167,4 +171,80 @@ public class ParcelPerfTest { Parcel.obtain().recycle(); } } @Test public void timeWriteException() { timeWriteException(false); } @Test public void timeWriteExceptionWithStackTraceParceling() { timeWriteException(true); } @Test public void timeReadException() { timeReadException(false); } @Test public void timeReadExceptionWithStackTraceParceling() { timeReadException(true); } private void timeWriteException(boolean enableParceling) { if (enableParceling) { Parcel.setStackTraceParceling(true); } try { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); Parcel p = Parcel.obtain(); SecurityException e = new SecurityException("TestMessage"); while (state.keepRunning()) { p.setDataPosition(0); p.writeException(e); } } finally { if (enableParceling) { Parcel.setStackTraceParceling(false); } } } private void timeReadException(boolean enableParceling) { if (enableParceling) { Parcel.setStackTraceParceling(true); } try { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); Parcel p = Parcel.obtain(); String msg = "TestMessage"; p.writeException(new SecurityException(msg)); p.setDataPosition(0); // First verify that remote cause is set (if parceling is enabled) try { p.readException(); } catch (SecurityException e) { assertEquals(e.getMessage(), msg); if (enableParceling) { assertTrue(e.getCause() instanceof RemoteException); } else { assertNull(e.getCause()); } } while (state.keepRunning()) { p.setDataPosition(0); try { p.readException(); } catch (SecurityException expected) { } } } finally { if (enableParceling) { Parcel.setStackTraceParceling(false); } } } } core/java/android/os/Parcel.java +72 −13 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ import java.util.Set; * {@link #readSparseArray(ClassLoader)}. */ public final class Parcel { private static final boolean DEBUG_RECYCLE = false; private static final boolean DEBUG_ARRAY_MAP = false; private static final String TAG = "Parcel"; Loading @@ -209,6 +210,12 @@ public final class Parcel { private RuntimeException mStack; /** * Whether or not to parcel the stack trace of an exception. This has a performance * impact, so should only be included in specific processes and only on debug builds. */ private static boolean sParcelExceptionStackTrace; private static final int POOL_SIZE = 6; private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE]; private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE]; Loading Loading @@ -325,6 +332,11 @@ public final class Parcel { private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName); private static native void nativeEnforceInterface(long nativePtr, String interfaceName); /** Last time exception with a stack trace was written */ private static volatile long sLastWriteExceptionStackTrace; /** Used for throttling of writing stack trace, which is costly */ private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000; @CriticalNative private static native long nativeGetBlobAshmemSize(long nativePtr); Loading Loading @@ -1696,6 +1708,11 @@ public final class Parcel { } } /** @hide For debugging purposes */ public static void setStackTraceParceling(boolean enabled) { sParcelExceptionStackTrace = enabled; } /** * Special function for writing an exception result at the header of * a parcel, to be used when returning an exception from a transaction. Loading Loading @@ -1753,6 +1770,27 @@ public final class Parcel { throw new RuntimeException(e); } writeString(e.getMessage()); final long timeNow = sParcelExceptionStackTrace ? SystemClock.elapsedRealtime() : 0; if (sParcelExceptionStackTrace && (timeNow - sLastWriteExceptionStackTrace > WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS)) { sLastWriteExceptionStackTrace = timeNow; final int sizePosition = dataPosition(); writeInt(0); // Header size will be filled in later StackTraceElement[] stackTrace = e.getStackTrace(); final int truncatedSize = Math.min(stackTrace.length, 5); StringBuilder sb = new StringBuilder(); for (int i = 0; i < truncatedSize; i++) { sb.append("\tat ").append(stackTrace[i]); } writeString(sb.toString()); final int payloadPosition = dataPosition(); setDataPosition(sizePosition); // Write stack trace header size. Used in native side to skip the header writeInt(payloadPosition - sizePosition); setDataPosition(payloadPosition); } else { writeInt(0); } switch (code) { case EX_SERVICE_SPECIFIC: writeInt(((ServiceSpecificException) e).errorCode); Loading Loading @@ -1818,7 +1856,19 @@ public final class Parcel { int code = readExceptionCode(); if (code != 0) { String msg = readString(); readException(code, msg); String remoteStackTrace = null; final int remoteStackPayloadSize = readInt(); if (remoteStackPayloadSize > 0) { remoteStackTrace = readString(); } Exception e = createException(code, msg); // Attach remote stack trace if availalble if (remoteStackTrace != null) { RemoteException cause = new RemoteException( "Remote stack trace:\n" + remoteStackTrace, null, false, false); e.initCause(cause); } SneakyThrow.sneakyThrow(e); } } Loading Loading @@ -1863,32 +1913,41 @@ public final class Parcel { * @param msg The exception message. */ public final void readException(int code, String msg) { SneakyThrow.sneakyThrow(createException(code, msg)); } /** * Creates an exception with the given message. * * @param code Used to determine which exception class to throw. * @param msg The exception message. */ private Exception createException(int code, String msg) { switch (code) { case EX_PARCELABLE: if (readInt() > 0) { SneakyThrow.sneakyThrow( (Exception) readParcelable(Parcelable.class.getClassLoader())); return (Exception) readParcelable(Parcelable.class.getClassLoader()); } else { throw new RuntimeException(msg + " [missing Parcelable]"); return new RuntimeException(msg + " [missing Parcelable]"); } case EX_SECURITY: throw new SecurityException(msg); return new SecurityException(msg); case EX_BAD_PARCELABLE: throw new BadParcelableException(msg); return new BadParcelableException(msg); case EX_ILLEGAL_ARGUMENT: throw new IllegalArgumentException(msg); return new IllegalArgumentException(msg); case EX_NULL_POINTER: throw new NullPointerException(msg); return new NullPointerException(msg); case EX_ILLEGAL_STATE: throw new IllegalStateException(msg); return new IllegalStateException(msg); case EX_NETWORK_MAIN_THREAD: throw new NetworkOnMainThreadException(); return new NetworkOnMainThreadException(); case EX_UNSUPPORTED_OPERATION: throw new UnsupportedOperationException(msg); return new UnsupportedOperationException(msg); case EX_SERVICE_SPECIFIC: throw new ServiceSpecificException(readInt(), msg); return new ServiceSpecificException(readInt(), msg); } throw new RuntimeException("Unknown exception code: " + code return new RuntimeException("Unknown exception code: " + code + " msg " + msg); } Loading core/java/android/os/RemoteException.java +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,12 @@ public class RemoteException extends AndroidException { super(message); } /** @hide */ public RemoteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } /** {@hide} */ public RuntimeException rethrowAsRuntimeException() { throw new RuntimeException(this); Loading core/java/android/util/AndroidException.java +6 −0 Original line number Diff line number Diff line Loading @@ -34,5 +34,11 @@ public class AndroidException extends Exception { public AndroidException(Exception cause) { super(cause); } /** @hide */ protected AndroidException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }; services/java/com/android/server/SystemServer.java +4 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.FileUtils; import android.os.IIncidentManager; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.PowerManager; import android.os.Process; import android.os.ServiceManager; Loading Loading @@ -360,6 +361,9 @@ public final class SystemServer { // to avoid throwing BadParcelableException. BaseBundle.setShouldDefuse(true); // Within the system server, when parceling exceptions, include the stack trace Parcel.setStackTraceParceling(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); Loading Loading
apct-tests/perftests/core/src/android/os/ParcelPerfTest.java +80 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,10 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @RunWith(AndroidJUnit4.class) @LargeTest public class ParcelPerfTest { Loading Loading @@ -167,4 +171,80 @@ public class ParcelPerfTest { Parcel.obtain().recycle(); } } @Test public void timeWriteException() { timeWriteException(false); } @Test public void timeWriteExceptionWithStackTraceParceling() { timeWriteException(true); } @Test public void timeReadException() { timeReadException(false); } @Test public void timeReadExceptionWithStackTraceParceling() { timeReadException(true); } private void timeWriteException(boolean enableParceling) { if (enableParceling) { Parcel.setStackTraceParceling(true); } try { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); Parcel p = Parcel.obtain(); SecurityException e = new SecurityException("TestMessage"); while (state.keepRunning()) { p.setDataPosition(0); p.writeException(e); } } finally { if (enableParceling) { Parcel.setStackTraceParceling(false); } } } private void timeReadException(boolean enableParceling) { if (enableParceling) { Parcel.setStackTraceParceling(true); } try { final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); Parcel p = Parcel.obtain(); String msg = "TestMessage"; p.writeException(new SecurityException(msg)); p.setDataPosition(0); // First verify that remote cause is set (if parceling is enabled) try { p.readException(); } catch (SecurityException e) { assertEquals(e.getMessage(), msg); if (enableParceling) { assertTrue(e.getCause() instanceof RemoteException); } else { assertNull(e.getCause()); } } while (state.keepRunning()) { p.setDataPosition(0); try { p.readException(); } catch (SecurityException expected) { } } } finally { if (enableParceling) { Parcel.setStackTraceParceling(false); } } } }
core/java/android/os/Parcel.java +72 −13 Original line number Diff line number Diff line Loading @@ -191,6 +191,7 @@ import java.util.Set; * {@link #readSparseArray(ClassLoader)}. */ public final class Parcel { private static final boolean DEBUG_RECYCLE = false; private static final boolean DEBUG_ARRAY_MAP = false; private static final String TAG = "Parcel"; Loading @@ -209,6 +210,12 @@ public final class Parcel { private RuntimeException mStack; /** * Whether or not to parcel the stack trace of an exception. This has a performance * impact, so should only be included in specific processes and only on debug builds. */ private static boolean sParcelExceptionStackTrace; private static final int POOL_SIZE = 6; private static final Parcel[] sOwnedPool = new Parcel[POOL_SIZE]; private static final Parcel[] sHolderPool = new Parcel[POOL_SIZE]; Loading Loading @@ -325,6 +332,11 @@ public final class Parcel { private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName); private static native void nativeEnforceInterface(long nativePtr, String interfaceName); /** Last time exception with a stack trace was written */ private static volatile long sLastWriteExceptionStackTrace; /** Used for throttling of writing stack trace, which is costly */ private static final int WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS = 1000; @CriticalNative private static native long nativeGetBlobAshmemSize(long nativePtr); Loading Loading @@ -1696,6 +1708,11 @@ public final class Parcel { } } /** @hide For debugging purposes */ public static void setStackTraceParceling(boolean enabled) { sParcelExceptionStackTrace = enabled; } /** * Special function for writing an exception result at the header of * a parcel, to be used when returning an exception from a transaction. Loading Loading @@ -1753,6 +1770,27 @@ public final class Parcel { throw new RuntimeException(e); } writeString(e.getMessage()); final long timeNow = sParcelExceptionStackTrace ? SystemClock.elapsedRealtime() : 0; if (sParcelExceptionStackTrace && (timeNow - sLastWriteExceptionStackTrace > WRITE_EXCEPTION_STACK_TRACE_THRESHOLD_MS)) { sLastWriteExceptionStackTrace = timeNow; final int sizePosition = dataPosition(); writeInt(0); // Header size will be filled in later StackTraceElement[] stackTrace = e.getStackTrace(); final int truncatedSize = Math.min(stackTrace.length, 5); StringBuilder sb = new StringBuilder(); for (int i = 0; i < truncatedSize; i++) { sb.append("\tat ").append(stackTrace[i]); } writeString(sb.toString()); final int payloadPosition = dataPosition(); setDataPosition(sizePosition); // Write stack trace header size. Used in native side to skip the header writeInt(payloadPosition - sizePosition); setDataPosition(payloadPosition); } else { writeInt(0); } switch (code) { case EX_SERVICE_SPECIFIC: writeInt(((ServiceSpecificException) e).errorCode); Loading Loading @@ -1818,7 +1856,19 @@ public final class Parcel { int code = readExceptionCode(); if (code != 0) { String msg = readString(); readException(code, msg); String remoteStackTrace = null; final int remoteStackPayloadSize = readInt(); if (remoteStackPayloadSize > 0) { remoteStackTrace = readString(); } Exception e = createException(code, msg); // Attach remote stack trace if availalble if (remoteStackTrace != null) { RemoteException cause = new RemoteException( "Remote stack trace:\n" + remoteStackTrace, null, false, false); e.initCause(cause); } SneakyThrow.sneakyThrow(e); } } Loading Loading @@ -1863,32 +1913,41 @@ public final class Parcel { * @param msg The exception message. */ public final void readException(int code, String msg) { SneakyThrow.sneakyThrow(createException(code, msg)); } /** * Creates an exception with the given message. * * @param code Used to determine which exception class to throw. * @param msg The exception message. */ private Exception createException(int code, String msg) { switch (code) { case EX_PARCELABLE: if (readInt() > 0) { SneakyThrow.sneakyThrow( (Exception) readParcelable(Parcelable.class.getClassLoader())); return (Exception) readParcelable(Parcelable.class.getClassLoader()); } else { throw new RuntimeException(msg + " [missing Parcelable]"); return new RuntimeException(msg + " [missing Parcelable]"); } case EX_SECURITY: throw new SecurityException(msg); return new SecurityException(msg); case EX_BAD_PARCELABLE: throw new BadParcelableException(msg); return new BadParcelableException(msg); case EX_ILLEGAL_ARGUMENT: throw new IllegalArgumentException(msg); return new IllegalArgumentException(msg); case EX_NULL_POINTER: throw new NullPointerException(msg); return new NullPointerException(msg); case EX_ILLEGAL_STATE: throw new IllegalStateException(msg); return new IllegalStateException(msg); case EX_NETWORK_MAIN_THREAD: throw new NetworkOnMainThreadException(); return new NetworkOnMainThreadException(); case EX_UNSUPPORTED_OPERATION: throw new UnsupportedOperationException(msg); return new UnsupportedOperationException(msg); case EX_SERVICE_SPECIFIC: throw new ServiceSpecificException(readInt(), msg); return new ServiceSpecificException(readInt(), msg); } throw new RuntimeException("Unknown exception code: " + code return new RuntimeException("Unknown exception code: " + code + " msg " + msg); } Loading
core/java/android/os/RemoteException.java +6 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,12 @@ public class RemoteException extends AndroidException { super(message); } /** @hide */ public RemoteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } /** {@hide} */ public RuntimeException rethrowAsRuntimeException() { throw new RuntimeException(this); Loading
core/java/android/util/AndroidException.java +6 −0 Original line number Diff line number Diff line Loading @@ -34,5 +34,11 @@ public class AndroidException extends Exception { public AndroidException(Exception cause) { super(cause); } /** @hide */ protected AndroidException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } };
services/java/com/android/server/SystemServer.java +4 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.os.FileUtils; import android.os.IIncidentManager; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.PowerManager; import android.os.Process; import android.os.ServiceManager; Loading Loading @@ -360,6 +361,9 @@ public final class SystemServer { // to avoid throwing BadParcelableException. BaseBundle.setShouldDefuse(true); // Within the system server, when parceling exceptions, include the stack trace Parcel.setStackTraceParceling(true); // Ensure binder calls into the system always run at foreground priority. BinderInternal.disableBackgroundScheduling(true); Loading