| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <ctime> |
| |
| #include <private/binder/Static.h> |
| |
| #include "binder_dispatcher.h" |
| |
| using std::chrono::steady_clock; |
| |
| namespace { |
| int convertDurationToMillis(const steady_clock::time_point& start, |
| const steady_clock::time_point& end) { |
| return static_cast<int>( |
| std::chrono::duration_cast<std::chrono::milliseconds>(end - start) |
| .count()); |
| } |
| } |
| namespace android { |
| namespace wificond { |
| namespace tests { |
| namespace integration { |
| |
| BinderDispatcher::BinderDispatcher() |
| : event_dispatcher_(new LooperBackedEventLoop()), |
| binder_fd_(-1), |
| needs_init_(true), |
| was_interrupted_(false) {} |
| |
| BinderDispatcher::~BinderDispatcher() { |
| // This is ugly! We want to cleanup the binder driver state at |
| // the end of each test (if binder driver was initialized during test). |
| // Destroying the instance of |ProcessState| should trigger the cleanup |
| // of the binder fd for this process. So, the next test will reinitialize |
| // a new instance of |ProcessState| and a new binder fd. |
| if (!needs_init_) { |
| event_dispatcher_->StopWatchFileDescriptor(binder_fd_); |
| gProcess.clear(); |
| } |
| } |
| |
| bool BinderDispatcher::DispatchFor(int timeout_millis) { |
| // Initialize the looper and binder if not already done. |
| if (needs_init_) { |
| Init(); |
| } |
| |
| was_interrupted_ = false; |
| steady_clock::time_point start_time = steady_clock::now(); |
| int millis_left = timeout_millis; |
| do { |
| event_dispatcher_->PollForOne(millis_left); |
| millis_left = timeout_millis - |
| convertDurationToMillis(start_time, steady_clock::now()); |
| } while (millis_left > 0 && !was_interrupted_); |
| return was_interrupted_; |
| } |
| |
| void BinderDispatcher::InterruptDispatch() { |
| was_interrupted_ = true; |
| } |
| |
| void BinderDispatcher::Init() { |
| // Initilize the binder fd for polling. |
| android::ProcessState::self()->setThreadPoolMaxThreadCount(0); |
| android::IPCThreadState::self()->disableBackgroundScheduling(true); |
| int err = android::IPCThreadState::self()->setupPolling(&binder_fd_); |
| CHECK_EQ(err, 0) << "Error setting up binder polling: " << strerror(-err); |
| CHECK_GE(binder_fd_, 0) << "Invalid binder FD: " << binder_fd_; |
| |
| auto binder_event_handler = |
| std::bind(&BinderDispatcher::OnBinderEvent, this, std::placeholders::_1); |
| // Add the binder fd to the looper watch list. |
| CHECK(event_dispatcher_->WatchFileDescriptor( |
| binder_fd_, |
| android::wificond::EventLoop::kModeInput, |
| binder_event_handler)) |
| << "Failed to watch binder FD"; |
| needs_init_ = false; |
| } |
| |
| void BinderDispatcher::OnBinderEvent(int /* fd */) { |
| android::IPCThreadState::self()->handlePolledCommands(); |
| } |
| } // namespace integration |
| } // namespace tests |
| } // namespace wificond |
| } // namespace android |