1 /*
2  * Copyright (C) 2020 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 package android.car.test.util;
17 
18 import android.annotation.Nullable;
19 import android.os.Bundle;
20 import android.util.Log;
21 
22 import com.android.internal.os.IResultReceiver;
23 import com.android.internal.util.Preconditions;
24 
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.TimeUnit;
27 
28 /**
29  * Implementation of {@link IResultReceiver} that blocks waiting for the result.
30  */
31 public final class BlockingResultReceiver extends IResultReceiver.Stub {
32 
33     private static final String TAG = BlockingResultReceiver.class.getSimpleName();
34 
35     private final CountDownLatch mLatch = new CountDownLatch(1);
36     private final long mTimeoutMs;
37 
38     private int mResultCode;
39     @Nullable private Bundle mResultData;
40 
41     /**
42      * Default constructor.
43      *
44      * @param timeoutMs how long to wait for before failing.
45      */
BlockingResultReceiver(long timeoutMs)46     public BlockingResultReceiver(long timeoutMs) {
47         mTimeoutMs = timeoutMs;
48     }
49 
50     @Override
send(int resultCode, Bundle resultData)51     public void send(int resultCode, Bundle resultData) {
52         Log.d(TAG, "send() received: code=" + resultCode + ", data=" + resultData + ", count="
53                 + mLatch.getCount());
54         Preconditions.checkState(mLatch.getCount() == 1,
55                 "send() already called (code=" + mResultCode + ", data=" + mResultData);
56         mResultCode = resultCode;
57         mResultData = resultData;
58         mLatch.countDown();
59     }
60 
assertCalled()61     private void assertCalled() throws InterruptedException {
62         boolean called = mLatch.await(mTimeoutMs, TimeUnit.MILLISECONDS);
63         Log.d(TAG, "assertCalled(): " + called);
64         Preconditions.checkState(called, "receiver not called in " + mTimeoutMs + " ms");
65     }
66 
67     /**
68      * Gets the {@code resultCode} or fails if it times out before {@code send()} is called.
69      */
getResultCode()70     public int getResultCode() throws InterruptedException {
71         assertCalled();
72         return mResultCode;
73     }
74 
75     /**
76      * Gets the {@code resultData} or fails if it times out before {@code send()} is called.
77      */
78     @Nullable
getResultData()79     public Bundle getResultData() throws InterruptedException {
80         assertCalled();
81         return mResultData;
82     }
83 }
84