1 /*
2  * Copyright (C) 2019 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 com.android.cts.verifier.wifi;
18 
19 import android.net.ConnectivityManager;
20 import android.net.Network;
21 import android.net.NetworkCapabilities;
22 import android.util.Log;
23 import android.util.Pair;
24 
25 import java.util.concurrent.CountDownLatch;
26 import java.util.concurrent.TimeUnit;
27 
28 /**
29  * Blocking callbacks for Wi-Fi and Connectivity Manager.
30  */
31 public class CallbackUtils {
32     private static final boolean DBG = true;
33     private static final String TAG = "CallbackUtils";
34     public static final int DEFAULT_CALLBACK_TIMEOUT_MS = 15_000;
35 
36     /**
37      * Utility NetworkCallback- provides mechanism to block execution with the
38      * waitForAttach method.
39      */
40     public static class NetworkCallback extends ConnectivityManager.NetworkCallback {
41         private final int mCallbackTimeoutInMs;
42 
43         private CountDownLatch mOnAvailableBlocker = new CountDownLatch(1);
44         private CountDownLatch mOnUnAvailableBlocker = new CountDownLatch(1);
45         private CountDownLatch mOnLostBlocker = new CountDownLatch(1);
46         // This is invoked multiple times, so initialize only when waitForCapabilitiesChanged() is
47         // invoked.
48         private CountDownLatch mOnCapabilitiesChangedBlocker = null;
49         private Network mNetwork;
50         private NetworkCapabilities mNetworkCapabilities;
51 
NetworkCallback()52         public NetworkCallback() {
53             mCallbackTimeoutInMs = DEFAULT_CALLBACK_TIMEOUT_MS;
54         }
55 
NetworkCallback(int callbackTimeoutInMs)56         public NetworkCallback(int callbackTimeoutInMs) {
57             mCallbackTimeoutInMs = callbackTimeoutInMs;
58         }
59 
60         @Override
onAvailable(Network network)61         public void onAvailable(Network network) {
62             if (DBG) Log.v(TAG, "onAvailable");
63             mNetwork = network;
64             mOnAvailableBlocker.countDown();
65         }
66 
67         @Override
onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)68         public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
69             if (DBG) Log.v(TAG, "onCapabilitiesChanged");
70             mNetwork = network;
71             mNetworkCapabilities = networkCapabilities;
72             if (mOnCapabilitiesChangedBlocker != null) mOnCapabilitiesChangedBlocker.countDown();
73         }
74 
75         @Override
onUnavailable()76         public void onUnavailable() {
77             if (DBG) Log.v(TAG, "onUnavailable");
78             mOnUnAvailableBlocker.countDown();
79         }
80 
81         @Override
onLost(Network network)82         public void onLost(Network network) {
83             if (DBG) Log.v(TAG, "onLost");
84             mNetwork = network;
85             mOnLostBlocker.countDown();
86         }
87 
getNetwork()88         public Network getNetwork() {
89             return mNetwork;
90         }
91 
getNetworkCapabilities()92         public NetworkCapabilities getNetworkCapabilities() {
93             return mNetworkCapabilities;
94         }
95 
96         /**
97          * Wait (blocks) for {@link #onAvailable(Network)} or timeout.
98          *
99          * @return A pair of values: whether the callback was invoked and the Network object
100          * created when successful - null otherwise.
101          */
waitForAvailable()102         public Pair<Boolean, Network> waitForAvailable() throws InterruptedException {
103             if (mOnAvailableBlocker.await(mCallbackTimeoutInMs, TimeUnit.MILLISECONDS)) {
104                 return Pair.create(true, mNetwork);
105             }
106             return Pair.create(false, null);
107         }
108 
109         /**
110          * Wait (blocks) for {@link #onUnavailable()} or timeout.
111          *
112          * @return true whether the callback was invoked.
113          */
waitForUnavailable()114         public boolean waitForUnavailable() throws InterruptedException {
115             return mOnUnAvailableBlocker.await(mCallbackTimeoutInMs, TimeUnit.MILLISECONDS);
116         }
117 
118         /**
119          * Wait (blocks) for {@link #onLost(Network)} or timeout.
120          *
121          * @return true whether the callback was invoked.
122          */
waitForLost()123         public boolean waitForLost() throws InterruptedException {
124             return mOnLostBlocker.await(mCallbackTimeoutInMs, TimeUnit.MILLISECONDS);
125         }
126 
127         /**
128          * Wait (blocks) for {@link #onCapabilitiesChanged(Network, NetworkCapabilities)} or
129          * timeout.
130          *
131          * @return true whether the callback was invoked.
132          */
waitForCapabilitiesChanged()133         public boolean waitForCapabilitiesChanged() throws InterruptedException {
134             mOnCapabilitiesChangedBlocker = new CountDownLatch(1);
135             return mOnCapabilitiesChangedBlocker.await(mCallbackTimeoutInMs, TimeUnit.MILLISECONDS);
136         }
137     }
138 }
139