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

Commit dc54b8c2 authored by Yu Shan's avatar Yu Shan
Browse files

Add debug command to remote access HAL.

Add debug command to test remote access HAL.

Bug: 241483300
Test: Follow:
change file sytem to read-write.
m -j TestWakeupClientServer
adb push
out/target/product/emulator_car64_x86_64/vendor/bin/TestWakeupClientServer
/vendor/bin

In one adb shell:
/vendor/bin/TestWakeupClientServer

In another shell:
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --start-debug-callback
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task
[should show no tasks]
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --ready-for-remote-task 1
[wait for 5s]
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task
[should see all the tasks from client ID 1]
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --ready-for-remote-task 0
[wait for 5s]
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task
[should see no new tasks]
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default
--ready-for-remote-task 1
dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task
[should see new tasks]

Change-Id: I551bf9ab5b55c4de9d8382d69bd5078ec62cad51
parent a725df46
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ cc_binary {
        "RemoteAccessService",
    ],
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "liblog",
        "libutils",
@@ -56,6 +57,7 @@ cc_library {
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "liblog",
        "libutils",
        "libgrpc++",
+30 −0
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@

#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteAccess.h>
#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
#include <aidl/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.h>
#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
#include <utils/SystemClock.h>
#include <wakeup_client.grpc.pb.h>

#include <string>
@@ -30,6 +33,27 @@ namespace hardware {
namespace automotive {
namespace remoteaccess {

// A IRemoteTaskCallback implementation for debug purpose.
class DebugRemoteTaskCallback final
    : public aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback {
  public:
    DebugRemoteTaskCallback() { mStartTimeMillis = android::uptimeMillis(); };

    ndk::ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
                                             const std::vector<uint8_t>& data) override;
    std::string printTasks();

  private:
    struct TaskData {
        std::string clientId;
        std::vector<uint8_t> data;
    };

    std::mutex mLock;
    int64_t mStartTimeMillis;
    std::vector<TaskData> mTasks;
};

class RemoteAccessService
    : public aidl::android::hardware::automotive::remoteaccess::BnRemoteAccess {
  public:
@@ -51,10 +75,14 @@ class RemoteAccessService
    ndk::ScopedAStatus notifyApStateChange(
            const aidl::android::hardware::automotive::remoteaccess::ApState& newState) override;

    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

  private:
    // For testing.
    friend class RemoteAccessServiceUnitTest;

    static bool checkDumpPermission();

    WakeupClient::StubInterface* mGrpcStub;
    std::thread mThread;
    std::mutex mLock;
@@ -69,12 +97,14 @@ class RemoteAccessService
    bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
    // Default wait time before retry connecting to remote access client is 10s.
    size_t mRetryWaitInMs = 10'000;
    std::shared_ptr<DebugRemoteTaskCallback> mDebugCallback;

    void runTaskLoop();
    void maybeStartTaskLoop();
    void maybeStopTaskLoop();

    void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
    void dumpHelp(int fd);
};

}  // namespace remoteaccess
+125 −1
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

#include "RemoteAccessService.h"

#include <android-base/stringprintf.h>
#include <android/binder_status.h>
#include <grpc++/grpc++.h>
#include <private/android_filesystem_config.h>
#include <utils/Log.h>
#include <chrono>
#include <thread>
@@ -32,6 +34,8 @@ namespace {
using ::aidl::android::hardware::automotive::remoteaccess::ApState;
using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
using ::android::base::ScopedLockAssertion;
using ::android::base::StringAppendF;
using ::android::base::StringPrintf;
using ::grpc::ClientContext;
using ::grpc::ClientReaderInterface;
using ::grpc::Status;
@@ -39,6 +43,10 @@ using ::grpc::StatusCode;
using ::ndk::ScopedAStatus;

const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
constexpr char COMMAND_SET_AP_STATE[] = "--set-ap-state";
constexpr char COMMAND_START_DEBUG_CALLBACK[] = "--start-debug-callback";
constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback";
constexpr char COMMAND_SHOW_TASK[] = "--show-task";

std::vector<uint8_t> stringToBytes(const std::string& s) {
    const char* data = s.data();
@@ -50,6 +58,18 @@ ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string&
            status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
}

std::string printBytes(const std::vector<uint8_t>& bytes) {
    std::string s;
    for (size_t i = 0; i < bytes.size(); i++) {
        StringAppendF(&s, "%02x", bytes[i]);
    }
    return s;
}

bool checkBoolFlag(const char* flag) {
    return !strcmp(flag, "1") || !strcmp(flag, "0");
}

}  // namespace

RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
@@ -154,7 +174,7 @@ ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServi
}

ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
        [[maybe_unused]] const std::shared_ptr<IRemoteTaskCallback>& callback) {
        const std::shared_ptr<IRemoteTaskCallback>& callback) {
    std::lock_guard<std::mutex> lockGuard(mLock);
    mRemoteTaskCallback = callback;
    return ScopedAStatus::ok();
@@ -184,6 +204,110 @@ ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState)
    return ScopedAStatus::ok();
}

bool RemoteAccessService::checkDumpPermission() {
    uid_t uid = AIBinder_getCallingUid();
    return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
}

void RemoteAccessService::dumpHelp(int fd) {
    dprintf(fd, "%s",
            (std::string("RemoteAccess HAL debug interface, Usage: \n") + COMMAND_SET_AP_STATE +
             " [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired)  Set the new AP state\n" +
             COMMAND_START_DEBUG_CALLBACK +
             " Start a debug callback that will record the received tasks\n" +
             COMMAND_STOP_DEBUG_CALLBACK + " Stop the debug callback\n" + COMMAND_SHOW_TASK +
             " Show tasks received by debug callback\n")
                    .c_str());
}

binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) {
    if (!checkDumpPermission()) {
        dprintf(fd, "Caller must be root, system or shell\n");
        return STATUS_PERMISSION_DENIED;
    }

    if (numArgs == 0) {
        dumpHelp(fd);
        return STATUS_OK;
    }

    if (!strcmp(args[0], COMMAND_SET_AP_STATE)) {
        if (numArgs < 3) {
            dumpHelp(fd);
            return STATUS_OK;
        }
        ApState apState = {};
        const char* remoteTaskFlag = args[1];
        if (!strcmp(remoteTaskFlag, "1") && !strcmp(remoteTaskFlag, "0")) {
            dumpHelp(fd);
            return STATUS_OK;
        }
        if (!checkBoolFlag(args[1])) {
            dumpHelp(fd);
            return STATUS_OK;
        }
        if (!strcmp(args[1], "1")) {
            apState.isReadyForRemoteTask = true;
        }
        if (!checkBoolFlag(args[2])) {
            dumpHelp(fd);
            return STATUS_OK;
        }
        if (!strcmp(args[2], "1")) {
            apState.isWakeupRequired = true;
        }
        auto status = notifyApStateChange(apState);
        if (!status.isOk()) {
            dprintf(fd, "Failed to set AP state, code: %d, error: %s\n", status.getStatus(),
                    status.getMessage());
        } else {
            dprintf(fd, "successfully set the new AP state\n");
        }
    } else if (!strcmp(args[0], COMMAND_START_DEBUG_CALLBACK)) {
        mDebugCallback = ndk::SharedRefBase::make<DebugRemoteTaskCallback>();
        setRemoteTaskCallback(mDebugCallback);
        dprintf(fd, "Debug callback registered\n");
    } else if (!strcmp(args[0], COMMAND_STOP_DEBUG_CALLBACK)) {
        if (mDebugCallback) {
            mDebugCallback.reset();
        }
        clearRemoteTaskCallback();
        dprintf(fd, "Debug callback unregistered\n");
    } else if (!strcmp(args[0], COMMAND_SHOW_TASK)) {
        if (mDebugCallback) {
            dprintf(fd, "%s", mDebugCallback->printTasks().c_str());
        } else {
            dprintf(fd, "Debug callback is not currently used, use \"%s\" first.\n",
                    COMMAND_START_DEBUG_CALLBACK);
        }
    } else {
        dumpHelp(fd);
    }

    return STATUS_OK;
}

ScopedAStatus DebugRemoteTaskCallback::onRemoteTaskRequested(const std::string& clientId,
                                                             const std::vector<uint8_t>& data) {
    std::lock_guard<std::mutex> lockGuard(mLock);
    mTasks.push_back({
            .clientId = clientId,
            .data = data,
    });
    return ScopedAStatus::ok();
}

std::string DebugRemoteTaskCallback::printTasks() {
    std::lock_guard<std::mutex> lockGuard(mLock);
    std::string s = StringPrintf("Received %zu tasks in %f seconds", mTasks.size(),
                                 (android::uptimeMillis() - mStartTimeMillis) / 1000.);
    for (size_t i = 0; i < mTasks.size(); i++) {
        StringAppendF(&s, "Client Id: %s, Data: %s\n", mTasks[i].clientId.c_str(),
                      printBytes(mTasks[i].data).c_str());
    }
    return s;
}

}  // namespace remoteaccess
}  // namespace automotive
}  // namespace hardware
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ cc_test {
        "RemoteAccessService",
    ],
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "liblog",
        "libutils",