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