Loading automotive/vehicle/2.0/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ cc_library_static { vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ "impl/vhal_v2_0/CommConn.cpp", "impl/vhal_v2_0/EmulatedVehicleHal.cpp", "impl/vhal_v2_0/VehicleEmulator.cpp", "impl/vhal_v2_0/PipeComm.cpp", Loading automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp 0 → 100644 +80 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "CommConn" #include <thread> #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <log/log.h> #include "CommConn.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { void CommConn::start() { mReadThread = std::make_unique<std::thread>(std::bind(&CommConn::readThread, this)); } void CommConn::stop() { if (mReadThread->joinable()) { mReadThread->join(); } } void CommConn::sendMessage(emulator::EmulatorMessage const& msg) { int numBytes = msg.ByteSize(); std::vector<uint8_t> buffer(static_cast<size_t>(numBytes)); if (!msg.SerializeToArray(buffer.data(), numBytes)) { ALOGE("%s: SerializeToString failed!", __func__); return; } write(buffer); } void CommConn::readThread() { std::vector<uint8_t> buffer; while (isOpen()) { buffer = read(); if (buffer.size() == 0) { ALOGI("%s: Read returned empty message, exiting read loop.", __func__); break; } emulator::EmulatorMessage rxMsg; if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) { emulator::EmulatorMessage respMsg; mMessageProcessor->processMessage(rxMsg, respMsg); sendMessage(respMsg); } } } } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h→automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h +49 −18 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ #define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <string> #include <thread> #include <vector> #include "VehicleHalProto.pb.h" namespace android { namespace hardware { namespace automotive { Loading @@ -29,32 +33,45 @@ namespace V2_0 { namespace impl { /** * This is the communications base class. It defines the interface used in DefaultVehicleHal to * send and receive data to and from the emulator. * MessageProcess is an interface implemented by VehicleEmulator to process messages received * over a CommConn. */ class CommBase { class MessageProcessor { public: virtual ~CommBase() = default; virtual ~MessageProcessor() = default; /** * Closes a connection if it is open. * Process a single message received over a CommConn. Populate the given respMsg with the reply * message we should send. */ virtual void stop() {} virtual void processMessage(emulator::EmulatorMessage const& rxMsg, emulator::EmulatorMessage& respMsg) = 0; }; /** * Creates a connection to the other side. * * @return int Returns fd or socket number if connection is successful. * Otherwise, returns -1 if no connection is availble. * This is the interface that both PipeComm and SocketComm use to represent a connection. The * connection will listen for commands on a separate 'read' thread. */ virtual int connect() { return 0; } class CommConn { public: CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {} virtual ~CommConn() {} /** * Opens the communications channel. * * @return int Returns 0 if channel is opened, else -errno if failed. * Start the read thread reading messages from this connection. */ virtual void start(); /** * Closes a connection if it is open. */ virtual int open() = 0; virtual void stop(); /** * Returns true if the connection is open and available to send/receive. */ virtual bool isOpen() = 0; /** * Blocking call to read data from the connection. Loading @@ -72,9 +89,24 @@ public: * @return int Number of bytes transmitted, or -1 if failed. */ virtual int write(const std::vector<uint8_t>& data) = 0; /** * Serialized and send the given message to the other side. */ void sendMessage(emulator::EmulatorMessage const& msg); protected: std::unique_ptr<std::thread> mReadThread; MessageProcessor* mMessageProcessor; /** * A thread that reads messages in a loop, and responds. You can stop this thread by calling * stop(). */ void readThread(); }; } // impl } // namespace impl } // namespace V2_0 } // namespace vehicle Loading @@ -82,5 +114,4 @@ public: } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp +18 −19 Original line number Diff line number Diff line Loading @@ -33,23 +33,28 @@ namespace V2_0 { namespace impl { PipeComm::PipeComm() { // Initialize member vars mPipeFd = -1; } PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {} int PipeComm::open() { void PipeComm::start() { int fd = qemu_pipe_open(CAR_SERVICE_NAME); if (fd < 0) { ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd); return -errno; return; } ALOGI("%s: OPENED PIPE, fd=%d", __FUNCTION__, fd); ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd); mPipeFd = fd; return 0; CommConn::start(); } void PipeComm::stop() { if (mPipeFd > 0) { ::close(mPipeFd); mPipeFd = -1; } CommConn::stop(); } std::vector<uint8_t> PipeComm::read() { Loading @@ -66,11 +71,8 @@ std::vector<uint8_t> PipeComm::read() { return msg; } else { ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes); { std::lock_guard<std::mutex> lock(mMutex); mPipeFd = -1; } } return std::vector<uint8_t>(); } Loading @@ -78,12 +80,9 @@ std::vector<uint8_t> PipeComm::read() { int PipeComm::write(const std::vector<uint8_t>& data) { int retVal = 0; { std::lock_guard<std::mutex> lock(mMutex); if (mPipeFd != -1) { retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size()); } } if (retVal < 0) { retVal = -errno; Loading automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h +14 −27 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ #include <mutex> #include <vector> #include "CommBase.h" #include "CommConn.h" namespace android { namespace hardware { Loading @@ -30,38 +30,25 @@ namespace V2_0 { namespace impl { /** * PipeComm uses a qemu pipe interface to connect to the Goldfish Emulator. * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the * Vehicle HAL and simulate changing properties. * * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open * at a time. */ class PipeComm : public CommBase { class PipeComm : public CommConn { public: PipeComm(); PipeComm(MessageProcessor* messageProcessor); /** * Opens a pipe and begins listening. * * @return int Returns 0 on success. */ int open() override; void start() override; void stop() override; /** * Blocking call to read data from the connection. * * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be * an empty vector if the connection was closed or some other error occurred. */ std::vector<uint8_t> read() override; /** * Transmits a string of data to the emulator. * * @param data Serialized protobuf data to transmit. * * @return int Number of bytes transmitted, or -1 if failed. */ int write(const std::vector<uint8_t>& data) override; inline bool isOpen() override { return mPipeFd > 0; } private: std::mutex mMutex; int mPipeFd; }; Loading Loading
automotive/vehicle/2.0/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ cc_library_static { vendor: true, defaults: ["vhal_v2_0_defaults"], srcs: [ "impl/vhal_v2_0/CommConn.cpp", "impl/vhal_v2_0/EmulatedVehicleHal.cpp", "impl/vhal_v2_0/VehicleEmulator.cpp", "impl/vhal_v2_0/PipeComm.cpp", Loading
automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp 0 → 100644 +80 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "CommConn" #include <thread> #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <log/log.h> #include "CommConn.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { namespace impl { void CommConn::start() { mReadThread = std::make_unique<std::thread>(std::bind(&CommConn::readThread, this)); } void CommConn::stop() { if (mReadThread->joinable()) { mReadThread->join(); } } void CommConn::sendMessage(emulator::EmulatorMessage const& msg) { int numBytes = msg.ByteSize(); std::vector<uint8_t> buffer(static_cast<size_t>(numBytes)); if (!msg.SerializeToArray(buffer.data(), numBytes)) { ALOGE("%s: SerializeToString failed!", __func__); return; } write(buffer); } void CommConn::readThread() { std::vector<uint8_t> buffer; while (isOpen()) { buffer = read(); if (buffer.size() == 0) { ALOGI("%s: Read returned empty message, exiting read loop.", __func__); break; } emulator::EmulatorMessage rxMsg; if (rxMsg.ParseFromArray(buffer.data(), static_cast<int32_t>(buffer.size()))) { emulator::EmulatorMessage respMsg; mMessageProcessor->processMessage(rxMsg, respMsg); sendMessage(respMsg); } } } } // namespace impl } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android
automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h→automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h +49 −18 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ #ifndef android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ #define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_ #include <android/hardware/automotive/vehicle/2.0/IVehicle.h> #include <string> #include <thread> #include <vector> #include "VehicleHalProto.pb.h" namespace android { namespace hardware { namespace automotive { Loading @@ -29,32 +33,45 @@ namespace V2_0 { namespace impl { /** * This is the communications base class. It defines the interface used in DefaultVehicleHal to * send and receive data to and from the emulator. * MessageProcess is an interface implemented by VehicleEmulator to process messages received * over a CommConn. */ class CommBase { class MessageProcessor { public: virtual ~CommBase() = default; virtual ~MessageProcessor() = default; /** * Closes a connection if it is open. * Process a single message received over a CommConn. Populate the given respMsg with the reply * message we should send. */ virtual void stop() {} virtual void processMessage(emulator::EmulatorMessage const& rxMsg, emulator::EmulatorMessage& respMsg) = 0; }; /** * Creates a connection to the other side. * * @return int Returns fd or socket number if connection is successful. * Otherwise, returns -1 if no connection is availble. * This is the interface that both PipeComm and SocketComm use to represent a connection. The * connection will listen for commands on a separate 'read' thread. */ virtual int connect() { return 0; } class CommConn { public: CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {} virtual ~CommConn() {} /** * Opens the communications channel. * * @return int Returns 0 if channel is opened, else -errno if failed. * Start the read thread reading messages from this connection. */ virtual void start(); /** * Closes a connection if it is open. */ virtual int open() = 0; virtual void stop(); /** * Returns true if the connection is open and available to send/receive. */ virtual bool isOpen() = 0; /** * Blocking call to read data from the connection. Loading @@ -72,9 +89,24 @@ public: * @return int Number of bytes transmitted, or -1 if failed. */ virtual int write(const std::vector<uint8_t>& data) = 0; /** * Serialized and send the given message to the other side. */ void sendMessage(emulator::EmulatorMessage const& msg); protected: std::unique_ptr<std::thread> mReadThread; MessageProcessor* mMessageProcessor; /** * A thread that reads messages in a loop, and responds. You can stop this thread by calling * stop(). */ void readThread(); }; } // impl } // namespace impl } // namespace V2_0 } // namespace vehicle Loading @@ -82,5 +114,4 @@ public: } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp +18 −19 Original line number Diff line number Diff line Loading @@ -33,23 +33,28 @@ namespace V2_0 { namespace impl { PipeComm::PipeComm() { // Initialize member vars mPipeFd = -1; } PipeComm::PipeComm(MessageProcessor* messageProcessor) : CommConn(messageProcessor), mPipeFd(-1) {} int PipeComm::open() { void PipeComm::start() { int fd = qemu_pipe_open(CAR_SERVICE_NAME); if (fd < 0) { ALOGE("%s: Could not open connection to service: %s %d", __FUNCTION__, strerror(errno), fd); return -errno; return; } ALOGI("%s: OPENED PIPE, fd=%d", __FUNCTION__, fd); ALOGI("%s: Starting pipe connection, fd=%d", __FUNCTION__, fd); mPipeFd = fd; return 0; CommConn::start(); } void PipeComm::stop() { if (mPipeFd > 0) { ::close(mPipeFd); mPipeFd = -1; } CommConn::stop(); } std::vector<uint8_t> PipeComm::read() { Loading @@ -66,11 +71,8 @@ std::vector<uint8_t> PipeComm::read() { return msg; } else { ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes); { std::lock_guard<std::mutex> lock(mMutex); mPipeFd = -1; } } return std::vector<uint8_t>(); } Loading @@ -78,12 +80,9 @@ std::vector<uint8_t> PipeComm::read() { int PipeComm::write(const std::vector<uint8_t>& data) { int retVal = 0; { std::lock_guard<std::mutex> lock(mMutex); if (mPipeFd != -1) { retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size()); } } if (retVal < 0) { retVal = -errno; Loading
automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h +14 −27 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ #include <mutex> #include <vector> #include "CommBase.h" #include "CommConn.h" namespace android { namespace hardware { Loading @@ -30,38 +30,25 @@ namespace V2_0 { namespace impl { /** * PipeComm uses a qemu pipe interface to connect to the Goldfish Emulator. * PipeComm opens a qemu pipe to connect to the emulator, allowing the emulator UI to access the * Vehicle HAL and simulate changing properties. * * Since the pipe is a client, it directly implements CommConn, and only one PipeComm can be open * at a time. */ class PipeComm : public CommBase { class PipeComm : public CommConn { public: PipeComm(); PipeComm(MessageProcessor* messageProcessor); /** * Opens a pipe and begins listening. * * @return int Returns 0 on success. */ int open() override; void start() override; void stop() override; /** * Blocking call to read data from the connection. * * @return std::vector<uint8_t> Serialized protobuf data received from emulator. This will be * an empty vector if the connection was closed or some other error occurred. */ std::vector<uint8_t> read() override; /** * Transmits a string of data to the emulator. * * @param data Serialized protobuf data to transmit. * * @return int Number of bytes transmitted, or -1 if failed. */ int write(const std::vector<uint8_t>& data) override; inline bool isOpen() override { return mPipeFd > 0; } private: std::mutex mMutex; int mPipeFd; }; Loading