diff --git a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h index 9aabad6573..b18986adac 100644 --- a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h +++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h @@ -105,6 +105,8 @@ class RemoteAccessService size_t mRetryWaitInMs = 10'000; std::shared_ptr mDebugCallback; + std::thread mInjectDebugTaskThread; + void runTaskLoop(); void maybeStartTaskLoop(); void maybeStopTaskLoop(); @@ -116,6 +118,8 @@ class RemoteAccessService void printCurrentStatus(int fd); std::string clientIdToTaskCountToStringLocked() REQUIRES(mLock); void debugInjectTask(int fd, std::string_view clientId, std::string_view taskData); + void debugInjectTaskNextReboot(int fd, std::string_view clientId, std::string_view taskData, + const char* latencyInSecStr); void updateGrpcConnected(bool connected); android::base::Result deliverRemoteTaskThroughCallback(const std::string& clientId, std::string_view taskData); diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp index bbda9df759..dbe8150124 100644 --- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp +++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp @@ -18,12 +18,16 @@ #include #include +#include #include #include #include #include +#include #include #include +#include +#include #include namespace android { @@ -37,6 +41,7 @@ using ::aidl::android::hardware::automotive::remoteaccess::ApState; using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback; using ::aidl::android::hardware::automotive::vehicle::VehicleProperty; using ::android::base::Error; +using ::android::base::ParseInt; using ::android::base::Result; using ::android::base::ScopedLockAssertion; using ::android::base::StringAppendF; @@ -57,8 +62,12 @@ constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback"; constexpr char COMMAND_SHOW_TASK[] = "--show-task"; constexpr char COMMAND_GET_VEHICLE_ID[] = "--get-vehicle-id"; constexpr char COMMAND_INJECT_TASK[] = "--inject-task"; +constexpr char COMMAND_INJECT_TASK_NEXT_REBOOT[] = "--inject-task-next-reboot"; constexpr char COMMAND_STATUS[] = "--status"; +constexpr char DEBUG_TASK_FOLDER[] = "/data/local/tests"; +constexpr char DEBUG_TASK_FILE[] = "/data/local/tests/debugTask"; + std::vector stringToBytes(std::string_view s) { const char* data = s.data(); return std::vector(data, data + s.size()); @@ -92,10 +101,43 @@ std::string boolToString(bool x) { } // namespace RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub) - : mGrpcStub(grpcStub){}; + : mGrpcStub(grpcStub) { + std::ifstream debugTaskFile; + debugTaskFile.open(DEBUG_TASK_FILE, std::ios::in); + if (!debugTaskFile.is_open()) { + ALOGD("No debug task available"); + return; + } + + char buffer[1024] = {}; + debugTaskFile.getline(buffer, sizeof(buffer)); + std::string clientId = std::string(buffer); + debugTaskFile.getline(buffer, sizeof(buffer)); + std::string taskData = std::string(buffer); + int latencyInSec; + debugTaskFile >> latencyInSec; + debugTaskFile.close(); + + ALOGD("Task for client: %s, data: [%s], latency: %d\n", clientId.c_str(), taskData.c_str(), + latencyInSec); + + mInjectDebugTaskThread = std::thread([this, clientId, taskData, latencyInSec] { + std::this_thread::sleep_for(std::chrono::seconds(latencyInSec)); + if (auto result = deliverRemoteTaskThroughCallback(clientId, taskData); !result.ok()) { + ALOGE("Failed to inject debug task, clientID: %s, taskData: %s, error: %s", + clientId.c_str(), taskData.c_str(), result.error().message().c_str()); + return; + } + ALOGD("Task for client: %s, data: [%s] successfully injected\n", clientId.c_str(), + taskData.c_str()); + }); +} RemoteAccessService::~RemoteAccessService() { maybeStopTaskLoop(); + if (mInjectDebugTaskThread.joinable()) { + mInjectDebugTaskThread.join(); + } } void RemoteAccessService::maybeStartTaskLoop() { @@ -286,9 +328,12 @@ void RemoteAccessService::dumpHelp(int fd) { "%s: Show tasks received by debug callback\n" "%s: Get vehicle id\n" "%s [client_id] [task_data]: Inject a task\n" + "%s [client_id] [task_data] [latencyInSec]: " + "Inject a task on next reboot after latencyInSec seconds\n" "%s: Show status\n", COMMAND_SET_AP_STATE, COMMAND_START_DEBUG_CALLBACK, COMMAND_STOP_DEBUG_CALLBACK, - COMMAND_SHOW_TASK, COMMAND_GET_VEHICLE_ID, COMMAND_INJECT_TASK, COMMAND_STATUS); + COMMAND_SHOW_TASK, COMMAND_GET_VEHICLE_ID, COMMAND_INJECT_TASK, + COMMAND_INJECT_TASK_NEXT_REBOOT, COMMAND_STATUS); } binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) { @@ -365,6 +410,12 @@ binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t nu return STATUS_OK; } debugInjectTask(fd, args[1], args[2]); + } else if (!strcmp(args[0], COMMAND_INJECT_TASK_NEXT_REBOOT)) { + if (numArgs < 4) { + dumpHelp(fd); + return STATUS_OK; + } + debugInjectTaskNextReboot(fd, args[1], args[2], args[3]); } else if (!strcmp(args[0], COMMAND_STATUS)) { printCurrentStatus(fd); } else { @@ -389,13 +440,41 @@ void RemoteAccessService::debugInjectTask(int fd, std::string_view clientId, std::string_view taskData) { std::string clientIdCopy = std::string(clientId); if (auto result = deliverRemoteTaskThroughCallback(clientIdCopy, taskData); !result.ok()) { - dprintf(fd, "Failed to inject task: %s", result.error().message().c_str()); + dprintf(fd, "Failed to inject task: %s\n", result.error().message().c_str()); return; } dprintf(fd, "Task for client: %s, data: [%s] successfully injected\n", clientId.data(), taskData.data()); } +void RemoteAccessService::debugInjectTaskNextReboot(int fd, std::string_view clientId, + std::string_view taskData, + const char* latencyInSecStr) { + int latencyInSec; + if (!ParseInt(latencyInSecStr, &latencyInSec)) { + dprintf(fd, "The input latency in second is not a valid integer"); + return; + } + std::ofstream debugTaskFile; + debugTaskFile.open(DEBUG_TASK_FILE, std::ios::out); + if (!debugTaskFile.is_open()) { + dprintf(fd, + "Failed to open debug task file, please run the command: " + "'adb shell touch %s' first\n", + DEBUG_TASK_FILE); + return; + } + if (taskData.find("\n") != std::string::npos) { + dprintf(fd, "Task data must not contain newline\n"); + return; + } + debugTaskFile << clientId << "\n" << taskData << "\n" << latencyInSec; + debugTaskFile.close(); + dprintf(fd, + "Task with clientId: %s, task data: %s, latency: %d sec scheduled for next reboot\n", + clientId.data(), taskData.data(), latencyInSec); +} + std::string RemoteAccessService::clientIdToTaskCountToStringLocked() { // Print the table header std::string output = "| ClientId | Count |\n";