Loading automotive/remoteaccess/hal/default/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ cc_binary { vintf_fragments: ["remoteaccess-default-service.xml"], init_rc: ["remoteaccess-default-service.rc"], cflags: [ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"", "-DGRPC_SERVICE_ADDRESS=\"10.0.2.2:50051\"", ], } Loading automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -30,12 +30,12 @@ constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default"; int main(int /* argc */, char* /* argv */[]) { LOG(INFO) << "Registering RemoteAccessService as service..."; #ifndef GRPC_SERVICE_ADDRESS LOG(ERROR) << "GRPC_SERVICE_ADDRESS is not defined, exiting"; exit(1); #endif LOG(INFO) << "Registering RemoteAccessService as service, server: " << GRPC_SERVICE_ADDRESS << "..."; grpc::ChannelArguments grpcargs = {}; #ifdef GRPC_SERVICE_IFNAME Loading @@ -48,8 +48,7 @@ int main(int /* argc */, char* /* argv */[]) { android::netdevice::WaitCondition::PRESENT_AND_UP); LOG(INFO) << "Waiting for interface: " << GRPC_SERVICE_IFNAME << " done"; #endif auto channel = grpc::CreateCustomChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials(), grpcargs); auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials()); auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel); auto service = ndk::SharedRefBase::make< android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get()); Loading automotive/remoteaccess/test_grpc_server/impl/Android.bp +21 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,26 @@ cc_binary { ], cflags: [ "-Wno-unused-parameter", "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"", "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"", ], } cc_binary_host { name: "TestWakeupClientServerHost", srcs: ["src/*.cpp"], local_include_dirs: ["include"], shared_libs: [ "libbase", "libutils", "libgrpc++", "libprotobuf-cpp-full", ], whole_static_libs: [ "wakeup_client_protos", ], cflags: [ "-Wno-unused-parameter", "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"", "-DHOST", ], } automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h +39 −9 Original line number Diff line number Diff line Loading @@ -34,11 +34,9 @@ namespace remoteaccess { // implementation, the task should come from remote task server. This class is thread-safe. class FakeTaskGenerator final { public: GetRemoteTasksResponse generateTask(); GetRemoteTasksResponse generateTask(const std::string& clientId); private: // Simulates the client ID for each task. std::atomic<int> mCurrentClientId = 0; constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef}; }; Loading Loading @@ -99,7 +97,7 @@ class TaskQueue final { void waitForTaskWithLock(std::unique_lock<std::mutex>& lock); }; class TestWakeupClientServiceImpl final : public WakeupClient::Service { class TestWakeupClientServiceImpl : public WakeupClient::Service { public: TestWakeupClientServiceImpl(); Loading @@ -112,25 +110,57 @@ class TestWakeupClientServiceImpl final : public WakeupClient::Service { const NotifyWakeupRequiredRequest* request, NotifyWakeupRequiredResponse* response) override; /** * Starts generating fake tasks for the specific client repeatedly. * * The fake task will have {0xDE 0xAD 0xBE 0xEF} as payload. A new fake task will be sent * to the client every 5s. */ void startGeneratingFakeTask(const std::string& clientId); /** * stops generating fake tasks. */ void stopGeneratingFakeTask(); /** * Returns whether we need to wakeup the target device to send remote tasks. */ bool isWakeupRequired(); /** * Returns whether we have an active connection with the target device. */ bool isRemoteTaskConnectionAlive(); /** * Injects a fake task with taskData to be sent to the specific client. */ void injectTask(const std::string& taskData, const std::string& clientId); /** * Wakes up the target device. * * This must be implemented by child class and contains device specific logic. E.g. this might * be sending QEMU commands for the emulator device. */ virtual void wakeupApplicationProcessor() = 0; private: // This is a thread for communicating with remote wakeup server (via network) and receive tasks // from it. std::thread mThread; // A variable to notify server is stopping. std::condition_variable mServerStoppedCv; std::condition_variable mTaskLoopStoppedCv; // Whether wakeup AP is required for executing tasks. std::atomic<bool> mWakeupRequired = true; // Whether we currently have an active long-live connection to deliver remote tasks. std::atomic<bool> mRemoteTaskConnectionAlive = false; std::mutex mLock; bool mServerStopped GUARDED_BY(mLock); bool mGeneratingFakeTask GUARDED_BY(mLock); // Thread-safe. For test impl only. FakeTaskGenerator mFakeTaskGenerator; // Thread-sfae. TaskQueue mTaskQueue; void fakeTaskGenerateLoop(); void wakeupApplicationProcessor(); void fakeTaskGenerateLoop(const std::string& clientId); void injectTaskResponse(const GetRemoteTasksResponse& response); }; } // namespace remoteaccess Loading automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp +63 −24 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include "TestWakeupClientServiceImpl.h" #include "ApPowerControl.h" #include <android-base/stringprintf.h> #include <inttypes.h> #include <utils/Looper.h> Loading @@ -44,12 +42,10 @@ constexpr int64_t KTaskTimeoutInMs = 20'000; } // namespace GetRemoteTasksResponse FakeTaskGenerator::generateTask() { int clientId = mCurrentClientId++; GetRemoteTasksResponse FakeTaskGenerator::generateTask(const std::string& clientId) { GetRemoteTasksResponse response; response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA))); std::string clientIdStr = StringPrintf("%d", clientId); response.set_clientid(clientIdStr); response.set_data(reinterpret_cast<const char*>(DATA), sizeof(DATA)); response.set_clientid(clientId); return response; } Loading Loading @@ -165,38 +161,68 @@ void TaskQueue::handleTaskTimeout() { } } TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() { mThread = std::thread([this] { fakeTaskGenerateLoop(); }); } TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {} TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() { { std::lock_guard<std::mutex> lockGuard(mLock); } mTaskQueue.stopWait(); stopGeneratingFakeTask(); } void TestWakeupClientServiceImpl::injectTask(const std::string& taskData, const std::string& clientId) { GetRemoteTasksResponse response; response.set_data(taskData); response.set_clientid(clientId); injectTaskResponse(response); } void TestWakeupClientServiceImpl::injectTaskResponse(const GetRemoteTasksResponse& response) { printf("Received a new task\n"); mTaskQueue.add(response); if (mWakeupRequired) { wakeupApplicationProcessor(); } } void TestWakeupClientServiceImpl::startGeneratingFakeTask(const std::string& clientId) { std::lock_guard<std::mutex> lockGuard(mLock); if (mGeneratingFakeTask) { printf("Fake task is already being generated\n"); return; } mGeneratingFakeTask = true; mThread = std::thread([this, clientId] { fakeTaskGenerateLoop(clientId); }); printf("Started generating fake tasks\n"); } void TestWakeupClientServiceImpl::stopGeneratingFakeTask() { { std::lock_guard<std::mutex> lockGuard(mLock); mServerStopped = true; mServerStoppedCv.notify_all(); if (!mGeneratingFakeTask) { printf("Fake task is not being generated, do nothing\n"); return; } mTaskLoopStoppedCv.notify_all(); mGeneratingFakeTask = false; } mTaskQueue.stopWait(); if (mThread.joinable()) { mThread.join(); } printf("Stopped generating fake tasks\n"); } void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() { void TestWakeupClientServiceImpl::fakeTaskGenerateLoop(const std::string& clientId) { // In actual implementation, this should communicate with the remote server and receives tasks // from it. Here we simulate receiving one remote task every {kTaskIntervalInMs}ms. while (true) { mTaskQueue.add(mFakeTaskGenerator.generateTask()); printf("Received a new task\n"); if (mWakeupRequired) { wakeupApplicationProcessor(); } injectTaskResponse(mFakeTaskGenerator.generateTask(clientId)); printf("Sleeping for %d seconds until next task\n", kTaskIntervalInMs); std::unique_lock lk(mLock); if (mServerStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] { if (mTaskLoopStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] { ScopedLockAssertion lockAssertion(mLock); return mServerStopped; return !mGeneratingFakeTask; })) { // If the stopped flag is set, we are quitting, exit the loop. return; Loading @@ -208,6 +234,7 @@ Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context, const GetRemoteTasksRequest* request, ServerWriter<GetRemoteTasksResponse>* writer) { printf("GetRemoteTasks called\n"); mRemoteTaskConnectionAlive = true; while (true) { mTaskQueue.waitForTask(); Loading @@ -226,16 +253,19 @@ Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context, // The task failed to be sent, add it back to the queue. The order might change, but // it is okay. mTaskQueue.add(response); mRemoteTaskConnectionAlive = false; return Status::CANCELLED; } } } mRemoteTaskConnectionAlive = false; return Status::OK; } Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context, const NotifyWakeupRequiredRequest* request, NotifyWakeupRequiredResponse* response) { printf("NotifyWakeupRequired called\n"); if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue.isEmpty()) { // If wakeup is now required and previously not required, this means we have finished // shutting down the device. If there are still pending tasks, try waking up AP again Loading @@ -243,11 +273,20 @@ Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context, wakeupApplicationProcessor(); } mWakeupRequired = request->iswakeuprequired(); if (mWakeupRequired) { // We won't know the connection is down unless we try to send a task over. If wakeup is // required, the connection is very likely already down. mRemoteTaskConnectionAlive = false; } return Status::OK; } void TestWakeupClientServiceImpl::wakeupApplicationProcessor() { wakeupAp(); bool TestWakeupClientServiceImpl::isWakeupRequired() { return mWakeupRequired; } bool TestWakeupClientServiceImpl::isRemoteTaskConnectionAlive() { return mRemoteTaskConnectionAlive; } } // namespace remoteaccess Loading Loading
automotive/remoteaccess/hal/default/Android.bp +1 −1 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ cc_binary { vintf_fragments: ["remoteaccess-default-service.xml"], init_rc: ["remoteaccess-default-service.rc"], cflags: [ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"", "-DGRPC_SERVICE_ADDRESS=\"10.0.2.2:50051\"", ], } Loading
automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp +3 −4 Original line number Diff line number Diff line Loading @@ -30,12 +30,12 @@ constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default"; int main(int /* argc */, char* /* argv */[]) { LOG(INFO) << "Registering RemoteAccessService as service..."; #ifndef GRPC_SERVICE_ADDRESS LOG(ERROR) << "GRPC_SERVICE_ADDRESS is not defined, exiting"; exit(1); #endif LOG(INFO) << "Registering RemoteAccessService as service, server: " << GRPC_SERVICE_ADDRESS << "..."; grpc::ChannelArguments grpcargs = {}; #ifdef GRPC_SERVICE_IFNAME Loading @@ -48,8 +48,7 @@ int main(int /* argc */, char* /* argv */[]) { android::netdevice::WaitCondition::PRESENT_AND_UP); LOG(INFO) << "Waiting for interface: " << GRPC_SERVICE_IFNAME << " done"; #endif auto channel = grpc::CreateCustomChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials(), grpcargs); auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials()); auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel); auto service = ndk::SharedRefBase::make< android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get()); Loading
automotive/remoteaccess/test_grpc_server/impl/Android.bp +21 −1 Original line number Diff line number Diff line Loading @@ -38,6 +38,26 @@ cc_binary { ], cflags: [ "-Wno-unused-parameter", "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"", "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"", ], } cc_binary_host { name: "TestWakeupClientServerHost", srcs: ["src/*.cpp"], local_include_dirs: ["include"], shared_libs: [ "libbase", "libutils", "libgrpc++", "libprotobuf-cpp-full", ], whole_static_libs: [ "wakeup_client_protos", ], cflags: [ "-Wno-unused-parameter", "-DGRPC_SERVICE_ADDRESS=\"127.0.0.1:50051\"", "-DHOST", ], }
automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h +39 −9 Original line number Diff line number Diff line Loading @@ -34,11 +34,9 @@ namespace remoteaccess { // implementation, the task should come from remote task server. This class is thread-safe. class FakeTaskGenerator final { public: GetRemoteTasksResponse generateTask(); GetRemoteTasksResponse generateTask(const std::string& clientId); private: // Simulates the client ID for each task. std::atomic<int> mCurrentClientId = 0; constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef}; }; Loading Loading @@ -99,7 +97,7 @@ class TaskQueue final { void waitForTaskWithLock(std::unique_lock<std::mutex>& lock); }; class TestWakeupClientServiceImpl final : public WakeupClient::Service { class TestWakeupClientServiceImpl : public WakeupClient::Service { public: TestWakeupClientServiceImpl(); Loading @@ -112,25 +110,57 @@ class TestWakeupClientServiceImpl final : public WakeupClient::Service { const NotifyWakeupRequiredRequest* request, NotifyWakeupRequiredResponse* response) override; /** * Starts generating fake tasks for the specific client repeatedly. * * The fake task will have {0xDE 0xAD 0xBE 0xEF} as payload. A new fake task will be sent * to the client every 5s. */ void startGeneratingFakeTask(const std::string& clientId); /** * stops generating fake tasks. */ void stopGeneratingFakeTask(); /** * Returns whether we need to wakeup the target device to send remote tasks. */ bool isWakeupRequired(); /** * Returns whether we have an active connection with the target device. */ bool isRemoteTaskConnectionAlive(); /** * Injects a fake task with taskData to be sent to the specific client. */ void injectTask(const std::string& taskData, const std::string& clientId); /** * Wakes up the target device. * * This must be implemented by child class and contains device specific logic. E.g. this might * be sending QEMU commands for the emulator device. */ virtual void wakeupApplicationProcessor() = 0; private: // This is a thread for communicating with remote wakeup server (via network) and receive tasks // from it. std::thread mThread; // A variable to notify server is stopping. std::condition_variable mServerStoppedCv; std::condition_variable mTaskLoopStoppedCv; // Whether wakeup AP is required for executing tasks. std::atomic<bool> mWakeupRequired = true; // Whether we currently have an active long-live connection to deliver remote tasks. std::atomic<bool> mRemoteTaskConnectionAlive = false; std::mutex mLock; bool mServerStopped GUARDED_BY(mLock); bool mGeneratingFakeTask GUARDED_BY(mLock); // Thread-safe. For test impl only. FakeTaskGenerator mFakeTaskGenerator; // Thread-sfae. TaskQueue mTaskQueue; void fakeTaskGenerateLoop(); void wakeupApplicationProcessor(); void fakeTaskGenerateLoop(const std::string& clientId); void injectTaskResponse(const GetRemoteTasksResponse& response); }; } // namespace remoteaccess Loading
automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp +63 −24 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ #include "TestWakeupClientServiceImpl.h" #include "ApPowerControl.h" #include <android-base/stringprintf.h> #include <inttypes.h> #include <utils/Looper.h> Loading @@ -44,12 +42,10 @@ constexpr int64_t KTaskTimeoutInMs = 20'000; } // namespace GetRemoteTasksResponse FakeTaskGenerator::generateTask() { int clientId = mCurrentClientId++; GetRemoteTasksResponse FakeTaskGenerator::generateTask(const std::string& clientId) { GetRemoteTasksResponse response; response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA))); std::string clientIdStr = StringPrintf("%d", clientId); response.set_clientid(clientIdStr); response.set_data(reinterpret_cast<const char*>(DATA), sizeof(DATA)); response.set_clientid(clientId); return response; } Loading Loading @@ -165,38 +161,68 @@ void TaskQueue::handleTaskTimeout() { } } TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() { mThread = std::thread([this] { fakeTaskGenerateLoop(); }); } TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {} TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() { { std::lock_guard<std::mutex> lockGuard(mLock); } mTaskQueue.stopWait(); stopGeneratingFakeTask(); } void TestWakeupClientServiceImpl::injectTask(const std::string& taskData, const std::string& clientId) { GetRemoteTasksResponse response; response.set_data(taskData); response.set_clientid(clientId); injectTaskResponse(response); } void TestWakeupClientServiceImpl::injectTaskResponse(const GetRemoteTasksResponse& response) { printf("Received a new task\n"); mTaskQueue.add(response); if (mWakeupRequired) { wakeupApplicationProcessor(); } } void TestWakeupClientServiceImpl::startGeneratingFakeTask(const std::string& clientId) { std::lock_guard<std::mutex> lockGuard(mLock); if (mGeneratingFakeTask) { printf("Fake task is already being generated\n"); return; } mGeneratingFakeTask = true; mThread = std::thread([this, clientId] { fakeTaskGenerateLoop(clientId); }); printf("Started generating fake tasks\n"); } void TestWakeupClientServiceImpl::stopGeneratingFakeTask() { { std::lock_guard<std::mutex> lockGuard(mLock); mServerStopped = true; mServerStoppedCv.notify_all(); if (!mGeneratingFakeTask) { printf("Fake task is not being generated, do nothing\n"); return; } mTaskLoopStoppedCv.notify_all(); mGeneratingFakeTask = false; } mTaskQueue.stopWait(); if (mThread.joinable()) { mThread.join(); } printf("Stopped generating fake tasks\n"); } void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() { void TestWakeupClientServiceImpl::fakeTaskGenerateLoop(const std::string& clientId) { // In actual implementation, this should communicate with the remote server and receives tasks // from it. Here we simulate receiving one remote task every {kTaskIntervalInMs}ms. while (true) { mTaskQueue.add(mFakeTaskGenerator.generateTask()); printf("Received a new task\n"); if (mWakeupRequired) { wakeupApplicationProcessor(); } injectTaskResponse(mFakeTaskGenerator.generateTask(clientId)); printf("Sleeping for %d seconds until next task\n", kTaskIntervalInMs); std::unique_lock lk(mLock); if (mServerStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] { if (mTaskLoopStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] { ScopedLockAssertion lockAssertion(mLock); return mServerStopped; return !mGeneratingFakeTask; })) { // If the stopped flag is set, we are quitting, exit the loop. return; Loading @@ -208,6 +234,7 @@ Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context, const GetRemoteTasksRequest* request, ServerWriter<GetRemoteTasksResponse>* writer) { printf("GetRemoteTasks called\n"); mRemoteTaskConnectionAlive = true; while (true) { mTaskQueue.waitForTask(); Loading @@ -226,16 +253,19 @@ Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context, // The task failed to be sent, add it back to the queue. The order might change, but // it is okay. mTaskQueue.add(response); mRemoteTaskConnectionAlive = false; return Status::CANCELLED; } } } mRemoteTaskConnectionAlive = false; return Status::OK; } Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context, const NotifyWakeupRequiredRequest* request, NotifyWakeupRequiredResponse* response) { printf("NotifyWakeupRequired called\n"); if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue.isEmpty()) { // If wakeup is now required and previously not required, this means we have finished // shutting down the device. If there are still pending tasks, try waking up AP again Loading @@ -243,11 +273,20 @@ Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context, wakeupApplicationProcessor(); } mWakeupRequired = request->iswakeuprequired(); if (mWakeupRequired) { // We won't know the connection is down unless we try to send a task over. If wakeup is // required, the connection is very likely already down. mRemoteTaskConnectionAlive = false; } return Status::OK; } void TestWakeupClientServiceImpl::wakeupApplicationProcessor() { wakeupAp(); bool TestWakeupClientServiceImpl::isWakeupRequired() { return mWakeupRequired; } bool TestWakeupClientServiceImpl::isRemoteTaskConnectionAlive() { return mRemoteTaskConnectionAlive; } } // namespace remoteaccess Loading