blob: 7f71905d7f280954cb90d2b51dc4c595669a66c0 [file] [log] [blame]
Jeff Sharkeye628b7d2017-01-17 13:50:20 -07001/*
2 * Copyright (C) 2017 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.os;
18
19import java.io.IOException;
20
21/**
22 * Wrapper class that offers to transport typical {@link Throwable} across a
23 * {@link Binder} call. This class is typically used to transport exceptions
24 * that cannot be modified to add {@link Parcelable} behavior, such as
25 * {@link IOException}.
26 * <ul>
27 * <li>The wrapped throwable must be defined as system class (that is, it must
28 * be in the same {@link ClassLoader} as {@link Parcelable}).
29 * <li>The wrapped throwable must support the
30 * {@link Throwable#Throwable(String)} constructor.
31 * <li>The receiver side must catch any thrown {@link ParcelableException} and
32 * call {@link #maybeRethrow(Class)} for all expected exception types.
33 * </ul>
34 *
35 * @hide
36 */
37public final class ParcelableException extends RuntimeException implements Parcelable {
38 public ParcelableException(Throwable t) {
39 super(t);
40 }
41
42 @SuppressWarnings("unchecked")
43 public <T extends Throwable> void maybeRethrow(Class<T> clazz) throws T {
44 if (clazz.isAssignableFrom(getCause().getClass())) {
45 throw (T) getCause();
46 }
47 }
48
49 /** {@hide} */
50 public static Throwable readFromParcel(Parcel in) {
51 final String name = in.readString();
52 final String msg = in.readString();
53 try {
54 final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader());
Jeff Sharkey020ed6a2017-09-20 16:09:16 -060055 if (Throwable.class.isAssignableFrom(clazz)) {
56 return (Throwable) clazz.getConstructor(String.class).newInstance(msg);
57 }
Jeff Sharkeye628b7d2017-01-17 13:50:20 -070058 } catch (ReflectiveOperationException e) {
Jeff Sharkeye628b7d2017-01-17 13:50:20 -070059 }
Jeff Sharkey020ed6a2017-09-20 16:09:16 -060060 return new RuntimeException(name + ": " + msg);
Jeff Sharkeye628b7d2017-01-17 13:50:20 -070061 }
62
63 /** {@hide} */
64 public static void writeToParcel(Parcel out, Throwable t) {
65 out.writeString(t.getClass().getName());
66 out.writeString(t.getMessage());
67 }
68
69 @Override
70 public int describeContents() {
71 return 0;
72 }
73
74 @Override
75 public void writeToParcel(Parcel dest, int flags) {
76 writeToParcel(dest, getCause());
77 }
78
79 public static final Creator<ParcelableException> CREATOR = new Creator<ParcelableException>() {
80 @Override
81 public ParcelableException createFromParcel(Parcel source) {
82 return new ParcelableException(readFromParcel(source));
83 }
84
85 @Override
86 public ParcelableException[] newArray(int size) {
87 return new ParcelableException[size];
88 }
89 };
90}