xref: /aosp_15_r20/test/vts/vts_hal_hidl_target/VtsHalHidlTargetCallbackBase.h (revision 9a74111979c139a065a9a7e4d45972320c5732c7)
1*9a741119SAndroid Build Coastguard Worker /*
2*9a741119SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*9a741119SAndroid Build Coastguard Worker  *
4*9a741119SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*9a741119SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*9a741119SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*9a741119SAndroid Build Coastguard Worker  *
8*9a741119SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*9a741119SAndroid Build Coastguard Worker  *
10*9a741119SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*9a741119SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*9a741119SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9a741119SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*9a741119SAndroid Build Coastguard Worker  * limitations under the License.
15*9a741119SAndroid Build Coastguard Worker  */
16*9a741119SAndroid Build Coastguard Worker 
17*9a741119SAndroid Build Coastguard Worker #ifndef __VTS_HAL_HIDL_TARGET_CALLBACK_BASE_H
18*9a741119SAndroid Build Coastguard Worker #define __VTS_HAL_HIDL_TARGET_CALLBACK_BASE_H
19*9a741119SAndroid Build Coastguard Worker 
20*9a741119SAndroid Build Coastguard Worker #include <chrono>
21*9a741119SAndroid Build Coastguard Worker #include <condition_variable>
22*9a741119SAndroid Build Coastguard Worker #include <iostream>
23*9a741119SAndroid Build Coastguard Worker #include <mutex>
24*9a741119SAndroid Build Coastguard Worker #include <queue>
25*9a741119SAndroid Build Coastguard Worker #include <unordered_map>
26*9a741119SAndroid Build Coastguard Worker #include <utility>
27*9a741119SAndroid Build Coastguard Worker 
28*9a741119SAndroid Build Coastguard Worker using namespace ::std;
29*9a741119SAndroid Build Coastguard Worker using namespace ::std::chrono;
30*9a741119SAndroid Build Coastguard Worker 
31*9a741119SAndroid Build Coastguard Worker constexpr char kVtsHalHidlTargetCallbackDefaultName[] =
32*9a741119SAndroid Build Coastguard Worker     "VtsHalHidlTargetCallbackDefaultName";
33*9a741119SAndroid Build Coastguard Worker constexpr milliseconds DEFAULT_CALLBACK_WAIT_TIMEOUT_INITIAL = minutes(1);
34*9a741119SAndroid Build Coastguard Worker 
35*9a741119SAndroid Build Coastguard Worker namespace testing {
36*9a741119SAndroid Build Coastguard Worker 
37*9a741119SAndroid Build Coastguard Worker /*
38*9a741119SAndroid Build Coastguard Worker  * VTS target side test template for callback.
39*9a741119SAndroid Build Coastguard Worker  *
40*9a741119SAndroid Build Coastguard Worker  * Providing wait and notify for callback functionality.
41*9a741119SAndroid Build Coastguard Worker  *
42*9a741119SAndroid Build Coastguard Worker  * A typical usage looks like this:
43*9a741119SAndroid Build Coastguard Worker  *
44*9a741119SAndroid Build Coastguard Worker  * class CallbackArgs {
45*9a741119SAndroid Build Coastguard Worker  *   ArgType1 arg1;
46*9a741119SAndroid Build Coastguard Worker  *   ArgType2 arg2;
47*9a741119SAndroid Build Coastguard Worker  * }
48*9a741119SAndroid Build Coastguard Worker  *
49*9a741119SAndroid Build Coastguard Worker  * class MyCallback
50*9a741119SAndroid Build Coastguard Worker  *     : public ::testing::VtsHalHidlTargetCallbackBase<>,
51*9a741119SAndroid Build Coastguard Worker  *       public CallbackInterface {
52*9a741119SAndroid Build Coastguard Worker  *  public:
53*9a741119SAndroid Build Coastguard Worker  *   CallbackApi1(ArgType1 arg1) {
54*9a741119SAndroid Build Coastguard Worker  *     CallbackArgs data;
55*9a741119SAndroid Build Coastguard Worker  *     data.arg1 = arg1;
56*9a741119SAndroid Build Coastguard Worker  *     NotifyFromCallback("CallbackApi1", data);
57*9a741119SAndroid Build Coastguard Worker  *   }
58*9a741119SAndroid Build Coastguard Worker  *
59*9a741119SAndroid Build Coastguard Worker  *   CallbackApi2(ArgType2 arg2) {
60*9a741119SAndroid Build Coastguard Worker  *     CallbackArgs data;
61*9a741119SAndroid Build Coastguard Worker  *     data.arg1 = arg1;
62*9a741119SAndroid Build Coastguard Worker  *     NotifyFromCallback("CallbackApi2", data);
63*9a741119SAndroid Build Coastguard Worker  *   }
64*9a741119SAndroid Build Coastguard Worker  * }
65*9a741119SAndroid Build Coastguard Worker  *
66*9a741119SAndroid Build Coastguard Worker  * Test(MyTest) {
67*9a741119SAndroid Build Coastguard Worker  *   CallApi1();
68*9a741119SAndroid Build Coastguard Worker  *   CallApi2();
69*9a741119SAndroid Build Coastguard Worker  *   auto result = cb_.WaitForCallback("CallbackApi1");
70*9a741119SAndroid Build Coastguard Worker  *   // cb_ as an instance of MyCallback, result is an instance of
71*9a741119SAndroid Build Coastguard Worker  *   // ::testing::VtsHalHidlTargetCallbackBase::WaitForCallbackResult
72*9a741119SAndroid Build Coastguard Worker  *   EXPECT_TRUE(result.no_timeout); // Check wait did not time out
73*9a741119SAndroid Build Coastguard Worker  *   EXPECT_TRUE(result.args); // Check CallbackArgs is received (not
74*9a741119SAndroid Build Coastguard Worker  *                                  nullptr). This is optional.
75*9a741119SAndroid Build Coastguard Worker  *   // Here check value of args using the pointer result.args;
76*9a741119SAndroid Build Coastguard Worker  *   result = cb_.WaitForCallback("CallbackApi2");
77*9a741119SAndroid Build Coastguard Worker  *   EXPECT_TRUE(result.no_timeout);
78*9a741119SAndroid Build Coastguard Worker  *   // Here check value of args using the pointer result.args;
79*9a741119SAndroid Build Coastguard Worker  *
80*9a741119SAndroid Build Coastguard Worker  *   // Additionally. a test can wait for one of multiple callbacks.
81*9a741119SAndroid Build Coastguard Worker  *   // In this case, wait will return when any of the callbacks in the provided
82*9a741119SAndroid Build Coastguard Worker  *   // name list is called.
83*9a741119SAndroid Build Coastguard Worker  *   result = cb_.WaitForCallbackAny(<vector_of_string>)
84*9a741119SAndroid Build Coastguard Worker  *   // When vector_of_string is not provided, all callback functions will
85*9a741119SAndroid Build Coastguard Worker  *   // be monitored. The name of callback function that was invoked
86*9a741119SAndroid Build Coastguard Worker  *   // is stored in result.name
87*9a741119SAndroid Build Coastguard Worker  * }
88*9a741119SAndroid Build Coastguard Worker  *
89*9a741119SAndroid Build Coastguard Worker  * Note type of CallbackArgsTemplateClass is same across the class, which means
90*9a741119SAndroid Build Coastguard Worker  * all WaitForCallback method will return the same data type.
91*9a741119SAndroid Build Coastguard Worker  */
92*9a741119SAndroid Build Coastguard Worker template <class CallbackArgsTemplateClass>
93*9a741119SAndroid Build Coastguard Worker class VtsHalHidlTargetCallbackBase {
94*9a741119SAndroid Build Coastguard Worker  public:
95*9a741119SAndroid Build Coastguard Worker   struct WaitForCallbackResult {
WaitForCallbackResultWaitForCallbackResult96*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult()
97*9a741119SAndroid Build Coastguard Worker         : no_timeout(false),
98*9a741119SAndroid Build Coastguard Worker           args(shared_ptr<CallbackArgsTemplateClass>(nullptr)),
99*9a741119SAndroid Build Coastguard Worker           name("") {}
100*9a741119SAndroid Build Coastguard Worker 
101*9a741119SAndroid Build Coastguard Worker     // Whether the wait timed out
102*9a741119SAndroid Build Coastguard Worker     bool no_timeout;
103*9a741119SAndroid Build Coastguard Worker     // Arguments data from callback functions. Defaults to nullptr.
104*9a741119SAndroid Build Coastguard Worker     shared_ptr<CallbackArgsTemplateClass> args;
105*9a741119SAndroid Build Coastguard Worker     // Name of the callback. Defaults to empty string.
106*9a741119SAndroid Build Coastguard Worker     string name;
107*9a741119SAndroid Build Coastguard Worker   };
108*9a741119SAndroid Build Coastguard Worker 
VtsHalHidlTargetCallbackBase()109*9a741119SAndroid Build Coastguard Worker   VtsHalHidlTargetCallbackBase()
110*9a741119SAndroid Build Coastguard Worker       : cb_default_wait_timeout_(DEFAULT_CALLBACK_WAIT_TIMEOUT_INITIAL) {}
111*9a741119SAndroid Build Coastguard Worker 
~VtsHalHidlTargetCallbackBase()112*9a741119SAndroid Build Coastguard Worker   virtual ~VtsHalHidlTargetCallbackBase() {
113*9a741119SAndroid Build Coastguard Worker     for (auto it : cb_lock_map_) {
114*9a741119SAndroid Build Coastguard Worker       delete it.second;
115*9a741119SAndroid Build Coastguard Worker     }
116*9a741119SAndroid Build Coastguard Worker   }
117*9a741119SAndroid Build Coastguard Worker 
118*9a741119SAndroid Build Coastguard Worker   /*
119*9a741119SAndroid Build Coastguard Worker    * Wait for a callback function in a test.
120*9a741119SAndroid Build Coastguard Worker    * Returns a WaitForCallbackResult object containing wait results.
121*9a741119SAndroid Build Coastguard Worker    * If callback_function_name is not provided, a default name will be used.
122*9a741119SAndroid Build Coastguard Worker    * Timeout defaults to -1 milliseconds. Negative timeout means use to
123*9a741119SAndroid Build Coastguard Worker    * use the time out set for the callback or default callback wait time out.
124*9a741119SAndroid Build Coastguard Worker    */
125*9a741119SAndroid Build Coastguard Worker   WaitForCallbackResult WaitForCallback(
126*9a741119SAndroid Build Coastguard Worker       const string& callback_function_name =
127*9a741119SAndroid Build Coastguard Worker           kVtsHalHidlTargetCallbackDefaultName,
128*9a741119SAndroid Build Coastguard Worker       milliseconds timeout = milliseconds(-1)) {
129*9a741119SAndroid Build Coastguard Worker     return GetCallbackLock(callback_function_name)->WaitForCallback(timeout);
130*9a741119SAndroid Build Coastguard Worker   }
131*9a741119SAndroid Build Coastguard Worker 
132*9a741119SAndroid Build Coastguard Worker   /*
133*9a741119SAndroid Build Coastguard Worker    * Wait for any of the callback functions specified.
134*9a741119SAndroid Build Coastguard Worker    * Returns a WaitForCallbackResult object containing wait results.
135*9a741119SAndroid Build Coastguard Worker    * If callback_function_names is not provided, all callback functions will
136*9a741119SAndroid Build Coastguard Worker    * be monitored, and the list of callback functions will be updated
137*9a741119SAndroid Build Coastguard Worker    * dynamically during run time.
138*9a741119SAndroid Build Coastguard Worker    * If timeout_any is not provided, the shortest timeout from the function
139*9a741119SAndroid Build Coastguard Worker    * list will be used.
140*9a741119SAndroid Build Coastguard Worker    */
141*9a741119SAndroid Build Coastguard Worker   WaitForCallbackResult WaitForCallbackAny(
142*9a741119SAndroid Build Coastguard Worker       const vector<string>& callback_function_names = vector<string>(),
143*9a741119SAndroid Build Coastguard Worker       milliseconds timeout_any = milliseconds(-1)) {
144*9a741119SAndroid Build Coastguard Worker     unique_lock<mutex> lock(cb_wait_any_mtx_);
145*9a741119SAndroid Build Coastguard Worker 
146*9a741119SAndroid Build Coastguard Worker     auto start_time = steady_clock::now();
147*9a741119SAndroid Build Coastguard Worker 
148*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult res = PeekCallbackLocks(callback_function_names);
149*9a741119SAndroid Build Coastguard Worker     while (!res.no_timeout) {
150*9a741119SAndroid Build Coastguard Worker       auto expiration =
151*9a741119SAndroid Build Coastguard Worker           GetWaitAnyTimeout(callback_function_names, start_time, timeout_any);
152*9a741119SAndroid Build Coastguard Worker       auto status = cb_wait_any_cv_.wait_until(lock, expiration);
153*9a741119SAndroid Build Coastguard Worker       if (status == cv_status::timeout) {
154*9a741119SAndroid Build Coastguard Worker         cerr << "Timed out waiting for callback functions." << endl;
155*9a741119SAndroid Build Coastguard Worker         break;
156*9a741119SAndroid Build Coastguard Worker       }
157*9a741119SAndroid Build Coastguard Worker       res = PeekCallbackLocks(callback_function_names);
158*9a741119SAndroid Build Coastguard Worker     }
159*9a741119SAndroid Build Coastguard Worker     return res;
160*9a741119SAndroid Build Coastguard Worker   }
161*9a741119SAndroid Build Coastguard Worker 
162*9a741119SAndroid Build Coastguard Worker   /*
163*9a741119SAndroid Build Coastguard Worker    * Notify a waiting test when a callback is invoked.
164*9a741119SAndroid Build Coastguard Worker    * If callback_function_name is not provided, a default name will be used.
165*9a741119SAndroid Build Coastguard Worker    */
166*9a741119SAndroid Build Coastguard Worker   void NotifyFromCallback(const string& callback_function_name =
167*9a741119SAndroid Build Coastguard Worker                               kVtsHalHidlTargetCallbackDefaultName) {
168*9a741119SAndroid Build Coastguard Worker     unique_lock<mutex> lock(cb_wait_any_mtx_);
169*9a741119SAndroid Build Coastguard Worker     GetCallbackLock(callback_function_name)->NotifyFromCallback();
170*9a741119SAndroid Build Coastguard Worker     cb_wait_any_cv_.notify_one();
171*9a741119SAndroid Build Coastguard Worker   }
172*9a741119SAndroid Build Coastguard Worker 
173*9a741119SAndroid Build Coastguard Worker   /*
174*9a741119SAndroid Build Coastguard Worker    * Notify a waiting test with data when a callback is invoked.
175*9a741119SAndroid Build Coastguard Worker    */
NotifyFromCallback(const CallbackArgsTemplateClass & data)176*9a741119SAndroid Build Coastguard Worker   void NotifyFromCallback(const CallbackArgsTemplateClass& data) {
177*9a741119SAndroid Build Coastguard Worker     NotifyFromCallback(kVtsHalHidlTargetCallbackDefaultName, data);
178*9a741119SAndroid Build Coastguard Worker   }
179*9a741119SAndroid Build Coastguard Worker 
180*9a741119SAndroid Build Coastguard Worker   /*
181*9a741119SAndroid Build Coastguard Worker    * Notify a waiting test with data when a callback is invoked.
182*9a741119SAndroid Build Coastguard Worker    * If callback_function_name is not provided, a default name will be used.
183*9a741119SAndroid Build Coastguard Worker    */
NotifyFromCallback(const string & callback_function_name,const CallbackArgsTemplateClass & data)184*9a741119SAndroid Build Coastguard Worker   void NotifyFromCallback(const string& callback_function_name,
185*9a741119SAndroid Build Coastguard Worker                           const CallbackArgsTemplateClass& data) {
186*9a741119SAndroid Build Coastguard Worker     unique_lock<mutex> lock(cb_wait_any_mtx_);
187*9a741119SAndroid Build Coastguard Worker     GetCallbackLock(callback_function_name)->NotifyFromCallback(data);
188*9a741119SAndroid Build Coastguard Worker     cb_wait_any_cv_.notify_one();
189*9a741119SAndroid Build Coastguard Worker   }
190*9a741119SAndroid Build Coastguard Worker 
191*9a741119SAndroid Build Coastguard Worker   /*
192*9a741119SAndroid Build Coastguard Worker    * Clear lock and data for a callback function.
193*9a741119SAndroid Build Coastguard Worker    * This function is optional.
194*9a741119SAndroid Build Coastguard Worker    */
195*9a741119SAndroid Build Coastguard Worker   void ClearForCallback(const string& callback_function_name =
196*9a741119SAndroid Build Coastguard Worker                             kVtsHalHidlTargetCallbackDefaultName) {
197*9a741119SAndroid Build Coastguard Worker     GetCallbackLock(callback_function_name, true);
198*9a741119SAndroid Build Coastguard Worker   }
199*9a741119SAndroid Build Coastguard Worker 
200*9a741119SAndroid Build Coastguard Worker   /*
201*9a741119SAndroid Build Coastguard Worker    * Get wait timeout for a specific callback function.
202*9a741119SAndroid Build Coastguard Worker    * If callback_function_name is not provided, a default name will be used.
203*9a741119SAndroid Build Coastguard Worker    */
204*9a741119SAndroid Build Coastguard Worker   milliseconds GetWaitTimeout(const string& callback_function_name =
205*9a741119SAndroid Build Coastguard Worker                                   kVtsHalHidlTargetCallbackDefaultName) {
206*9a741119SAndroid Build Coastguard Worker     return GetCallbackLock(callback_function_name)->GetWaitTimeout();
207*9a741119SAndroid Build Coastguard Worker   }
208*9a741119SAndroid Build Coastguard Worker 
209*9a741119SAndroid Build Coastguard Worker   /*
210*9a741119SAndroid Build Coastguard Worker    * Set wait timeout for a specific callback function.
211*9a741119SAndroid Build Coastguard Worker    * To set a default timeout (not for the default function name),
212*9a741119SAndroid Build Coastguard Worker    * use SetWaitTimeoutDefault. default function name callback timeout will
213*9a741119SAndroid Build Coastguard Worker    * also be set by SetWaitTimeoutDefault.
214*9a741119SAndroid Build Coastguard Worker    */
SetWaitTimeout(const string & callback_function_name,milliseconds timeout)215*9a741119SAndroid Build Coastguard Worker   void SetWaitTimeout(const string& callback_function_name,
216*9a741119SAndroid Build Coastguard Worker                       milliseconds timeout) {
217*9a741119SAndroid Build Coastguard Worker     GetCallbackLock(callback_function_name)->SetWaitTimeout(timeout);
218*9a741119SAndroid Build Coastguard Worker   }
219*9a741119SAndroid Build Coastguard Worker 
220*9a741119SAndroid Build Coastguard Worker   /*
221*9a741119SAndroid Build Coastguard Worker    * Get default wait timeout for a callback function.
222*9a741119SAndroid Build Coastguard Worker    * The default timeout is valid for all callback function names that
223*9a741119SAndroid Build Coastguard Worker    * have not been specified a timeout value, including default function name.
224*9a741119SAndroid Build Coastguard Worker    */
GetWaitTimeoutDefault()225*9a741119SAndroid Build Coastguard Worker   milliseconds GetWaitTimeoutDefault() { return cb_default_wait_timeout_; }
226*9a741119SAndroid Build Coastguard Worker 
227*9a741119SAndroid Build Coastguard Worker   /*
228*9a741119SAndroid Build Coastguard Worker    * Set default wait timeout for a callback function.
229*9a741119SAndroid Build Coastguard Worker    * The default timeout is valid for all callback function names that
230*9a741119SAndroid Build Coastguard Worker    * have not been specified a timeout value, including default function name.
231*9a741119SAndroid Build Coastguard Worker    */
SetWaitTimeoutDefault(milliseconds timeout)232*9a741119SAndroid Build Coastguard Worker   void SetWaitTimeoutDefault(milliseconds timeout) {
233*9a741119SAndroid Build Coastguard Worker     cb_default_wait_timeout_ = timeout;
234*9a741119SAndroid Build Coastguard Worker   }
235*9a741119SAndroid Build Coastguard Worker 
236*9a741119SAndroid Build Coastguard Worker  private:
237*9a741119SAndroid Build Coastguard Worker   /*
238*9a741119SAndroid Build Coastguard Worker    * A utility class to store semaphore and data for a callback name.
239*9a741119SAndroid Build Coastguard Worker    */
240*9a741119SAndroid Build Coastguard Worker   class CallbackLock {
241*9a741119SAndroid Build Coastguard Worker    public:
CallbackLock(VtsHalHidlTargetCallbackBase & parent,const string & name)242*9a741119SAndroid Build Coastguard Worker     CallbackLock(VtsHalHidlTargetCallbackBase& parent, const string& name)
243*9a741119SAndroid Build Coastguard Worker         : wait_count_(0),
244*9a741119SAndroid Build Coastguard Worker           parent_(parent),
245*9a741119SAndroid Build Coastguard Worker           timeout_(milliseconds(-1)),
246*9a741119SAndroid Build Coastguard Worker           name_(name) {}
247*9a741119SAndroid Build Coastguard Worker 
248*9a741119SAndroid Build Coastguard Worker     /*
249*9a741119SAndroid Build Coastguard Worker      * Wait for represented callback function.
250*9a741119SAndroid Build Coastguard Worker      * Timeout defaults to -1 milliseconds. Negative timeout means use to
251*9a741119SAndroid Build Coastguard Worker      * use the time out set for the callback or default callback wait time out.
252*9a741119SAndroid Build Coastguard Worker      */
253*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult WaitForCallback(
254*9a741119SAndroid Build Coastguard Worker         milliseconds timeout = milliseconds(-1),
255*9a741119SAndroid Build Coastguard Worker         bool no_wait_blocking = false) {
256*9a741119SAndroid Build Coastguard Worker       return Wait(timeout, no_wait_blocking);
257*9a741119SAndroid Build Coastguard Worker     }
258*9a741119SAndroid Build Coastguard Worker 
259*9a741119SAndroid Build Coastguard Worker     /*
260*9a741119SAndroid Build Coastguard Worker      * Wait for represented callback function.
261*9a741119SAndroid Build Coastguard Worker      * Timeout defaults to -1 milliseconds. Negative timeout means use to
262*9a741119SAndroid Build Coastguard Worker      * use the time out set for the callback or default callback wait time out.
263*9a741119SAndroid Build Coastguard Worker      */
WaitForCallback(bool no_wait_blocking)264*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult WaitForCallback(bool no_wait_blocking) {
265*9a741119SAndroid Build Coastguard Worker       return Wait(milliseconds(-1), no_wait_blocking);
266*9a741119SAndroid Build Coastguard Worker     }
267*9a741119SAndroid Build Coastguard Worker 
268*9a741119SAndroid Build Coastguard Worker     /* Notify from represented callback function. */
NotifyFromCallback()269*9a741119SAndroid Build Coastguard Worker     void NotifyFromCallback() {
270*9a741119SAndroid Build Coastguard Worker       unique_lock<mutex> lock(wait_mtx_);
271*9a741119SAndroid Build Coastguard Worker       Notify();
272*9a741119SAndroid Build Coastguard Worker     }
273*9a741119SAndroid Build Coastguard Worker 
274*9a741119SAndroid Build Coastguard Worker     /* Notify from represented callback function with data. */
NotifyFromCallback(const CallbackArgsTemplateClass & data)275*9a741119SAndroid Build Coastguard Worker     void NotifyFromCallback(const CallbackArgsTemplateClass& data) {
276*9a741119SAndroid Build Coastguard Worker       unique_lock<mutex> wait_lock(wait_mtx_);
277*9a741119SAndroid Build Coastguard Worker       arg_data_.push(make_shared<CallbackArgsTemplateClass>(data));
278*9a741119SAndroid Build Coastguard Worker       Notify();
279*9a741119SAndroid Build Coastguard Worker     }
280*9a741119SAndroid Build Coastguard Worker 
281*9a741119SAndroid Build Coastguard Worker     /* Set wait timeout for represented callback function. */
SetWaitTimeout(milliseconds timeout)282*9a741119SAndroid Build Coastguard Worker     void SetWaitTimeout(milliseconds timeout) { timeout_ = timeout; }
283*9a741119SAndroid Build Coastguard Worker 
284*9a741119SAndroid Build Coastguard Worker     /* Get wait timeout for represented callback function. */
GetWaitTimeout()285*9a741119SAndroid Build Coastguard Worker     milliseconds GetWaitTimeout() {
286*9a741119SAndroid Build Coastguard Worker       if (timeout_ < milliseconds(0)) {
287*9a741119SAndroid Build Coastguard Worker         return parent_.GetWaitTimeoutDefault();
288*9a741119SAndroid Build Coastguard Worker       }
289*9a741119SAndroid Build Coastguard Worker       return timeout_;
290*9a741119SAndroid Build Coastguard Worker     }
291*9a741119SAndroid Build Coastguard Worker 
292*9a741119SAndroid Build Coastguard Worker    private:
293*9a741119SAndroid Build Coastguard Worker     /*
294*9a741119SAndroid Build Coastguard Worker      * Wait for represented callback function in a test.
295*9a741119SAndroid Build Coastguard Worker      * Returns a WaitForCallbackResult object containing wait results.
296*9a741119SAndroid Build Coastguard Worker      * Timeout defaults to -1 milliseconds. Negative timeout means use to
297*9a741119SAndroid Build Coastguard Worker      * use the time out set for the callback or default callback wait time out.
298*9a741119SAndroid Build Coastguard Worker      */
Wait(milliseconds timeout,bool no_wait_blocking)299*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult Wait(milliseconds timeout, bool no_wait_blocking) {
300*9a741119SAndroid Build Coastguard Worker       unique_lock<mutex> lock(wait_mtx_);
301*9a741119SAndroid Build Coastguard Worker       WaitForCallbackResult res;
302*9a741119SAndroid Build Coastguard Worker       res.name = name_;
303*9a741119SAndroid Build Coastguard Worker       if (!no_wait_blocking) {
304*9a741119SAndroid Build Coastguard Worker         if (timeout < milliseconds(0)) {
305*9a741119SAndroid Build Coastguard Worker           timeout = GetWaitTimeout();
306*9a741119SAndroid Build Coastguard Worker         }
307*9a741119SAndroid Build Coastguard Worker         auto expiration = steady_clock::now() + timeout;
308*9a741119SAndroid Build Coastguard Worker         while (wait_count_ == 0) {
309*9a741119SAndroid Build Coastguard Worker           auto status = wait_cv_.wait_until(lock, expiration);
310*9a741119SAndroid Build Coastguard Worker           if (status == cv_status::timeout) {
311*9a741119SAndroid Build Coastguard Worker             cerr << "Timed out waiting for callback" << endl;
312*9a741119SAndroid Build Coastguard Worker             return res;
313*9a741119SAndroid Build Coastguard Worker           }
314*9a741119SAndroid Build Coastguard Worker         }
315*9a741119SAndroid Build Coastguard Worker       } else if (!wait_count_) {
316*9a741119SAndroid Build Coastguard Worker         return res;
317*9a741119SAndroid Build Coastguard Worker       }
318*9a741119SAndroid Build Coastguard Worker 
319*9a741119SAndroid Build Coastguard Worker       wait_count_--;
320*9a741119SAndroid Build Coastguard Worker       res.no_timeout = true;
321*9a741119SAndroid Build Coastguard Worker       if (!arg_data_.empty()) {
322*9a741119SAndroid Build Coastguard Worker         res.args = arg_data_.front();
323*9a741119SAndroid Build Coastguard Worker         arg_data_.pop();
324*9a741119SAndroid Build Coastguard Worker       }
325*9a741119SAndroid Build Coastguard Worker       return res;
326*9a741119SAndroid Build Coastguard Worker     }
327*9a741119SAndroid Build Coastguard Worker 
328*9a741119SAndroid Build Coastguard Worker     /* Notify from represented callback function. */
Notify()329*9a741119SAndroid Build Coastguard Worker     void Notify() {
330*9a741119SAndroid Build Coastguard Worker       wait_count_++;
331*9a741119SAndroid Build Coastguard Worker       wait_cv_.notify_one();
332*9a741119SAndroid Build Coastguard Worker     }
333*9a741119SAndroid Build Coastguard Worker 
334*9a741119SAndroid Build Coastguard Worker     // Mutex for protecting operations on wait count and conditional variable
335*9a741119SAndroid Build Coastguard Worker     mutex wait_mtx_;
336*9a741119SAndroid Build Coastguard Worker     // Conditional variable for callback wait and notify
337*9a741119SAndroid Build Coastguard Worker     condition_variable wait_cv_;
338*9a741119SAndroid Build Coastguard Worker     // Count for callback conditional variable
339*9a741119SAndroid Build Coastguard Worker     unsigned int wait_count_;
340*9a741119SAndroid Build Coastguard Worker     // A queue of callback arg data
341*9a741119SAndroid Build Coastguard Worker     queue<shared_ptr<CallbackArgsTemplateClass>> arg_data_;
342*9a741119SAndroid Build Coastguard Worker     // Pointer to parent class
343*9a741119SAndroid Build Coastguard Worker     VtsHalHidlTargetCallbackBase& parent_;
344*9a741119SAndroid Build Coastguard Worker     // Wait time out
345*9a741119SAndroid Build Coastguard Worker     milliseconds timeout_;
346*9a741119SAndroid Build Coastguard Worker     // Name of the represented callback function
347*9a741119SAndroid Build Coastguard Worker     string name_;
348*9a741119SAndroid Build Coastguard Worker   };
349*9a741119SAndroid Build Coastguard Worker 
350*9a741119SAndroid Build Coastguard Worker   /*
351*9a741119SAndroid Build Coastguard Worker    * Get CallbackLock object using callback function name.
352*9a741119SAndroid Build Coastguard Worker    * If callback_function_name is not provided, a default name will be used.
353*9a741119SAndroid Build Coastguard Worker    * If callback_function_name does not exists in map yet, a new CallbackLock
354*9a741119SAndroid Build Coastguard Worker    * object will be created.
355*9a741119SAndroid Build Coastguard Worker    * If auto_clear is true, the old CallbackLock will be deleted.
356*9a741119SAndroid Build Coastguard Worker    */
357*9a741119SAndroid Build Coastguard Worker   CallbackLock* GetCallbackLock(const string& callback_function_name,
358*9a741119SAndroid Build Coastguard Worker                                 bool auto_clear = false) {
359*9a741119SAndroid Build Coastguard Worker     unique_lock<mutex> lock(cb_lock_map_mtx_);
360*9a741119SAndroid Build Coastguard Worker     auto found = cb_lock_map_.find(callback_function_name);
361*9a741119SAndroid Build Coastguard Worker     if (found == cb_lock_map_.end()) {
362*9a741119SAndroid Build Coastguard Worker       CallbackLock* result = new CallbackLock(*this, callback_function_name);
363*9a741119SAndroid Build Coastguard Worker       cb_lock_map_.insert({callback_function_name, result});
364*9a741119SAndroid Build Coastguard Worker       return result;
365*9a741119SAndroid Build Coastguard Worker     } else {
366*9a741119SAndroid Build Coastguard Worker       if (auto_clear) {
367*9a741119SAndroid Build Coastguard Worker         delete (found->second);
368*9a741119SAndroid Build Coastguard Worker         found->second = new CallbackLock(*this, callback_function_name);
369*9a741119SAndroid Build Coastguard Worker       }
370*9a741119SAndroid Build Coastguard Worker       return found->second;
371*9a741119SAndroid Build Coastguard Worker     }
372*9a741119SAndroid Build Coastguard Worker   }
373*9a741119SAndroid Build Coastguard Worker 
374*9a741119SAndroid Build Coastguard Worker   /*
375*9a741119SAndroid Build Coastguard Worker    * Get wait timeout for a list of function names.
376*9a741119SAndroid Build Coastguard Worker    * If timeout_any is not negative, start_time + timeout_any will be returned.
377*9a741119SAndroid Build Coastguard Worker    * Otherwise, the shortest timeout from the list will be returned.
378*9a741119SAndroid Build Coastguard Worker    */
GetWaitAnyTimeout(const vector<string> & callback_function_names,steady_clock::time_point start_time,milliseconds timeout_any)379*9a741119SAndroid Build Coastguard Worker   steady_clock::time_point GetWaitAnyTimeout(
380*9a741119SAndroid Build Coastguard Worker       const vector<string>& callback_function_names,
381*9a741119SAndroid Build Coastguard Worker       steady_clock::time_point start_time, milliseconds timeout_any) {
382*9a741119SAndroid Build Coastguard Worker     if (timeout_any >= milliseconds(0)) {
383*9a741119SAndroid Build Coastguard Worker       return start_time + timeout_any;
384*9a741119SAndroid Build Coastguard Worker     }
385*9a741119SAndroid Build Coastguard Worker 
386*9a741119SAndroid Build Coastguard Worker     auto locks = GetWaitAnyCallbackLocks(callback_function_names);
387*9a741119SAndroid Build Coastguard Worker 
388*9a741119SAndroid Build Coastguard Worker     auto timeout_min = steady_clock::duration::max();
389*9a741119SAndroid Build Coastguard Worker     for (auto lock : locks) {
390*9a741119SAndroid Build Coastguard Worker       auto timeout = lock->GetWaitTimeout();
391*9a741119SAndroid Build Coastguard Worker       if (timeout < timeout_min) {
392*9a741119SAndroid Build Coastguard Worker         timeout_min = timeout;
393*9a741119SAndroid Build Coastguard Worker       }
394*9a741119SAndroid Build Coastguard Worker     }
395*9a741119SAndroid Build Coastguard Worker 
396*9a741119SAndroid Build Coastguard Worker     return start_time + timeout_min;
397*9a741119SAndroid Build Coastguard Worker   }
398*9a741119SAndroid Build Coastguard Worker 
399*9a741119SAndroid Build Coastguard Worker   /*
400*9a741119SAndroid Build Coastguard Worker    * Get a list of CallbackLock pointers from provided function name list.
401*9a741119SAndroid Build Coastguard Worker    */
GetWaitAnyCallbackLocks(const vector<string> & callback_function_names)402*9a741119SAndroid Build Coastguard Worker   vector<CallbackLock*> GetWaitAnyCallbackLocks(
403*9a741119SAndroid Build Coastguard Worker       const vector<string>& callback_function_names) {
404*9a741119SAndroid Build Coastguard Worker     vector<CallbackLock*> res;
405*9a741119SAndroid Build Coastguard Worker     if (callback_function_names.empty()) {
406*9a741119SAndroid Build Coastguard Worker       for (auto const& it : cb_lock_map_) {
407*9a741119SAndroid Build Coastguard Worker         res.push_back(it.second);
408*9a741119SAndroid Build Coastguard Worker       }
409*9a741119SAndroid Build Coastguard Worker     } else {
410*9a741119SAndroid Build Coastguard Worker       for (auto const& name : callback_function_names) {
411*9a741119SAndroid Build Coastguard Worker         res.push_back(GetCallbackLock(name));
412*9a741119SAndroid Build Coastguard Worker       }
413*9a741119SAndroid Build Coastguard Worker     }
414*9a741119SAndroid Build Coastguard Worker     return res;
415*9a741119SAndroid Build Coastguard Worker   }
416*9a741119SAndroid Build Coastguard Worker 
417*9a741119SAndroid Build Coastguard Worker   /*
418*9a741119SAndroid Build Coastguard Worker    * Peek into the list of callback locks to check whether any of the
419*9a741119SAndroid Build Coastguard Worker    * callback functions has been called.
420*9a741119SAndroid Build Coastguard Worker    */
PeekCallbackLocks(const vector<string> & callback_function_names)421*9a741119SAndroid Build Coastguard Worker   WaitForCallbackResult PeekCallbackLocks(
422*9a741119SAndroid Build Coastguard Worker       const vector<string>& callback_function_names) {
423*9a741119SAndroid Build Coastguard Worker     auto locks = GetWaitAnyCallbackLocks(callback_function_names);
424*9a741119SAndroid Build Coastguard Worker     for (auto lock : locks) {
425*9a741119SAndroid Build Coastguard Worker       auto test = lock->WaitForCallback(true);
426*9a741119SAndroid Build Coastguard Worker       if (test.no_timeout) {
427*9a741119SAndroid Build Coastguard Worker         return test;
428*9a741119SAndroid Build Coastguard Worker       }
429*9a741119SAndroid Build Coastguard Worker     }
430*9a741119SAndroid Build Coastguard Worker     WaitForCallbackResult res;
431*9a741119SAndroid Build Coastguard Worker     return res;
432*9a741119SAndroid Build Coastguard Worker   }
433*9a741119SAndroid Build Coastguard Worker 
434*9a741119SAndroid Build Coastguard Worker   // A map of function name and CallbackLock object pointers
435*9a741119SAndroid Build Coastguard Worker   unordered_map<string, CallbackLock*> cb_lock_map_;
436*9a741119SAndroid Build Coastguard Worker   // Mutex for protecting operations on lock map
437*9a741119SAndroid Build Coastguard Worker   mutex cb_lock_map_mtx_;
438*9a741119SAndroid Build Coastguard Worker   // Mutex for protecting waiting any callback
439*9a741119SAndroid Build Coastguard Worker   mutex cb_wait_any_mtx_;
440*9a741119SAndroid Build Coastguard Worker   // Default wait timeout
441*9a741119SAndroid Build Coastguard Worker   milliseconds cb_default_wait_timeout_;
442*9a741119SAndroid Build Coastguard Worker   // Conditional variable for any callback notify
443*9a741119SAndroid Build Coastguard Worker   condition_variable cb_wait_any_cv_;
444*9a741119SAndroid Build Coastguard Worker };
445*9a741119SAndroid Build Coastguard Worker 
446*9a741119SAndroid Build Coastguard Worker }  // namespace testing
447*9a741119SAndroid Build Coastguard Worker 
448*9a741119SAndroid Build Coastguard Worker #endif  // __VTS_HAL_HIDL_TARGET_CALLBACK_BASE_H
449