Loading core/java/android/os/Parcel.java +30 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.util.SizeF; import android.util.SparseArray; import android.util.SparseBooleanArray; import libcore.util.SneakyThrow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; Loading Loading @@ -249,6 +251,7 @@ public final class Parcel { private static final int EX_NETWORK_MAIN_THREAD = -6; private static final int EX_UNSUPPORTED_OPERATION = -7; private static final int EX_SERVICE_SPECIFIC = -8; private static final int EX_PARCELABLE = -9; private static final int EX_HAS_REPLY_HEADER = -128; // special; see below // EX_TRANSACTION_FAILED is used exclusively in native code. // see libbinder's binder/Status.h Loading Loading @@ -1555,7 +1558,12 @@ public final class Parcel { */ public final void writeException(Exception e) { int code = 0; if (e instanceof SecurityException) { if (e instanceof Parcelable && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { // We only send Parcelable exceptions that are in the // BootClassLoader to ensure that the receiver can unpack them code = EX_PARCELABLE; } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; Loading @@ -1581,8 +1589,20 @@ public final class Parcel { throw new RuntimeException(e); } writeString(e.getMessage()); if (e instanceof ServiceSpecificException) { switch (code) { case EX_SERVICE_SPECIFIC: writeInt(((ServiceSpecificException) e).errorCode); break; case EX_PARCELABLE: // Write parceled exception prefixed by length final int sizePosition = dataPosition(); writeInt(0); writeParcelable((Parcelable) e, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); final int payloadPosition = dataPosition(); setDataPosition(sizePosition); writeInt(payloadPosition - sizePosition); setDataPosition(payloadPosition); break; } } Loading Loading @@ -1680,6 +1700,13 @@ public final class Parcel { */ public final void readException(int code, String msg) { switch (code) { case EX_PARCELABLE: if (readInt() > 0) { SneakyThrow.sneakyThrow( (Exception) readParcelable(Parcelable.class.getClassLoader())); } else { throw new RuntimeException(msg + " [missing Parcelable]"); } case EX_SECURITY: throw new SecurityException(msg); case EX_BAD_PARCELABLE: Loading core/java/android/os/ParcelableException.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.os; import java.io.IOException; /** * Wrapper class that offers to transport typical {@link Throwable} across a * {@link Binder} call. This class is typically used to transport exceptions * that cannot be modified to add {@link Parcelable} behavior, such as * {@link IOException}. * <ul> * <li>The wrapped throwable must be defined as system class (that is, it must * be in the same {@link ClassLoader} as {@link Parcelable}). * <li>The wrapped throwable must support the * {@link Throwable#Throwable(String)} constructor. * <li>The receiver side must catch any thrown {@link ParcelableException} and * call {@link #maybeRethrow(Class)} for all expected exception types. * </ul> * * @hide */ public final class ParcelableException extends RuntimeException implements Parcelable { public ParcelableException(Throwable t) { super(t); } @SuppressWarnings("unchecked") public <T extends Throwable> void maybeRethrow(Class<T> clazz) throws T { if (clazz.isAssignableFrom(getCause().getClass())) { throw (T) getCause(); } } /** {@hide} */ public static Throwable readFromParcel(Parcel in) { final String name = in.readString(); final String msg = in.readString(); try { final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader()); return (Throwable) clazz.getConstructor(String.class).newInstance(msg); } catch (ReflectiveOperationException e) { throw new RuntimeException(name + ": " + msg); } } /** {@hide} */ public static void writeToParcel(Parcel out, Throwable t) { out.writeString(t.getClass().getName()); out.writeString(t.getMessage()); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcel(dest, getCause()); } public static final Creator<ParcelableException> CREATOR = new Creator<ParcelableException>() { @Override public ParcelableException createFromParcel(Parcel source) { return new ParcelableException(readFromParcel(source)); } @Override public ParcelableException[] newArray(int size) { return new ParcelableException[size]; } }; } core/java/android/util/ExceptionUtils.java +5 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.util; import android.os.ParcelableException; import java.io.IOException; /** Loading @@ -24,19 +26,13 @@ import java.io.IOException; * @hide */ public class ExceptionUtils { // TODO: longer term these should be replaced with first-class // Parcel.read/writeException() and AIDL support, but for now do this using // a nasty hack. private static final String PREFIX_IO = "\u2603"; public static RuntimeException wrap(IOException e) { throw new IllegalStateException(PREFIX_IO + e.getMessage()); throw new ParcelableException(e); } public static void maybeUnwrapIOException(RuntimeException e) throws IOException { if ((e instanceof IllegalStateException) && e.getMessage().startsWith(PREFIX_IO)) { throw new IOException(e.getMessage().substring(PREFIX_IO.length())); if (e instanceof ParcelableException) { ((ParcelableException) e).maybeRethrow(IOException.class); } } Loading Loading
core/java/android/os/Parcel.java +30 −3 Original line number Diff line number Diff line Loading @@ -27,6 +27,8 @@ import android.util.SizeF; import android.util.SparseArray; import android.util.SparseBooleanArray; import libcore.util.SneakyThrow; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; Loading Loading @@ -249,6 +251,7 @@ public final class Parcel { private static final int EX_NETWORK_MAIN_THREAD = -6; private static final int EX_UNSUPPORTED_OPERATION = -7; private static final int EX_SERVICE_SPECIFIC = -8; private static final int EX_PARCELABLE = -9; private static final int EX_HAS_REPLY_HEADER = -128; // special; see below // EX_TRANSACTION_FAILED is used exclusively in native code. // see libbinder's binder/Status.h Loading Loading @@ -1555,7 +1558,12 @@ public final class Parcel { */ public final void writeException(Exception e) { int code = 0; if (e instanceof SecurityException) { if (e instanceof Parcelable && (e.getClass().getClassLoader() == Parcelable.class.getClassLoader())) { // We only send Parcelable exceptions that are in the // BootClassLoader to ensure that the receiver can unpack them code = EX_PARCELABLE; } else if (e instanceof SecurityException) { code = EX_SECURITY; } else if (e instanceof BadParcelableException) { code = EX_BAD_PARCELABLE; Loading @@ -1581,8 +1589,20 @@ public final class Parcel { throw new RuntimeException(e); } writeString(e.getMessage()); if (e instanceof ServiceSpecificException) { switch (code) { case EX_SERVICE_SPECIFIC: writeInt(((ServiceSpecificException) e).errorCode); break; case EX_PARCELABLE: // Write parceled exception prefixed by length final int sizePosition = dataPosition(); writeInt(0); writeParcelable((Parcelable) e, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); final int payloadPosition = dataPosition(); setDataPosition(sizePosition); writeInt(payloadPosition - sizePosition); setDataPosition(payloadPosition); break; } } Loading Loading @@ -1680,6 +1700,13 @@ public final class Parcel { */ public final void readException(int code, String msg) { switch (code) { case EX_PARCELABLE: if (readInt() > 0) { SneakyThrow.sneakyThrow( (Exception) readParcelable(Parcelable.class.getClassLoader())); } else { throw new RuntimeException(msg + " [missing Parcelable]"); } case EX_SECURITY: throw new SecurityException(msg); case EX_BAD_PARCELABLE: Loading
core/java/android/os/ParcelableException.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.os; import java.io.IOException; /** * Wrapper class that offers to transport typical {@link Throwable} across a * {@link Binder} call. This class is typically used to transport exceptions * that cannot be modified to add {@link Parcelable} behavior, such as * {@link IOException}. * <ul> * <li>The wrapped throwable must be defined as system class (that is, it must * be in the same {@link ClassLoader} as {@link Parcelable}). * <li>The wrapped throwable must support the * {@link Throwable#Throwable(String)} constructor. * <li>The receiver side must catch any thrown {@link ParcelableException} and * call {@link #maybeRethrow(Class)} for all expected exception types. * </ul> * * @hide */ public final class ParcelableException extends RuntimeException implements Parcelable { public ParcelableException(Throwable t) { super(t); } @SuppressWarnings("unchecked") public <T extends Throwable> void maybeRethrow(Class<T> clazz) throws T { if (clazz.isAssignableFrom(getCause().getClass())) { throw (T) getCause(); } } /** {@hide} */ public static Throwable readFromParcel(Parcel in) { final String name = in.readString(); final String msg = in.readString(); try { final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader()); return (Throwable) clazz.getConstructor(String.class).newInstance(msg); } catch (ReflectiveOperationException e) { throw new RuntimeException(name + ": " + msg); } } /** {@hide} */ public static void writeToParcel(Parcel out, Throwable t) { out.writeString(t.getClass().getName()); out.writeString(t.getMessage()); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { writeToParcel(dest, getCause()); } public static final Creator<ParcelableException> CREATOR = new Creator<ParcelableException>() { @Override public ParcelableException createFromParcel(Parcel source) { return new ParcelableException(readFromParcel(source)); } @Override public ParcelableException[] newArray(int size) { return new ParcelableException[size]; } }; }
core/java/android/util/ExceptionUtils.java +5 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.util; import android.os.ParcelableException; import java.io.IOException; /** Loading @@ -24,19 +26,13 @@ import java.io.IOException; * @hide */ public class ExceptionUtils { // TODO: longer term these should be replaced with first-class // Parcel.read/writeException() and AIDL support, but for now do this using // a nasty hack. private static final String PREFIX_IO = "\u2603"; public static RuntimeException wrap(IOException e) { throw new IllegalStateException(PREFIX_IO + e.getMessage()); throw new ParcelableException(e); } public static void maybeUnwrapIOException(RuntimeException e) throws IOException { if ((e instanceof IllegalStateException) && e.getMessage().startsWith(PREFIX_IO)) { throw new IOException(e.getMessage().substring(PREFIX_IO.length())); if (e instanceof ParcelableException) { ((ParcelableException) e).maybeRethrow(IOException.class); } } Loading