• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package android.os;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 
21 import java.util.concurrent.CompletableFuture;
22 import java.util.concurrent.ExecutionException;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.TimeoutException;
25 
26 /**
27  * Extends ResultReceiver to allow the server end of the ResultReceiver to synchronously wait
28  * on the response from the client. This enables an RPC like system but with the ability to
29  * timeout and discard late results.
30  *
31  * NOTE: Can only be used for one response. Subsequent responses on the same instance are ignored.
32  * {@hide}
33  */
34 public class SynchronousResultReceiver extends ResultReceiver {
35     public static class Result {
36         public int resultCode;
37         @Nullable public Bundle bundle;
38 
Result(int resultCode, @Nullable Bundle bundle)39         public Result(int resultCode, @Nullable Bundle bundle) {
40             this.resultCode = resultCode;
41             this.bundle = bundle;
42         }
43     }
44 
45     private final CompletableFuture<Result> mFuture = new CompletableFuture<>();
46     private final String mName;
47 
SynchronousResultReceiver()48     public SynchronousResultReceiver() {
49         super((Handler) null);
50         mName = null;
51     }
52 
53     /**
54      * @param name Name for logging purposes
55      */
SynchronousResultReceiver(String name)56     public SynchronousResultReceiver(String name) {
57         super((Handler) null);
58         mName = name;
59     }
60 
61     @Override
onReceiveResult(int resultCode, Bundle resultData)62     final protected void onReceiveResult(int resultCode, Bundle resultData) {
63         super.onReceiveResult(resultCode, resultData);
64         mFuture.complete(new Result(resultCode, resultData));
65     }
66 
getName()67     public String getName() {
68         return mName;
69     }
70 
71     /**
72      * Blocks waiting for the result from the remote client.
73      *
74      * @return the Result
75      * @throws TimeoutException if the timeout in milliseconds expired.
76      */
awaitResult(long timeoutMillis)77     public @NonNull Result awaitResult(long timeoutMillis) throws TimeoutException {
78         final long deadline = System.currentTimeMillis() + timeoutMillis;
79         while (timeoutMillis >= 0) {
80             try {
81                 return mFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
82             } catch (ExecutionException e) {
83                 // This will NEVER happen.
84                 throw new AssertionError("Error receiving response", e);
85             } catch (InterruptedException e) {
86                 // The thread was interrupted, try and get the value again, this time
87                 // with the remaining time until the deadline.
88                 timeoutMillis -= deadline - System.currentTimeMillis();
89             }
90         }
91         throw new TimeoutException();
92     }
93 
94 }
95