• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.android.managedprovisioning.common;
17 
18 import android.content.BroadcastReceiver;
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import androidx.annotation.Nullable;
23 import android.util.Log;
24 
25 import java.util.concurrent.ArrayBlockingQueue;
26 import java.util.concurrent.BlockingQueue;
27 import java.util.concurrent.TimeUnit;
28 
29 /**
30  * A receiver that allows caller to wait for the broadcast synchronously. Notice that you should not
31  * reuse the instance. Usage is typically like this:
32  * <pre>
33  *     BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(context, "action");
34  *     try {
35  *         receiver.register();
36  *         Intent intent = receiver.awaitForBroadcast();
37  *         // assert the intent
38  *     } finally {
39  *         receiver.unregisterQuietly();
40  *     }
41  * </pre>
42  */
43 public class BlockingBroadcastReceiver extends BroadcastReceiver {
44     private static final String TAG = "BlockingBroadcast";
45 
46     private static final int DEFAULT_TIMEOUT_SECONDS = 10;
47 
48     private final BlockingQueue<Intent> mBlockingQueue;
49     private final String mExpectedAction;
50     private final Context mContext;
51 
BlockingBroadcastReceiver(Context context, String expectedAction)52     public BlockingBroadcastReceiver(Context context, String expectedAction) {
53         mContext = context;
54         mExpectedAction = expectedAction;
55         mBlockingQueue = new ArrayBlockingQueue<>(1);
56     }
57 
58     @Override
onReceive(Context context, Intent intent)59     public void onReceive(Context context, Intent intent) {
60         if (mExpectedAction.equals(intent.getAction())) {
61             mBlockingQueue.add(intent);
62         }
63     }
64 
register()65     public void register() {
66         mContext.registerReceiver(this, new IntentFilter(mExpectedAction));
67     }
68 
69     /**
70      * Wait until the broadcast and return the received broadcast intent. {@code null} is returned
71      * if no broadcast with expected action is received within 10 seconds.
72      */
awaitForBroadcast()73     public @Nullable Intent awaitForBroadcast() {
74         try {
75             return mBlockingQueue.poll(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
76         } catch (InterruptedException e) {
77             Log.e(TAG, "waitForBroadcast get interrupted: ", e);
78         }
79         return null;
80     }
81 
82     /**
83      * Wait until the broadcast and return the received broadcast intent. {@code null} is returned
84      * if no broadcast with expected action is received within the given timeout.
85      */
awaitForBroadcast(long timeoutMillis)86     public @Nullable Intent awaitForBroadcast(long timeoutMillis) {
87         try {
88             return mBlockingQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS);
89         } catch (InterruptedException e) {
90             Log.e(TAG, "waitForBroadcast get interrupted: ", e);
91         }
92         return null;
93     }
94 
unregisterQuietly()95     public void unregisterQuietly() {
96         try {
97             mContext.unregisterReceiver(this);
98         } catch (Exception ex) {
99             Log.e(TAG, "Failed to unregister BlockingBroadcastReceiver: ", ex);
100         }
101     }
102 }
103