Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6dbb919 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement a host side TestWakeupClientService." into main

parents 23ddfba4 3a129d7a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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\"",
    ],
}

+3 −4
Original line number Diff line number Diff line
@@ -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
@@ -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());
+21 −1
Original line number Diff line number Diff line
@@ -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",
    ],
}
+39 −9
Original line number Diff line number Diff line
@@ -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};
};

@@ -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();

@@ -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
+63 −24
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

#include "TestWakeupClientServiceImpl.h"

#include "ApPowerControl.h"

#include <android-base/stringprintf.h>
#include <inttypes.h>
#include <utils/Looper.h>
@@ -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;
}

@@ -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;
@@ -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();

@@ -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
@@ -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