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

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

Merge changes from topic "vhal_grpc" into main

* changes:
  Use runtime config file instead of compile flag.
  Move FakeVehicleHardwareUnitTest to auto-presumbmit.
  Support Enter Garage Mode in remote access HAL.
parents c1f2146e e0ed3508
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -52,11 +52,6 @@ cc_binary {
    defaults: ["remote-access-hal-defaults"],
    vintf_fragments: ["remoteaccess-default-service.xml"],
    init_rc: ["remoteaccess-default-service.rc"],
    cflags: [
        // Uncomment this if running on emulator and connecting to a local grpc server
        // running on host 127.0.0.1:50051 (TestWakeupClientServerHost)
        // "-DGRPC_SERVICE_ADDRESS=\"10.0.2.2:50051\"",
    ],
}

cc_binary {
@@ -64,10 +59,6 @@ cc_binary {
    defaults: ["remote-access-hal-defaults"],
    vintf_fragments: ["remoteaccess-default-service.xml"],
    init_rc: ["remoteaccess-tcu-test-service.rc"],
    cflags: [
        "-DGRPC_SERVICE_ADDRESS=\"10.10.10.1:50051\"",
        "-DGRPC_SERVICE_IFNAME=\"eth1\"",
    ],
}

cc_library {
+28 −0
Original line number Diff line number Diff line
@@ -124,6 +124,11 @@ message ScheduleTaskResponse {
    ErrorCode errorCode = 1;
}

enum ScheduleTaskType {
    CUSTOM = 0;
    ENTER_GARAGE_MODE = 1;
}

message GrpcScheduleInfo {
    string clientId = 1;
    string scheduleId = 2;
@@ -131,6 +136,7 @@ message GrpcScheduleInfo {
    int32 count = 4;
    int64 startTimeInEpochSeconds = 5;
    int64 periodicInSeconds = 6;
    ScheduleTaskType taskType = 7;
}

message UnscheduleTaskRequest {
@@ -162,3 +168,25 @@ message GetAllPendingScheduledTasksRequest {
message GetAllPendingScheduledTasksResponse {
    repeated GrpcScheduleInfo allScheduledTasks = 1;
}

/**
 * Service provided by a power controller unit.
 */
service PowerController {
    rpc IsVehicleInUse(IsVehicleInUseRequest) returns (IsVehicleInUseResponse) {}

    rpc GetApPowerBootupReason(GetApPowerBootupReasonRequest)
            returns (GetApPowerBootupReasonResponse) {}
}

message IsVehicleInUseRequest {}

message IsVehicleInUseResponse {
    bool isVehicleInUse = 1;
}

message GetApPowerBootupReasonRequest {}

message GetApPowerBootupReasonResponse {
    int32 bootupReason = 1;
}
+55 −26
Original line number Diff line number Diff line
@@ -27,37 +27,66 @@
#include <libnetdevice/libnetdevice.h>
#include <stdlib.h>

namespace {

constexpr char GRPC_SERVICE_CONFIG_FILE[] = "/vendor/etc/automotive/powercontroller/serverconfig";
constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default";

void maybeGetGrpcServiceInfo(std::string* address, std::string* ifname) {
    std::ifstream ifs(GRPC_SERVICE_CONFIG_FILE);
    if (!ifs) {
        LOG(INFO) << "Cannot open grpc service config file at: " << GRPC_SERVICE_CONFIG_FILE
                  << ", assume no service is available";
        return;
    }
    int count = 0;
    while (ifs.good()) {
        std::string line;
        ifs >> line;
        // First line is address, second line, if present is ifname.
        if (count == 0) {
            *address = line;
        } else {
            *ifname = line;
            break;
        }
        count++;
    }
    ifs.close();
}

}  // namespace

int main(int /* argc */, char* /* argv */[]) {
    android::hardware::automotive::remoteaccess::WakeupClient::StubInterface* grpcStub = nullptr;
    std::string grpcServiceAddress = "";
    std::string grpcServiceIfname = "";
    maybeGetGrpcServiceInfo(&grpcServiceAddress, &grpcServiceIfname);

    std::unique_ptr<android::hardware::automotive::remoteaccess::WakeupClient::Stub> grpcStub;

#ifdef GRPC_SERVICE_ADDRESS
    LOG(INFO) << "Registering RemoteAccessService as service, server: " << GRPC_SERVICE_ADDRESS
    if (grpcServiceAddress != "") {
        LOG(INFO) << "Registering RemoteAccessService as service, server: " << grpcServiceAddress
                  << "...";
        grpc::ChannelArguments grpcargs = {};

#ifdef GRPC_SERVICE_IFNAME
        if (grpcServiceIfname != "") {
            grpcargs.SetSocketMutator(
                    android::hardware::automotive::remoteaccess::MakeBindToDeviceSocketMutator(
                    GRPC_SERVICE_IFNAME));
    LOG(DEBUG) << "GRPC_SERVICE_IFNAME specified as: " << GRPC_SERVICE_IFNAME;
    LOG(INFO) << "Waiting for interface: " << GRPC_SERVICE_IFNAME;
    android::netdevice::waitFor({GRPC_SERVICE_IFNAME},
                            grpcServiceIfname));
            LOG(DEBUG) << "grpcServiceIfname specified as: " << grpcServiceIfname;
            LOG(INFO) << "Waiting for interface: " << grpcServiceIfname;
            android::netdevice::waitFor({grpcServiceIfname},
                                        android::netdevice::WaitCondition::PRESENT_AND_UP);
    LOG(INFO) << "Waiting for interface: " << GRPC_SERVICE_IFNAME << " done";
#endif  // #ifdef GRPC_SERVICE_IFNAME
    auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials());
    auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);

    grpcStub = clientStub.get();

#else
    LOG(INFO) << "GRPC_SERVICE_ADDRESS is not defined, work in fake mode";
#endif  // #ifdef GRPC_SERVICE_ADDRESS
            LOG(INFO) << "Waiting for interface: " << grpcServiceIfname << " done";
        }
        auto channel = grpc::CreateChannel(grpcServiceAddress, grpc::InsecureChannelCredentials());
        grpcStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);
    } else {
        LOG(INFO) << "grpcServiceAddress is not defined, work in fake mode";
    }

    auto service = ndk::SharedRefBase::make<
            android::hardware::automotive::remoteaccess::RemoteAccessService>(grpcStub);
            android::hardware::automotive::remoteaccess::RemoteAccessService>(grpcStub.get());

    binder_exception_t err = AServiceManager_addService(service->asBinder().get(), SERVICE_NAME);
    if (err != EX_NONE) {
+4 −1
Original line number Diff line number Diff line
@@ -346,8 +346,8 @@ ndk::ScopedAStatus RemoteAccessService::getSupportedTaskTypesForScheduling(
        return ScopedAStatus::ok();
    }

    // TODO(b/316233421): support ENTER_GARAGE_MODE type.
    out->push_back(TaskType::CUSTOM);
    out->push_back(TaskType::ENTER_GARAGE_MODE);
    return ScopedAStatus::ok();
}

@@ -380,6 +380,8 @@ ScopedAStatus RemoteAccessService::scheduleTask(const ScheduleInfo& scheduleInfo
    }

    request.mutable_scheduleinfo()->set_clientid(scheduleInfo.clientId);
    request.mutable_scheduleinfo()->set_tasktype(
            static_cast<ScheduleTaskType>(scheduleInfo.taskType));
    request.mutable_scheduleinfo()->set_scheduleid(scheduleInfo.scheduleId);
    request.mutable_scheduleinfo()->set_data(scheduleInfo.taskData.data(),
                                             scheduleInfo.taskData.size());
@@ -485,6 +487,7 @@ ScopedAStatus RemoteAccessService::getAllPendingScheduledTasks(const std::string
        const GrpcScheduleInfo& rpcScheduleInfo = response.allscheduledtasks(i);
        ScheduleInfo scheduleInfo = {
                .clientId = rpcScheduleInfo.clientid(),
                .taskType = static_cast<TaskType>(rpcScheduleInfo.tasktype()),
                .scheduleId = rpcScheduleInfo.scheduleid(),
                .taskData = stringToBytes(rpcScheduleInfo.data()),
                .count = rpcScheduleInfo.count(),
+106 −16
Original line number Diff line number Diff line
@@ -30,6 +30,11 @@ namespace hardware {
namespace automotive {
namespace remoteaccess {

// The following are the same as VehicleApPowerBootupReason defined in VHAL.
constexpr int32_t BOOTUP_REASON_USER_POWER_ON = 0;
constexpr int32_t BOOTUP_REASON_SYSTEM_REMOTE_ACCESS = 2;
constexpr int32_t BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE = 3;

// A class to generate fake task for testing. Not required for real implementation. In real
// implementation, the task should come from remote task server. This class is thread-safe.
class FakeTaskGenerator final {
@@ -98,50 +103,57 @@ class TaskQueue final {
};

// forward-declaration
class TestWakeupClientServiceImpl;
class ServiceImpl;

class TaskScheduleMsgHandler final : public android::MessageHandler {
  public:
    TaskScheduleMsgHandler(TestWakeupClientServiceImpl* mImpl);
    TaskScheduleMsgHandler(ServiceImpl* impl);
    void handleMessage(const android::Message& message) override;

  private:
    TestWakeupClientServiceImpl* mImpl;
    ServiceImpl* mImpl;
};

class TestWakeupClientServiceImpl : public WakeupClient::Service {
class ServiceImpl {
  public:
    TestWakeupClientServiceImpl();
    ServiceImpl();

    ~TestWakeupClientServiceImpl();
    virtual ~ServiceImpl() = 0;

    // Stop the handling for all income requests. Prepare for shutdown.
    void stopServer();

    grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
                                grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
                                grpc::ServerWriter<GetRemoteTasksResponse>* writer);

    grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
                                      const NotifyWakeupRequiredRequest* request,
                                      NotifyWakeupRequiredResponse* response) override;
                                      NotifyWakeupRequiredResponse* response);

    grpc::Status ScheduleTask(grpc::ServerContext* context, const ScheduleTaskRequest* request,
                              ScheduleTaskResponse* response) override;
                              ScheduleTaskResponse* response);

    grpc::Status UnscheduleTask(grpc::ServerContext* context, const UnscheduleTaskRequest* request,
                                UnscheduleTaskResponse* response) override;
                                UnscheduleTaskResponse* response);

    grpc::Status UnscheduleAllTasks(grpc::ServerContext* context,
                                    const UnscheduleAllTasksRequest* request,
                                    UnscheduleAllTasksResponse* response) override;
                                    UnscheduleAllTasksResponse* response);

    grpc::Status IsTaskScheduled(grpc::ServerContext* context,
                                 const IsTaskScheduledRequest* request,
                                 IsTaskScheduledResponse* response) override;
                                 IsTaskScheduledResponse* response);

    grpc::Status GetAllPendingScheduledTasks(
            grpc::ServerContext* context, const GetAllPendingScheduledTasksRequest* request,
            GetAllPendingScheduledTasksResponse* response) override;
    grpc::Status GetAllPendingScheduledTasks(grpc::ServerContext* context,
                                             const GetAllPendingScheduledTasksRequest* request,
                                             GetAllPendingScheduledTasksResponse* response);

    grpc::Status IsVehicleInUse(grpc::ServerContext* context, const IsVehicleInUseRequest* request,
                                IsVehicleInUseResponse* response);

    grpc::Status GetApPowerBootupReason(grpc::ServerContext* context,
                                        const GetApPowerBootupReasonRequest* request,
                                        GetApPowerBootupReasonResponse* response);

    /**
     * Starts generating fake tasks for the specific client repeatedly.
@@ -177,7 +189,7 @@ class TestWakeupClientServiceImpl : public WakeupClient::Service {
     * 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;
    virtual void wakeupApplicationProcessor(int32_t bootupReason) = 0;

    /**
     * Cleans up a scheduled task info.
@@ -185,6 +197,16 @@ class TestWakeupClientServiceImpl : public WakeupClient::Service {
    void cleanupScheduledTaskLocked(const std::string& clientId, const std::string& scheduleId)
            REQUIRES(mLock);

    /**
     * Sets whether vehicle is in use.
     */
    void setVehicleInUse(bool vehicleInUse);

    /**
     * Sets the bootup reason.
     */
    void setBootupReason(int32_t bootupReason);

  private:
    friend class TaskScheduleMsgHandler;

@@ -218,6 +240,8 @@ class TestWakeupClientServiceImpl : public WakeupClient::Service {
    std::atomic<bool> mServerStopped = false;
    std::unordered_map<std::string, std::unordered_map<std::string, ScheduleInfo>>
            mInfoByScheduleIdByClientId GUARDED_BY(mLock);
    std::atomic<bool> mVehicleInUse = false;
    std::atomic<int32_t> mBootupReason = BOOTUP_REASON_USER_POWER_ON;

    // Thread-safe. For test impl only.
    FakeTaskGenerator mFakeTaskGenerator;
@@ -232,6 +256,72 @@ class TestWakeupClientServiceImpl : public WakeupClient::Service {
    void loop();
};

class WakeupClientServiceImpl : public WakeupClient::Service {
  public:
    WakeupClientServiceImpl(ServiceImpl* impl) { mImpl = impl; }

    grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
                                grpc::ServerWriter<GetRemoteTasksResponse>* writer) override {
        return mImpl->GetRemoteTasks(context, request, writer);
    }

    grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
                                      const NotifyWakeupRequiredRequest* request,
                                      NotifyWakeupRequiredResponse* response) override {
        return mImpl->NotifyWakeupRequired(context, request, response);
    }

    grpc::Status ScheduleTask(grpc::ServerContext* context, const ScheduleTaskRequest* request,
                              ScheduleTaskResponse* response) override {
        return mImpl->ScheduleTask(context, request, response);
    }

    grpc::Status UnscheduleTask(grpc::ServerContext* context, const UnscheduleTaskRequest* request,
                                UnscheduleTaskResponse* response) override {
        return mImpl->UnscheduleTask(context, request, response);
    }

    grpc::Status UnscheduleAllTasks(grpc::ServerContext* context,
                                    const UnscheduleAllTasksRequest* request,
                                    UnscheduleAllTasksResponse* response) override {
        return mImpl->UnscheduleAllTasks(context, request, response);
    }

    grpc::Status IsTaskScheduled(grpc::ServerContext* context,
                                 const IsTaskScheduledRequest* request,
                                 IsTaskScheduledResponse* response) override {
        return mImpl->IsTaskScheduled(context, request, response);
    }

    grpc::Status GetAllPendingScheduledTasks(
            grpc::ServerContext* context, const GetAllPendingScheduledTasksRequest* request,
            GetAllPendingScheduledTasksResponse* response) override {
        return mImpl->GetAllPendingScheduledTasks(context, request, response);
    }

  private:
    ServiceImpl* mImpl;
};

class PowerControllerServiceImpl : public PowerController::Service {
  public:
    PowerControllerServiceImpl(ServiceImpl* impl) { mImpl = impl; }

    grpc::Status IsVehicleInUse(grpc::ServerContext* context, const IsVehicleInUseRequest* request,
                                IsVehicleInUseResponse* response) override {
        return mImpl->IsVehicleInUse(context, request, response);
    }

    grpc::Status GetApPowerBootupReason(grpc::ServerContext* context,
                                        const GetApPowerBootupReasonRequest* request,
                                        GetApPowerBootupReasonResponse* response) override {
        return mImpl->GetApPowerBootupReason(context, request, response);
    }

  private:
    ServiceImpl* mImpl;
};

}  // namespace remoteaccess
}  // namespace automotive
}  // namespace hardware
Loading