1 /* 2 * Copyright (C) 2015 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 17 package android.support.v4.os; 18 19 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 20 21 import android.os.Bundle; 22 import android.os.Handler; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.os.RemoteException; 26 import android.support.annotation.RestrictTo; 27 28 /** 29 * Generic interface for receiving a callback result from someone. Use this 30 * by creating a subclass and implement {@link #onReceiveResult}, which you can 31 * then pass to others and send through IPC, and receive results they 32 * supply with {@link #send}. 33 * 34 * <p>Note: the implementation underneath is just a simple wrapper around 35 * a {@link Binder} that is used to perform the communication. This means 36 * semantically you should treat it as such: this class does not impact process 37 * lifecycle management (you must be using some higher-level component to tell 38 * the system that your process needs to continue running), the connection will 39 * break if your process goes away for any reason, etc.</p> 40 * @hide 41 */ 42 @RestrictTo(LIBRARY_GROUP) 43 public class ResultReceiver implements Parcelable { 44 final boolean mLocal; 45 final Handler mHandler; 46 47 IResultReceiver mReceiver; 48 49 class MyRunnable implements Runnable { 50 final int mResultCode; 51 final Bundle mResultData; 52 53 MyRunnable(int resultCode, Bundle resultData) { 54 mResultCode = resultCode; 55 mResultData = resultData; 56 } 57 58 @Override 59 public void run() { 60 onReceiveResult(mResultCode, mResultData); 61 } 62 } 63 64 class MyResultReceiver extends IResultReceiver.Stub { 65 @Override 66 public void send(int resultCode, Bundle resultData) { 67 if (mHandler != null) { 68 mHandler.post(new MyRunnable(resultCode, resultData)); 69 } else { 70 onReceiveResult(resultCode, resultData); 71 } 72 } 73 } 74 75 /** 76 * Create a new ResultReceive to receive results. Your 77 * {@link #onReceiveResult} method will be called from the thread running 78 * <var>handler</var> if given, or from an arbitrary thread if null. 79 */ 80 public ResultReceiver(Handler handler) { 81 mLocal = true; 82 mHandler = handler; 83 } 84 85 /** 86 * Deliver a result to this receiver. Will call {@link #onReceiveResult}, 87 * always asynchronously if the receiver has supplied a Handler in which 88 * to dispatch the result. 89 * @param resultCode Arbitrary result code to deliver, as defined by you. 90 * @param resultData Any additional data provided by you. 91 */ 92 public void send(int resultCode, Bundle resultData) { 93 if (mLocal) { 94 if (mHandler != null) { 95 mHandler.post(new MyRunnable(resultCode, resultData)); 96 } else { 97 onReceiveResult(resultCode, resultData); 98 } 99 return; 100 } 101 102 if (mReceiver != null) { 103 try { 104 mReceiver.send(resultCode, resultData); 105 } catch (RemoteException e) { 106 } 107 } 108 } 109 110 /** 111 * Override to receive results delivered to this object. 112 * 113 * @param resultCode Arbitrary result code delivered by the sender, as 114 * defined by the sender. 115 * @param resultData Any additional data provided by the sender. 116 */ 117 protected void onReceiveResult(int resultCode, Bundle resultData) { 118 } 119 120 @Override 121 public int describeContents() { 122 return 0; 123 } 124 125 @Override 126 public void writeToParcel(Parcel out, int flags) { 127 synchronized (this) { 128 if (mReceiver == null) { 129 mReceiver = new MyResultReceiver(); 130 } 131 out.writeStrongBinder(mReceiver.asBinder()); 132 } 133 } 134 135 ResultReceiver(Parcel in) { 136 mLocal = false; 137 mHandler = null; 138 mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder()); 139 } 140 141 public static final Creator<ResultReceiver> CREATOR 142 = new Creator<ResultReceiver>() { 143 @Override 144 public ResultReceiver createFromParcel(Parcel in) { 145 return new ResultReceiver(in); 146 } 147 @Override 148 public ResultReceiver[] newArray(int size) { 149 return new ResultReceiver[size]; 150 } 151 }; 152 } 153