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

Commit a84d10c2 authored by Yu Shan's avatar Yu Shan Committed by Android (Google) Code Review
Browse files

Merge changes Ia9f1d7fa,I2d363aa2 into main

* changes:
  Implement scheduleTask in TestWakeupClientService.
  Implement ScheduleTask API using grpc.
parents 2c10ac81 bfc29b24
Loading
Loading
Loading
Loading
+95 −0
Original line number Diff line number Diff line
@@ -55,6 +55,31 @@ class MockGrpcClientStub : public WakeupClient::StubInterface {
        return Status::OK;
    }

    Status ScheduleTask(ClientContext* context, const ScheduleTaskRequest& request,
                        ScheduleTaskResponse* response) {
        return Status::OK;
    }

    Status UnscheduleTask(ClientContext* context, const UnscheduleTaskRequest& request,
                          UnscheduleTaskResponse* response) {
        return Status::OK;
    }

    Status UnscheduleAllTasks(ClientContext* context, const UnscheduleAllTasksRequest& request,
                              UnscheduleAllTasksResponse* response) {
        return Status::OK;
    }

    Status IsTaskScheduled(ClientContext* context, const IsTaskScheduledRequest& request,
                           IsTaskScheduledResponse* response) {
        return Status::OK;
    }

    Status GetAllScheduledTasks(ClientContext* context, const GetAllScheduledTasksRequest& request,
                                GetAllScheduledTasksResponse* response) {
        return Status::OK;
    }

    // Async methods which we do not care.
    ClientAsyncReaderInterface<GetRemoteTasksResponse>* AsyncGetRemoteTasksRaw(
            [[maybe_unused]] ClientContext* context,
@@ -83,6 +108,76 @@ class MockGrpcClientStub : public WakeupClient::StubInterface {
                                        [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* AsyncScheduleTaskRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const ScheduleTaskRequest& request,
            [[maybe_unused]] CompletionQueue* cq) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<ScheduleTaskResponse>* PrepareAsyncScheduleTaskRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const ScheduleTaskRequest& request,
            [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* AsyncUnscheduleTaskRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const UnscheduleTaskRequest& request,
            [[maybe_unused]] CompletionQueue* cq) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<UnscheduleTaskResponse>* PrepareAsyncUnscheduleTaskRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const UnscheduleTaskRequest& request,
            [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>* AsyncUnscheduleAllTasksRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const UnscheduleAllTasksRequest& request,
            [[maybe_unused]] CompletionQueue* cq) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<UnscheduleAllTasksResponse>*
    PrepareAsyncUnscheduleAllTasksRaw([[maybe_unused]] ClientContext* context,
                                      [[maybe_unused]] const UnscheduleAllTasksRequest& request,
                                      [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* AsyncIsTaskScheduledRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const IsTaskScheduledRequest& request,
            [[maybe_unused]] CompletionQueue* cq) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<IsTaskScheduledResponse>* PrepareAsyncIsTaskScheduledRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const IsTaskScheduledRequest& request,
            [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>* AsyncGetAllScheduledTasksRaw(
            [[maybe_unused]] ClientContext* context,
            [[maybe_unused]] const GetAllScheduledTasksRequest& request,
            [[maybe_unused]] CompletionQueue* cq) {
        return nullptr;
    }

    ClientAsyncResponseReaderInterface<GetAllScheduledTasksResponse>*
    PrepareAsyncGetAllScheduledTasksRaw([[maybe_unused]] ClientContext* context,
                                        [[maybe_unused]] const GetAllScheduledTasksRequest& request,
                                        [[maybe_unused]] CompletionQueue* c) {
        return nullptr;
    }
};

}  // namespace remoteaccess
+97 −0
Original line number Diff line number Diff line
@@ -18,6 +18,12 @@ syntax = "proto3";

package android.hardware.automotive.remoteaccess;

enum ErrorCode {
    OK = 0;
    UNSPECIFIED = 1;
    INVALID_ARG = 2;
}

/**
 * Service provided by a wakeup client running on TCU.
 */
@@ -50,6 +56,50 @@ service WakeupClient {
     * to wake up AP.
     */
    rpc NotifyWakeupRequired(NotifyWakeupRequiredRequest) returns (NotifyWakeupRequiredResponse) {}

    /**
     * Schedules a task to be executed later even when the vehicle is off.
     *
     * <p>This sends a scheduled task message to a device external to Android so that the device
     * can wake up Android and deliver the task through {@link IRemoteTaskCallback}.
     *
     * <p>Note that the scheduled task execution is on a best-effort basis. Multiple situations
     * might cause the task not to execute successfully:
     *
     * <ul>
     * <li>The vehicle is low on battery and the other device decides not to wake up Android.
     * <li>User turns off vehicle while the task is executing.
     * <li>The task logic itself fails.
     *
     * <p>Must return a response with error code: {@code INVALID_ARG} if a pending schedule with the
     * same {@code scheduleId} for this client exists.
     */
    rpc ScheduleTask(ScheduleTaskRequest) returns (ScheduleTaskResponse) {}

    /**
     * Unschedules a scheduled task.
     *
     * <p>Does nothing if a pending schedule with {@code clientId} and {@code scheduleId} does not
     * exist.
     */
    rpc UnscheduleTask(UnscheduleTaskRequest) returns (UnscheduleTaskResponse) {}

    /**
     * Unschedules all scheduled tasks for the client.
     */
    rpc UnscheduleAllTasks(UnscheduleAllTasksRequest) returns (UnscheduleAllTasksResponse) {}

    /**
     * Returns whether the specified task is scheduled.
     */
    rpc IsTaskScheduled(IsTaskScheduledRequest) returns (IsTaskScheduledResponse) {}

    /**
     * Gets all pending scheduled tasks for the client.
     *
     * <p>The finished scheduled tasks will not be included.
     */
    rpc GetAllScheduledTasks(GetAllScheduledTasksRequest) returns (GetAllScheduledTasksResponse) {}
}

message GetRemoteTasksRequest {}
@@ -64,3 +114,50 @@ message NotifyWakeupRequiredRequest {
}

message NotifyWakeupRequiredResponse {}

message ScheduleTaskRequest {
    GrpcScheduleInfo scheduleInfo = 1;
}

message ScheduleTaskResponse {
    ErrorCode errorCode = 1;
}

message GrpcScheduleInfo {
    string clientId = 1;
    string scheduleId = 2;
    bytes data = 3;
    int32 count = 4;
    int64 startTimeInEpochSeconds = 5;
    int64 periodicInSeconds = 6;
}

message UnscheduleTaskRequest {
    string clientId = 1;
    string scheduleId = 2;
}

message UnscheduleTaskResponse {}

message UnscheduleAllTasksRequest {
    string clientId = 1;
}

message UnscheduleAllTasksResponse {}

message IsTaskScheduledRequest {
    string clientId = 1;
    string scheduleId = 2;
}

message IsTaskScheduledResponse {
    bool isTaskScheduled = 1;
}

message GetAllScheduledTasksRequest {
    string clientId = 1;
}

message GetAllScheduledTasksResponse {
    repeated GrpcScheduleInfo allScheduledTasks = 1;
}
+84 −16
Original line number Diff line number Diff line
@@ -314,38 +314,106 @@ ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState)
    return ScopedAStatus::ok();
}

ScopedAStatus RemoteAccessService::isTaskScheduleSupported([[maybe_unused]] bool* out) {
    // TODO(b/297271235): implement this.
ScopedAStatus RemoteAccessService::isTaskScheduleSupported(bool* out) {
    *out = true;
    return ScopedAStatus::ok();
}

ScopedAStatus RemoteAccessService::scheduleTask([[maybe_unused]] const ScheduleInfo& scheduleInfo) {
    // TODO(b/297271235): implement this.
ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo) {
    ClientContext context;
    ScheduleTaskRequest request = {};
    ScheduleTaskResponse response = {};
    request.mutable_scheduleinfo()->set_clientid(scheduleInfo.clientId);
    request.mutable_scheduleinfo()->set_scheduleid(scheduleInfo.scheduleId);
    request.mutable_scheduleinfo()->set_data(scheduleInfo.taskData.data(),
                                             scheduleInfo.taskData.size());
    request.mutable_scheduleinfo()->set_count(scheduleInfo.count);
    request.mutable_scheduleinfo()->set_starttimeinepochseconds(
            scheduleInfo.startTimeInEpochSeconds);
    request.mutable_scheduleinfo()->set_periodicinseconds(scheduleInfo.periodicInSeconds);
    Status status = mGrpcStub->ScheduleTask(&context, request, &response);
    if (!status.ok()) {
        return rpcStatusToScopedAStatus(status, "Failed to call ScheduleTask");
    }
    int errorCode = response.errorcode();
    switch (errorCode) {
        case ErrorCode::OK:
            return ScopedAStatus::ok();
        case ErrorCode::INVALID_ARG:
            return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
        default:
            // Should not happen.
            return ScopedAStatus::fromServiceSpecificErrorWithMessage(
                    -1, ("Got unknown error code: " + ErrorCode_Name(errorCode) +
                         " from remote access HAL")
                                .c_str());
    }
}

ScopedAStatus RemoteAccessService::unscheduleTask([[maybe_unused]] const std::string& clientId,
                                                  [[maybe_unused]] const std::string& scheduleId) {
    // TODO(b/297271235): implement this.
ScopedAStatus RemoteAccessService::unscheduleTask(const std::string& clientId,
                                                  const std::string& scheduleId) {
    ClientContext context;
    UnscheduleTaskRequest request = {};
    UnscheduleTaskResponse response = {};
    request.set_clientid(clientId);
    request.set_scheduleid(scheduleId);
    Status status = mGrpcStub->UnscheduleTask(&context, request, &response);
    if (!status.ok()) {
        return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleTask");
    }
    return ScopedAStatus::ok();
}

ScopedAStatus RemoteAccessService::unscheduleAllTasks(
        [[maybe_unused]] const std::string& clientId) {
    // TODO(b/297271235): implement this.
ScopedAStatus RemoteAccessService::unscheduleAllTasks(const std::string& clientId) {
    ClientContext context;
    UnscheduleAllTasksRequest request = {};
    UnscheduleAllTasksResponse response = {};
    request.set_clientid(clientId);
    Status status = mGrpcStub->UnscheduleAllTasks(&context, request, &response);
    if (!status.ok()) {
        return rpcStatusToScopedAStatus(status, "Failed to call UnscheduleAllTasks");
    }
    return ScopedAStatus::ok();
}

ScopedAStatus RemoteAccessService::isTaskScheduled([[maybe_unused]] const std::string& clientId,
                                                   [[maybe_unused]] const std::string& scheduleId,
                                                   [[maybe_unused]] bool* out) {
    // TODO(b/297271235): implement this.
ScopedAStatus RemoteAccessService::isTaskScheduled(const std::string& clientId,
                                                   const std::string& scheduleId, bool* out) {
    ClientContext context;
    IsTaskScheduledRequest request = {};
    IsTaskScheduledResponse response = {};
    request.set_clientid(clientId);
    request.set_scheduleid(scheduleId);
    Status status = mGrpcStub->IsTaskScheduled(&context, request, &response);
    if (!status.ok()) {
        return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled");
    }
    *out = response.istaskscheduled();
    return ScopedAStatus::ok();
}

ScopedAStatus RemoteAccessService::getAllScheduledTasks(const std::string& clientId,
                                                        std::vector<ScheduleInfo>* out) {
    // TODO(b/297271235): implement this.
    ClientContext context;
    GetAllScheduledTasksRequest request = {};
    GetAllScheduledTasksResponse response = {};
    request.set_clientid(clientId);
    Status status = mGrpcStub->GetAllScheduledTasks(&context, request, &response);
    if (!status.ok()) {
        return rpcStatusToScopedAStatus(status, "Failed to call isTaskScheduled");
    }
    out->clear();
    for (int i = 0; i < response.allscheduledtasks_size(); i++) {
        const GrpcScheduleInfo& rpcScheduleInfo = response.allscheduledtasks(i);
        ScheduleInfo scheduleInfo = {
                .clientId = rpcScheduleInfo.clientid(),
                .scheduleId = rpcScheduleInfo.scheduleid(),
                .taskData = stringToBytes(rpcScheduleInfo.data()),
                .count = rpcScheduleInfo.count(),
                .startTimeInEpochSeconds = rpcScheduleInfo.starttimeinepochseconds(),
                .periodicInSeconds = rpcScheduleInfo.periodicinseconds(),
        };
        out->push_back(std::move(scheduleInfo));
    }
    return ScopedAStatus::ok();
}

+227 −0

File changed.

Preview size limit exceeded, changes collapsed.

+24 −0
Original line number Diff line number Diff line
@@ -61,3 +61,27 @@ cc_binary_host {
        "-DHOST",
    ],
}

cc_test_host {
    name: "TestWakeupClientServerHostUnitTest",
    srcs: [
        "test/*.cpp",
        "src/TestWakeupClientServiceImpl.cpp",
    ],
    local_include_dirs: ["include"],
    shared_libs: [
        "libbase",
        "libutils",
        "libgrpc++",
        "libprotobuf-cpp-full",
    ],
    static_libs: [
        "libgtest",
    ],
    whole_static_libs: [
        "wakeup_client_protos",
    ],
    cflags: [
        "-Wno-unused-parameter",
    ],
}
Loading