1/* 2 * Copyright (C) 2016 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#include <ctime> 18 19#include <private/binder/Static.h> 20 21#include "binder_dispatcher.h" 22 23using std::chrono::steady_clock; 24 25namespace { 26int convertDurationToMillis(const steady_clock::time_point& start, 27 const steady_clock::time_point& end) { 28 return static_cast<int>( 29 std::chrono::duration_cast<std::chrono::milliseconds>(end - start) 30 .count()); 31} 32} 33namespace android { 34namespace wificond { 35namespace tests { 36namespace integration { 37 38BinderDispatcher::BinderDispatcher() 39 : event_dispatcher_(new LooperBackedEventLoop()), 40 binder_fd_(-1), 41 needs_init_(true), 42 was_interrupted_(false) {} 43 44BinderDispatcher::~BinderDispatcher() { 45 // This is ugly! We want to cleanup the binder driver state at 46 // the end of each test (if binder driver was initialized during test). 47 // Destroying the instance of |ProcessState| should trigger the cleanup 48 // of the binder fd for this process. So, the next test will reinitialize 49 // a new instance of |ProcessState| and a new binder fd. 50 if (!needs_init_) { 51 event_dispatcher_->StopWatchFileDescriptor(binder_fd_); 52 gProcess.clear(); 53 } 54} 55 56bool BinderDispatcher::DispatchFor(int timeout_millis) { 57 // Initialize the looper and binder if not already done. 58 if (needs_init_) { 59 Init(); 60 } 61 62 was_interrupted_ = false; 63 steady_clock::time_point start_time = steady_clock::now(); 64 int millis_left = timeout_millis; 65 do { 66 event_dispatcher_->PollForOne(millis_left); 67 millis_left = timeout_millis - 68 convertDurationToMillis(start_time, steady_clock::now()); 69 } while (millis_left > 0 && !was_interrupted_); 70 return was_interrupted_; 71} 72 73void BinderDispatcher::InterruptDispatch() { 74 was_interrupted_ = true; 75} 76 77void BinderDispatcher::Init() { 78 // Initilize the binder fd for polling. 79 android::ProcessState::self()->setThreadPoolMaxThreadCount(0); 80 android::IPCThreadState::self()->disableBackgroundScheduling(true); 81 int err = android::IPCThreadState::self()->setupPolling(&binder_fd_); 82 CHECK_EQ(err, 0) << "Error setting up binder polling: " << strerror(-err); 83 CHECK_GE(binder_fd_, 0) << "Invalid binder FD: " << binder_fd_; 84 85 auto binder_event_handler = 86 std::bind(&BinderDispatcher::OnBinderEvent, this, std::placeholders::_1); 87 // Add the binder fd to the looper watch list. 88 CHECK(event_dispatcher_->WatchFileDescriptor( 89 binder_fd_, 90 android::wificond::EventLoop::kModeInput, 91 binder_event_handler)) 92 << "Failed to watch binder FD"; 93 needs_init_ = false; 94} 95 96void BinderDispatcher::OnBinderEvent(int /* fd */) { 97 android::IPCThreadState::self()->handlePolledCommands(); 98} 99} // namespace integration 100} // namespace tests 101} // namespace wificond 102} // namespace android 103