1 /*
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 
17 package android.app.cts.android.app.cts.tools;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.SystemClock;
24 
25 import androidx.test.InstrumentationRegistry;
26 
27 import com.android.compatibility.common.util.SystemUtil;
28 
29 import java.io.IOException;
30 
31 /**
32  * Helper to wait for a broadcast to be sent.
33  */
34 public class WaitForBroadcast {
35     final Context mContext;
36 
37     String mWaitingAction;
38     boolean mHasResult;
39     Intent mReceivedIntent;
40 
41     final BroadcastReceiver mReceiver = new BroadcastReceiver() {
42         @Override public void onReceive(Context context, Intent intent) {
43             synchronized (WaitForBroadcast.this) {
44                 mReceivedIntent = intent;
45                 mHasResult = true;
46                 WaitForBroadcast.this.notifyAll();
47             }
48         }
49     };
50 
WaitForBroadcast(Context context)51     public WaitForBroadcast(Context context) {
52         mContext = context;
53     }
54 
prepare(String action)55     public void prepare(String action) {
56         if (mWaitingAction != null) {
57             throw new IllegalStateException("Already prepared");
58         }
59         mWaitingAction = action;
60         IntentFilter filter = new IntentFilter();
61         filter.addAction(action);
62         mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);
63     }
64 
doWait(long timeout)65     public Intent doWait(long timeout) {
66         try {
67             SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
68                     "am wait-for-broadcast-barrier");
69         } catch (IOException e) {
70             throw new IllegalStateException(e);
71         }
72 
73         final long endTime = SystemClock.uptimeMillis() + timeout;
74         synchronized (this) {
75             while (!mHasResult) {
76                 final long now = SystemClock.uptimeMillis();
77                 if (now >= endTime) {
78                     String action = mWaitingAction;
79                     cleanup();
80                     throw new IllegalStateException("Timed out waiting for broadcast " + action);
81                 }
82                 try {
83                     wait(endTime - now);
84                 } catch (InterruptedException e) {
85                 }
86             }
87             cleanup();
88             return mReceivedIntent;
89         }
90     }
91 
cleanup()92     void cleanup() {
93         if (mWaitingAction != null) {
94             mContext.unregisterReceiver(mReceiver);
95             mWaitingAction = null;
96         }
97     }
98 }
99