You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.7 KiB
139 lines
3.7 KiB
/* |
|
* 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 <android-base/logging.h> |
|
#include <utils/Looper.h> |
|
#include <utils/Timers.h> |
|
|
|
namespace { |
|
|
|
class EventLoopCallback : public android::MessageHandler { |
|
public: |
|
explicit EventLoopCallback(const std::function<void()>& callback) |
|
: callback_(callback) { |
|
} |
|
|
|
~EventLoopCallback() override = default; |
|
|
|
virtual void handleMessage(const android::Message& message) { |
|
callback_(); |
|
} |
|
|
|
private: |
|
const std::function<void()> callback_; |
|
|
|
DISALLOW_COPY_AND_ASSIGN(EventLoopCallback); |
|
}; |
|
|
|
class WatchFdCallback : public android::LooperCallback { |
|
public: |
|
explicit WatchFdCallback(const std::function<void(int)>& 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<void(int)> 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<void()>& callback) { |
|
sp<android::MessageHandler> event_loop_callback = |
|
new EventLoopCallback(callback); |
|
looper_->sendMessage(event_loop_callback, NULL); |
|
} |
|
|
|
void LooperBackedEventLoop::PostDelayedTask( |
|
const std::function<void()>& callback, |
|
int64_t delay_ms) { |
|
sp<android::MessageHandler> looper_callback = new EventLoopCallback(callback); |
|
looper_->sendMessageDelayed(ms2ns(delay_ms), looper_callback, NULL); |
|
} |
|
|
|
bool LooperBackedEventLoop::WatchFileDescriptor( |
|
int fd, |
|
ReadyMode mode, |
|
const std::function<void(int)>& callback) { |
|
sp<android::LooperCallback> 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
|
|
|