/* * 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 "wificond/looper_backed_event_loop.h" #include #include #include namespace { class EventLoopCallback : public android::MessageHandler { public: explicit EventLoopCallback(const std::function& callback) : callback_(callback) { } ~EventLoopCallback() override = default; virtual void handleMessage(const android::Message& message) { callback_(); } private: const std::function callback_; DISALLOW_COPY_AND_ASSIGN(EventLoopCallback); }; class WatchFdCallback : public android::LooperCallback { public: explicit WatchFdCallback(const std::function& callback) : callback_(callback) { } ~WatchFdCallback() override = default; virtual int handleEvent(int fd, int events, void* data) { callback_(fd); // Returning 1 means Looper keeps watching this file descriptor after // callback is called. // See Looper.h for details. return 1; } private: const std::function callback_; DISALLOW_COPY_AND_ASSIGN(WatchFdCallback); }; } // namespace namespace android { namespace wificond { LooperBackedEventLoop::LooperBackedEventLoop() : should_continue_(true) { looper_ = android::Looper::prepare(Looper::PREPARE_ALLOW_NON_CALLBACKS); } LooperBackedEventLoop::~LooperBackedEventLoop() { } void LooperBackedEventLoop::PostTask(const std::function& callback) { sp event_loop_callback = new EventLoopCallback(callback); looper_->sendMessage(event_loop_callback, NULL); } void LooperBackedEventLoop::PostDelayedTask( const std::function& callback, int64_t delay_ms) { sp looper_callback = new EventLoopCallback(callback); looper_->sendMessageDelayed(ms2ns(delay_ms), looper_callback, NULL); } bool LooperBackedEventLoop::WatchFileDescriptor( int fd, ReadyMode mode, const std::function& callback) { sp watch_fd_callback = new WatchFdCallback(callback); int event; if (mode == kModeInput) { event = Looper::EVENT_INPUT; } else if (mode == kModeOutput) { event = Looper::EVENT_OUTPUT; } else { LOG(ERROR) << "Invalid mode for WatchFileDescriptor()."; return false; } // addFd() returns 1 if descriptor was added, 0 if arguments were invalid. // Since we are using non-NULL callback, the second parameter 'ident' will // always be ignored. It is OK to use 0 for 'ident'. // See Looper.h for more details. if (looper_->addFd(fd, 0, event, watch_fd_callback, NULL) == 0) { LOG(ERROR) << "Invalid arguments for Looper::addFd()."; return false; } return true; } bool LooperBackedEventLoop::StopWatchFileDescriptor(int fd) { if (looper_->removeFd(fd) == 1) { return true; } return false; } void LooperBackedEventLoop::Poll() { while (should_continue_) { looper_->pollOnce(-1); } } void LooperBackedEventLoop::PollForOne(int timeout_millis) { looper_->pollOnce(timeout_millis); } void LooperBackedEventLoop::TriggerExit() { PostTask([this](){ should_continue_ = false; }); } } // namespace wificond } // namespace android