blob: c3e72f16c18c29b1fcceea9fddfc2d8c21cf6148 [file] [log] [blame]
/*
* 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