[automerger skipped] Camera: add proper HwLevel check am: cd02298b46 am: 616f595527 am: 8235ceff90 -s ours am: 874cc70085 -s ours am: 72c7579c08 -s ours
am: 1c26316b03 -s ours
Change-Id: Iada7b3c5a712df0b44581acbbc05982ac2c5bbf0
diff --git a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
index 8ab7350..632e816 100644
--- a/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
+++ b/audio/common/all-versions/default/include/common/all-versions/default/HidlUtils.impl.h
@@ -174,9 +174,9 @@
config->ext.mix.hwModule = halConfig.ext.mix.hw_module;
config->ext.mix.ioHandle = halConfig.ext.mix.handle;
if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) {
- config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
- } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream);
+ } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
+ config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
}
break;
}
@@ -212,11 +212,11 @@
halConfig->ext.mix.hw_module = config.ext.mix.hwModule;
halConfig->ext.mix.handle = config.ext.mix.ioHandle;
if (config.role == AudioPortRole::SOURCE) {
- halConfig->ext.mix.usecase.source =
- static_cast<audio_source_t>(config.ext.mix.useCase.source);
- } else if (config.role == AudioPortRole::SINK) {
halConfig->ext.mix.usecase.stream =
static_cast<audio_stream_type_t>(config.ext.mix.useCase.stream);
+ } else if (config.role == AudioPortRole::SINK) {
+ halConfig->ext.mix.usecase.source =
+ static_cast<audio_source_t>(config.ext.mix.useCase.source);
}
break;
}
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 9c9b749..b811c10 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -1105,11 +1105,10 @@
}
TEST_P(InputStreamTest, getActiveMicrophones) {
- doc::test("Getting active microphones should always succeed");
+ doc::test("Active microphones of a non started stream may not be retrievable");
hidl_vec<MicrophoneInfo> microphones;
- ASSERT_OK(device->getMicrophones(returnIn(res, microphones)));
- ASSERT_OK(res);
- ASSERT_TRUE(microphones.size() > 0);
+ ASSERT_OK(stream->getActiveMicrophones(returnIn(res, microphones)));
+ ASSERT_RESULT(okOrNotSupported, res);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.h
index eb53b48..222d3de 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.h
@@ -124,7 +124,8 @@
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
// Utility methods for extending interfaces.
- Result analyzeStatus(const char* funcName, int status);
+ Result analyzeStatus(const char* funcName, int status,
+ const std::vector<int>& ignoreErrors = {});
void closeInputStream(audio_stream_in_t* stream);
void closeOutputStream(audio_stream_out_t* stream);
audio_hw_device_t* device() const { return mDevice; }
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
index 230b8de..52d2186 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Device.impl.h
@@ -40,8 +40,9 @@
mDevice = nullptr;
}
-Result Device::analyzeStatus(const char* funcName, int status) {
- return util::analyzeStatus("Device", funcName, status);
+Result Device::analyzeStatus(const char* funcName, int status,
+ const std::vector<int>& ignoreErrors) {
+ return util::analyzeStatus("Device", funcName, status, ignoreErrors);
}
void Device::closeInputStream(audio_stream_in_t* stream) {
@@ -155,7 +156,8 @@
}
AudioConfig suggestedConfig;
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
- _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
+ _hidl_cb(analyzeStatus("open_output_stream", status, {EINVAL} /* ignore */), streamOut,
+ suggestedConfig);
return Void();
}
@@ -183,7 +185,8 @@
}
AudioConfig suggestedConfig;
HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
- _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
+ _hidl_cb(analyzeStatus("open_input_stream", status, {EINVAL} /* ignore */), streamIn,
+ suggestedConfig);
return Void();
}
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
index 43e5d6e..a9f59fb 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/DevicesFactory.impl.h
@@ -106,8 +106,8 @@
return rc;
}
-IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
- return new DevicesFactory();
+IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name) {
+ return strcmp(name, "default") == 0 ? new DevicesFactory() : nullptr;
}
} // namespace implementation
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
index 6f79429..375759d 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
@@ -163,6 +163,22 @@
if (retval == Result::OK) {
hidlHandle = native_handle_create(1, 0);
hidlHandle->data[0] = halInfo.shared_memory_fd;
+
+ // Negative buffer size frame is a legacy hack to indicate that the buffer
+ // is shareable to applications before the relevant flag was introduced
+ bool applicationShareable =
+ halInfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE || halInfo.buffer_size_frames < 0;
+ halInfo.buffer_size_frames = abs(halInfo.buffer_size_frames);
+#ifdef AUDIO_HAL_VERSION_2_0
+ if (applicationShareable) {
+ halInfo.buffer_size_frames *= -1;
+ }
+#else
+ info.flags =
+ halInfo.flags | (applicationShareable ? MmapBufferFlag::APPLICATION_SHAREABLE
+ : MmapBufferFlag::NONE);
+#endif
+
info.sharedMemory =
hidl_memory("audio_buffer", hidlHandle, frameSize * halInfo.buffer_size_frames);
info.bufferSizeFrames = halInfo.buffer_size_frames;
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
index 1882a2c..f27c739 100644
--- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
@@ -183,8 +183,8 @@
return Void();
}
-IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) {
- return new EffectsFactory();
+IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name) {
+ return strcmp(name, "default") == 0 ? new EffectsFactory() : nullptr;
}
} // namespace implementation
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 22ab079..7802ef0 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -58,12 +58,14 @@
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",
"impl/vhal_v2_0/SocketComm.cpp",
"impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
"impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
+ "impl/vhal_v2_0/GeneratorHub.cpp",
],
local_include_dirs: ["common/include/vhal_v2_0"],
export_include_dirs: ["impl"],
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h
deleted file mode 100644
index 6832ad3..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommBase.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
-
-#include <string>
-#include <vector>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-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.
- */
-class CommBase {
-public:
- virtual ~CommBase() = default;
-
- /**
- * Closes a connection if it is open.
- */
- virtual void stop() {}
-
- /**
- * 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.
- */
- virtual int connect() { return 0; }
-
- /**
- * Opens the communications channel.
- *
- * @return int Returns 0 if channel is opened, else -errno if failed.
- */
- virtual int open() = 0;
-
- /**
- * 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.
- */
- virtual std::vector<uint8_t> read() = 0;
-
- /**
- * 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.
- */
- virtual int write(const std::vector<uint8_t>& data) = 0;
-};
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
new file mode 100644
index 0000000..bf1de81
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
new file mode 100644
index 0000000..87b0dfc
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/CommConn.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#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 {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/**
+ * MessageProcess is an interface implemented by VehicleEmulator to process messages received
+ * over a CommConn.
+ */
+class MessageProcessor {
+ public:
+ virtual ~MessageProcessor() = default;
+
+ /**
+ * Process a single message received over a CommConn. Populate the given respMsg with the reply
+ * message we should send.
+ */
+ virtual void processMessage(emulator::EmulatorMessage const& rxMsg,
+ emulator::EmulatorMessage& respMsg) = 0;
+};
+
+/**
+ * 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.
+ */
+class CommConn {
+ public:
+ CommConn(MessageProcessor* messageProcessor) : mMessageProcessor(messageProcessor) {}
+
+ virtual ~CommConn() {}
+
+ /**
+ * Start the read thread reading messages from this connection.
+ */
+ virtual void start();
+
+ /**
+ * Closes a connection if it is open.
+ */
+ 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.
+ *
+ * @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.
+ */
+ virtual std::vector<uint8_t> read() = 0;
+
+ /**
+ * 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.
+ */
+ 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();
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_CommBase_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index eb9d660..917fbc3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -34,6 +34,8 @@
constexpr int AP_POWER_STATE_REPORT = (int)VehicleProperty::AP_POWER_STATE_REPORT;
constexpr int DOOR_1_LEFT = (int)VehicleAreaDoor::ROW_1_LEFT;
constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT;
+constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT;
+constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT;
constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
@@ -48,6 +50,14 @@
VehicleAreaSeat::ROW_2_CENTER);
constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT);
constexpr int HVAC_ALL = HVAC_LEFT | HVAC_RIGHT;
+constexpr int VENDOR_EXTENSION_BOOLEAN_PROPERTY =
+ (int)(0x101 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::BOOLEAN | VehicleArea::DOOR);
+constexpr int VENDOR_EXTENSION_FLOAT_PROPERTY =
+ (int)(0x102 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::FLOAT | VehicleArea::SEAT);
+constexpr int VENDOR_EXTENSION_INT_PROPERTY =
+ (int)(0x103 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::INT32 | VehicleArea::WINDOW);
+constexpr int VENDOR_EXTENSION_STRING_PROPERTY =
+ (int)(0x104 | VehiclePropertyGroup::VENDOR | VehiclePropertyType::STRING | VehicleArea::GLOBAL);
/**
* This property is used for test purpose to generate fake events. Here is the test package that
@@ -70,33 +80,39 @@
enum class FakeDataCommand : int32_t {
/**
* Starts linear fake data generation. Caller must provide additional data:
- * int32Values[1] - VehicleProperty to which command applies
+ * int32Values[1] - vehicle property to which command applies
* int64Values[0] - periodic interval in nanoseconds
* floatValues[0] - initial value
* floatValues[1] - dispersion defines the min/max value relative to initial value, where
* max = initial_value + dispersion, min = initial_value - dispersion.
* Dispersion should be non-negative, otherwise the behavior is undefined.
* floatValues[2] - increment, with every timer tick the value will be incremented by this
- * amount. When reaching to max value, the current value will be set to min.
- * It should be non-negative, otherwise the behavior is undefined.
+ * amount. When reaching to max value, the current value will be set to
+ * min. It should be non-negative, otherwise the behavior is undefined.
*/
StartLinear = 0,
- /** Stops generating of fake data that was triggered by Start commands.
- * int32Values[1] - VehicleProperty to which command applies. VHAL will stop the
+ /** Stops linear fake data generation that was triggered by StartLinear commands.
+ * int32Values[1] - vehicle property to which command applies. VHAL will stop the
* corresponding linear generation for that property.
*/
StopLinear = 1,
/**
- * Starts JSON-based fake data generation. Caller must provide a string value specifying
- * the path to fake value JSON file:
+ * Starts JSON-based fake data generation. It iterates through JSON-encoded VHAL events from a
+ * file and inject them to VHAL. The iteration can be repeated multiple times or infinitely.
+ * Caller must provide additional data:
+ * int32Values[1] - number of iterations. If it is not provided or -1. The iteration will be
+ * repeated infinite times.
* stringValue - path to the fake values JSON file
*/
StartJson = 2,
/**
- * Stops JSON-based fake data generation. No additional arguments needed.
+ * Stops JSON-based fake data generation. As multiple JSON-based generation can happen at the
+ * same time. Caller must provide the path of fake value JSON file to stop the corresponding
+ * generation:
+ * stringValue - path to the fake values JSON file
*/
StopJson = 3,
@@ -366,10 +382,14 @@
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
.areaConfigs = {VehicleAreaConfig{
- .areaId = HVAC_LEFT, .minFloatValue = 16, .maxFloatValue = 32,
+ .areaId = HVAC_LEFT,
+ .minFloatValue = 16,
+ .maxFloatValue = 32,
},
VehicleAreaConfig{
- .areaId = HVAC_RIGHT, .minFloatValue = 16, .maxFloatValue = 32,
+ .areaId = HVAC_RIGHT,
+ .minFloatValue = 16,
+ .maxFloatValue = 32,
}}},
.initialAreaValues = {{HVAC_LEFT, {.floatValues = {16}}},
{HVAC_RIGHT, {.floatValues = {20}}}}},
@@ -523,6 +543,51 @@
{.config = {.prop = VEHICLE_MAP_SERVICE,
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
+
+ // Example Vendor Extension properties for testing
+ {.config = {.prop = VENDOR_EXTENSION_BOOLEAN_PROPERTY,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
+ VehicleAreaConfig{.areaId = DOOR_1_RIGHT},
+ VehicleAreaConfig{.areaId = DOOR_2_LEFT},
+ VehicleAreaConfig{.areaId = DOOR_2_RIGHT}}},
+ .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
+ {DOOR_1_RIGHT, {.int32Values = {1}}},
+ {DOOR_2_LEFT, {.int32Values = {0}}},
+ {DOOR_2_RIGHT, {.int32Values = {0}}}}},
+
+ {.config = {.prop = VENDOR_EXTENSION_FLOAT_PROPERTY,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = HVAC_LEFT, .minFloatValue = -10, .maxFloatValue = 10},
+ VehicleAreaConfig{.areaId = HVAC_RIGHT,
+ .minFloatValue = -10,
+ .maxFloatValue = 10}}},
+ .initialAreaValues = {{HVAC_LEFT, {.floatValues = {1}}}, {HVAC_RIGHT, {.floatValues = {2}}}}},
+
+ {.config = {.prop = VENDOR_EXTENSION_INT_PROPERTY,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (int)VehicleAreaWindow::FRONT_WINDSHIELD,
+ .minInt32Value = -100,
+ .maxInt32Value = 100},
+ VehicleAreaConfig{.areaId = (int)VehicleAreaWindow::REAR_WINDSHIELD,
+ .minInt32Value = -100,
+ .maxInt32Value = 100},
+ VehicleAreaConfig{.areaId = (int)VehicleAreaWindow::ROOF_TOP_1,
+ .minInt32Value = -100,
+ .maxInt32Value = 100}}},
+ .initialAreaValues = {{(int)VehicleAreaWindow::FRONT_WINDSHIELD, {.int32Values = {1}}},
+ {(int)VehicleAreaWindow::REAR_WINDSHIELD, {.int32Values = {0}}},
+ {(int)VehicleAreaWindow::ROOF_TOP_1, {.int32Values = {-1}}}}},
+
+ {.config = {.prop = VENDOR_EXTENSION_STRING_PROPERTY,
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+ .initialValue = {.stringValue = "Vendor String Property"}},
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 07695bf..58d8867 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -92,10 +92,8 @@
mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
mRecurrentTimer(
std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)),
- mLinearFakeValueGenerator(std::make_unique<LinearFakeValueGenerator>(
- std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))),
- mJsonFakeValueGenerator(std::make_unique<JsonFakeValueGenerator>(
- std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))) {
+ mGeneratorHub(
+ std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1)) {
initStaticConfig();
for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
mPropStore->registerProperty(kVehicleProperties[i].config);
@@ -189,6 +187,7 @@
}
getEmulatorOrDie()->doSetValueFromClient(propValue);
+ doHalEvent(getValuePool()->obtain(propValue));
return StatusCode::OK;
}
@@ -343,19 +342,54 @@
switch (command) {
case FakeDataCommand::StartLinear: {
ALOGI("%s, FakeDataCommand::StartLinear", __func__);
- return mLinearFakeValueGenerator->start(request);
+ if (v.int32Values.size() < 2) {
+ ALOGE("%s: expected property ID in int32Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ if (!v.int64Values.size()) {
+ ALOGE("%s: interval is not provided in int64Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ if (v.floatValues.size() < 3) {
+ ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
+ v.floatValues.size());
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ mGeneratorHub.registerGenerator(cookie,
+ std::make_unique<LinearFakeValueGenerator>(request));
+ break;
}
case FakeDataCommand::StartJson: {
ALOGI("%s, FakeDataCommand::StartJson", __func__);
- return mJsonFakeValueGenerator->start(request);
+ if (v.stringValue.empty()) {
+ ALOGE("%s: path to JSON file is missing", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ mGeneratorHub.registerGenerator(cookie,
+ std::make_unique<JsonFakeValueGenerator>(request));
+ break;
}
case FakeDataCommand::StopLinear: {
ALOGI("%s, FakeDataCommand::StopLinear", __func__);
- return mLinearFakeValueGenerator->stop(request);
+ if (v.int32Values.size() < 2) {
+ ALOGE("%s: expected property ID in int32Values", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = v.int32Values[1];
+ mGeneratorHub.unregisterGenerator(cookie);
+ break;
}
case FakeDataCommand::StopJson: {
ALOGI("%s, FakeDataCommand::StopJson", __func__);
- return mJsonFakeValueGenerator->stop(request);
+ if (v.stringValue.empty()) {
+ ALOGE("%s: path to JSON file is missing", __func__);
+ return StatusCode::INVALID_ARG;
+ }
+ int32_t cookie = std::hash<std::string>()(v.stringValue);
+ mGeneratorHub.unregisterGenerator(cookie);
+ break;
}
case FakeDataCommand::KeyPress: {
ALOGI("%s, FakeDataCommand::KeyPress", __func__);
@@ -398,7 +432,7 @@
mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus);
auto changeMode = mPropStore->getConfigOrDie(value.prop)->changeMode;
if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) {
- doHalEvent(move(updatedPropValue));
+ doHalEvent(std::move(updatedPropValue));
}
}
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index c188aef..ec59690 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -30,8 +30,7 @@
#include "vhal_v2_0/VehiclePropertyStore.h"
#include "DefaultConfig.h"
-#include "FakeValueGenerator.h"
-
+#include "GeneratorHub.h"
#include "VehicleEmulator.h"
namespace android {
@@ -85,8 +84,7 @@
VehiclePropertyStore* mPropStore;
std::unordered_set<int32_t> mHvacPowerProps;
RecurrentTimer mRecurrentTimer;
- std::unique_ptr<FakeValueGenerator> mLinearFakeValueGenerator;
- std::unique_ptr<FakeValueGenerator> mJsonFakeValueGenerator;
+ GeneratorHub mGeneratorHub;
};
} // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
index 1eeb88d..d6ad77d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h
@@ -27,28 +27,22 @@
namespace impl {
-using OnHalEvent = std::function<void(const VehiclePropValue& event)>;
-using MuxGuard = std::lock_guard<std::mutex>;
-
class FakeValueGenerator {
public:
virtual ~FakeValueGenerator() = default;
- /**
- * Starts generating VHAL events
- *
- * @param request in VehiclePropValue with required information to start fake data generation
- * @return StatusCode of the start request
- */
- virtual StatusCode start(const VehiclePropValue& request) = 0;
- /**
- * Stops generating VHAL events
- * @param request in VehiclePropValue with required information to stop fake data generation
- * @return StatusCode of the stop request
- */
- virtual StatusCode stop(const VehiclePropValue& request) = 0;
+
+ virtual VehiclePropValue nextEvent() = 0;
+
+ virtual bool hasNext() = 0;
};
-} // impl
+using Clock = std::chrono::steady_clock;
+using Nanos = std::chrono::nanoseconds;
+using TimePoint = std::chrono::time_point<Clock, Nanos>;
+
+using FakeValueGeneratorPtr = std::unique_ptr<FakeValueGenerator>;
+
+} // namespace impl
} // namespace V2_0
} // namespace vehicle
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
new file mode 100644
index 0000000..548285a
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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 "GeneratorHub"
+
+#include <log/log.h>
+
+#include "GeneratorHub.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+GeneratorHub::GeneratorHub(const OnHalEvent& onHalEvent)
+ : mOnHalEvent(onHalEvent), mThread(&GeneratorHub::run, this) {}
+
+void GeneratorHub::registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator) {
+ {
+ std::lock_guard<std::mutex> g(mLock);
+ // Register only if the generator can produce event
+ if (generator->hasNext()) {
+ // Push the next event if it is a new generator
+ if (mGenerators.find(cookie) == mGenerators.end()) {
+ ALOGI("%s: Registering new generator, cookie: %d", __func__, cookie);
+ mEventQueue.push({cookie, generator->nextEvent()});
+ }
+ mGenerators[cookie] = std::move(generator);
+ ALOGI("%s: Registered generator, cookie: %d", __func__, cookie);
+ }
+ }
+ mCond.notify_one();
+}
+
+void GeneratorHub::unregisterGenerator(int32_t cookie) {
+ {
+ std::lock_guard<std::mutex> g(mLock);
+ mGenerators.erase(cookie);
+ }
+ mCond.notify_one();
+ ALOGI("%s: Unregistered generator, cookie: %d", __func__, cookie);
+}
+
+void GeneratorHub::run() {
+ while (true) {
+ std::unique_lock<std::mutex> g(mLock);
+ // Pop events whose generator does not exist (may be already unregistered)
+ while (!mEventQueue.empty()
+ && mGenerators.find(mEventQueue.top().cookie) == mGenerators.end()) {
+ mEventQueue.pop();
+ }
+ // Wait until event queue is not empty
+ mCond.wait(g, [this] { return !mEventQueue.empty(); });
+
+ const VhalEvent& curEvent = mEventQueue.top();
+
+ TimePoint eventTime(Nanos(curEvent.val.timestamp));
+ // Wait until the soonest event happen
+ if (mCond.wait_until(g, eventTime) != std::cv_status::timeout) {
+ // It is possible that a new generator is registered and produced a sooner event, or current
+ // generator is unregistered, in this case the thread will re-evaluate the soonest event
+ ALOGI("Something happened while waiting");
+ continue;
+ }
+ // Now it's time to handle current event.
+ mOnHalEvent(curEvent.val);
+ // Update queue by popping current event and producing next event from the same generator
+ int32_t cookie = curEvent.cookie;
+ mEventQueue.pop();
+ if (hasNext(cookie)) {
+ mEventQueue.push({cookie, mGenerators[cookie]->nextEvent()});
+ } else {
+ ALOGI("%s: Generator ended, unregister it, cookie: %d", __func__, cookie);
+ mGenerators.erase(cookie);
+ }
+ }
+}
+
+bool GeneratorHub::hasNext(int32_t cookie) {
+ return mGenerators.find(cookie) != mGenerators.end() && mGenerators[cookie]->hasNext();
+}
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
new file mode 100644
index 0000000..dcf6a4f
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/GeneratorHub.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_
+
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <iostream>
+#include <queue>
+#include <thread>
+#include <unordered_map>
+
+#include "FakeValueGenerator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/**
+ * This is the scheduler for all VHAL event generators. It manages all generators and uses priority
+ * queue to maintain generated events ordered by timestamp. The scheduler uses a single thread to
+ * keep querying and updating the event queue to make sure events from all generators are produced
+ * in order.
+ */
+class GeneratorHub {
+private:
+ struct VhalEvent {
+ int32_t cookie; // Cookie is used to find the associated generator.
+ VehiclePropValue val;
+ };
+ // Comparator used by priority queue to keep track of soonest event.
+ struct GreaterByTime {
+ bool operator()(const VhalEvent& lhs, const VhalEvent& rhs) const {
+ return lhs.val.timestamp > rhs.val.timestamp;
+ }
+ };
+
+ using OnHalEvent = std::function<void(const VehiclePropValue& event)>;
+
+public:
+ GeneratorHub(const OnHalEvent& onHalEvent);
+ ~GeneratorHub() = default;
+
+ /**
+ * Register a new generator. The generator will be discarded if it could not produce next event.
+ * The existing generator will be overridden if it has the same cookie.
+ */
+ void registerGenerator(int32_t cookie, FakeValueGeneratorPtr generator);
+
+ void unregisterGenerator(int32_t cookie);
+
+private:
+ /**
+ * Main loop of the single thread to producing event and updating event queue.
+ */
+ void run();
+
+ bool hasNext(int32_t cookie);
+
+private:
+ std::priority_queue<VhalEvent, std::vector<VhalEvent>, GreaterByTime> mEventQueue;
+ std::unordered_map<int32_t, FakeValueGeneratorPtr> mGenerators;
+ OnHalEvent mOnHalEvent;
+
+ mutable std::mutex mLock;
+ std::condition_variable mCond;
+ std::thread mThread;
+};
+
+} // namespace impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_GeneratorHub_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
index 88b8f86..b8fd2ba 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp
@@ -17,6 +17,8 @@
#define LOG_TAG "JsonFakeValueGenerator"
#include <fstream>
+#include <type_traits>
+#include <typeinfo>
#include <log/log.h>
#include <vhal_v2_0/VehicleUtils.h>
@@ -31,57 +33,48 @@
namespace impl {
-JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent)
- : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {}
-
-JsonFakeValueGenerator::~JsonFakeValueGenerator() {
- mStopRequested = true;
- {
- MuxGuard g(mLock);
- mGenCfg.index = 0;
- mGenCfg.events.clear();
- }
- mCond.notify_one();
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-
-StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) {
+JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
- if (v.stringValue.empty()) {
- ALOGE("%s: path to JSON file is missing", __func__);
- return StatusCode::INVALID_ARG;
- }
const char* file = v.stringValue.c_str();
std::ifstream ifs(file);
if (!ifs) {
ALOGE("%s: couldn't open %s for parsing.", __func__, file);
- return StatusCode::INTERNAL_ERROR;
}
- std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs);
-
- {
- MuxGuard g(mLock);
- mGenCfg = {0, fakeVhalEvents};
- }
- mCond.notify_one();
- return StatusCode::OK;
+ mGenCfg = {
+ .index = 0,
+ .events = parseFakeValueJson(ifs),
+ };
+ // Iterate infinitely if repetition number is not provided
+ mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
}
-StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) {
- const auto& v = request.value;
- if (!v.stringValue.empty()) {
- ALOGI("%s: %s", __func__, v.stringValue.c_str());
+VehiclePropValue JsonFakeValueGenerator::nextEvent() {
+ VehiclePropValue generatedValue;
+ if (!hasNext()) {
+ return generatedValue;
}
+ TimePoint eventTime = Clock::now();
+ if (mGenCfg.index != 0) {
+ // All events (start from 2nd one) are supposed to happen in the future with a delay
+ // equals to the duration between previous and current event.
+ eventTime += Nanos(mGenCfg.events[mGenCfg.index].timestamp -
+ mGenCfg.events[mGenCfg.index - 1].timestamp);
+ }
+ generatedValue = mGenCfg.events[mGenCfg.index];
+ generatedValue.timestamp = eventTime.time_since_epoch().count();
- {
- MuxGuard g(mLock);
+ mGenCfg.index++;
+ if (mGenCfg.index == mGenCfg.events.size()) {
mGenCfg.index = 0;
- mGenCfg.events.clear();
+ if (mNumOfIterations > 0) {
+ mNumOfIterations--;
+ }
}
- mCond.notify_one();
- return StatusCode::OK;
+ return generatedValue;
+}
+
+bool JsonFakeValueGenerator::hasNext() {
+ return mNumOfIterations != 0 && mGenCfg.events.size() > 0;
}
std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) {
@@ -131,9 +124,14 @@
case VehiclePropertyType::STRING:
value.stringValue = rawEventValue.asString();
break;
+ case VehiclePropertyType::MIXED:
+ copyMixedValueJson(value, rawEventValue);
+ if (isDiagnosticProperty(event.prop)) {
+ value.bytes = generateDiagnosticBytes(value);
+ }
+ break;
default:
- ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__,
- event.prop, rawEventValue.asString().c_str());
+ ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop);
continue;
}
fakeVhalEvents.push_back(event);
@@ -141,30 +139,60 @@
return fakeVhalEvents;
}
-void JsonFakeValueGenerator::loop() {
- static constexpr auto kInvalidTime = TimePoint(Nanos::max());
+void JsonFakeValueGenerator::copyMixedValueJson(VehiclePropValue::RawValue& dest,
+ const Json::Value& jsonValue) {
+ copyJsonArray(dest.int32Values, jsonValue["int32Values"]);
+ copyJsonArray(dest.int64Values, jsonValue["int64Values"]);
+ copyJsonArray(dest.floatValues, jsonValue["floatValues"]);
+ dest.stringValue = jsonValue["stringValue"].asString();
+}
- while (!mStopRequested) {
- auto nextEventTime = kInvalidTime;
- {
- MuxGuard g(mLock);
- if (mGenCfg.index < mGenCfg.events.size()) {
- mOnHalEvent(mGenCfg.events[mGenCfg.index]);
- }
- if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) {
- Nanos intervalNano =
- static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp -
- mGenCfg.events[mGenCfg.index].timestamp);
- nextEventTime = Clock::now() + intervalNano;
- }
- mGenCfg.index++;
+template <typename T>
+void JsonFakeValueGenerator::copyJsonArray(hidl_vec<T>& dest, const Json::Value& jsonArray) {
+ dest.resize(jsonArray.size());
+ for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) {
+ if (std::is_same<T, int32_t>::value) {
+ dest[i] = jsonArray[i].asInt();
+ } else if (std::is_same<T, int64_t>::value) {
+ dest[i] = jsonArray[i].asInt64();
+ } else if (std::is_same<T, float>::value) {
+ dest[i] = jsonArray[i].asFloat();
}
-
- std::unique_lock<std::mutex> g(mLock);
- mCond.wait_until(g, nextEventTime);
}
}
+bool JsonFakeValueGenerator::isDiagnosticProperty(int32_t prop) {
+ return prop == (int32_t)VehicleProperty::OBD2_LIVE_FRAME ||
+ prop == (int32_t)VehicleProperty::OBD2_FREEZE_FRAME;
+}
+
+hidl_vec<uint8_t> JsonFakeValueGenerator::generateDiagnosticBytes(
+ const VehiclePropValue::RawValue& diagnosticValue) {
+ size_t byteSize = ((size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX +
+ (size_t)DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX + 2);
+ hidl_vec<uint8_t> bytes(byteSize % 8 == 0 ? byteSize / 8 : byteSize / 8 + 1);
+
+ auto& int32Values = diagnosticValue.int32Values;
+ for (size_t i = 0; i < int32Values.size(); i++) {
+ if (int32Values[i] != 0) {
+ setBit(bytes, i);
+ }
+ }
+
+ auto& floatValues = diagnosticValue.floatValues;
+ for (size_t i = 0; i < floatValues.size(); i++) {
+ if (floatValues[i] != 0.0) {
+ setBit(bytes, i + (size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX + 1);
+ }
+ }
+ return bytes;
+}
+
+void JsonFakeValueGenerator::setBit(hidl_vec<uint8_t>& bytes, size_t idx) {
+ uint8_t mask = 1 << (idx % 8);
+ bytes[idx / 8] |= mask;
+}
+
} // namespace impl
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
index 51da4c5..70575f7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h
@@ -17,11 +17,8 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
#define android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_
-#include <atomic>
#include <chrono>
-#include <condition_variable>
#include <iostream>
-#include <thread>
#include <json/json.h>
@@ -37,32 +34,33 @@
class JsonFakeValueGenerator : public FakeValueGenerator {
private:
- using Nanos = std::chrono::nanoseconds;
- using Clock = std::chrono::steady_clock;
- using TimePoint = std::chrono::time_point<Clock, Nanos>;
-
struct GeneratorCfg {
size_t index;
std::vector<VehiclePropValue> events;
};
public:
- JsonFakeValueGenerator(const OnHalEvent& onHalEvent);
- ~JsonFakeValueGenerator();
- StatusCode start(const VehiclePropValue& request) override;
- StatusCode stop(const VehiclePropValue& request) override;
+ JsonFakeValueGenerator(const VehiclePropValue& request);
+ ~JsonFakeValueGenerator() = default;
+
+ VehiclePropValue nextEvent();
+
+ bool hasNext();
private:
std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is);
- void loop();
+ void copyMixedValueJson(VehiclePropValue::RawValue& dest, const Json::Value& jsonValue);
+
+ template <typename T>
+ void copyJsonArray(hidl_vec<T>& dest, const Json::Value& jsonArray);
+
+ bool isDiagnosticProperty(int32_t prop);
+ hidl_vec<uint8_t> generateDiagnosticBytes(const VehiclePropValue::RawValue& diagnosticValue);
+ void setBit(hidl_vec<uint8_t>& bytes, size_t idx);
private:
- OnHalEvent mOnHalEvent;
- std::thread mThread;
- mutable std::mutex mLock;
- std::condition_variable mCond;
GeneratorCfg mGenCfg;
- std::atomic_bool mStopRequested{false};
+ int32_t mNumOfIterations;
};
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
index 8cb9322..7bdc97c 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp
@@ -29,101 +29,48 @@
namespace impl {
-LinearFakeValueGenerator::LinearFakeValueGenerator(const OnHalEvent& onHalEvent)
- : mOnHalEvent(onHalEvent),
- mRecurrentTimer(std::bind(&LinearFakeValueGenerator::onTimer, this, std::placeholders::_1)) {}
-
-StatusCode LinearFakeValueGenerator::start(const VehiclePropValue& request) {
+LinearFakeValueGenerator::LinearFakeValueGenerator(const VehiclePropValue& request) {
const auto& v = request.value;
- if (v.int32Values.size() < 2) {
- ALOGE("%s: expected property ID in int32Values", __func__);
- return StatusCode::INVALID_ARG;
- }
- int32_t propId = v.int32Values[1];
-
- if (!v.int64Values.size()) {
- ALOGE("%s: interval is not provided in int64Values", __func__);
- return StatusCode::INVALID_ARG;
- }
- auto interval = std::chrono::nanoseconds(v.int64Values[0]);
-
- if (v.floatValues.size() < 3) {
- ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__,
- v.floatValues.size());
- return StatusCode::INVALID_ARG;
- }
- float initialValue = v.floatValues[0];
- float dispersion = v.floatValues[1];
- float increment = v.floatValues[2];
-
- MuxGuard g(mLock);
- removeLocked(propId);
- mGenCfg.insert({propId, GeneratorCfg{
- .initialValue = initialValue,
- .currentValue = initialValue,
- .dispersion = dispersion,
- .increment = increment,}});
-
- mRecurrentTimer.registerRecurrentEvent(interval, propId);
- return StatusCode::OK;
+ mGenCfg = GeneratorCfg{
+ .propId = v.int32Values[1],
+ .initialValue = v.floatValues[0],
+ .currentValue = v.floatValues[0],
+ .dispersion = v.floatValues[1],
+ .increment = v.floatValues[2],
+ .interval = Nanos(v.int64Values[0]),
+ };
}
-StatusCode LinearFakeValueGenerator::stop(const VehiclePropValue& request) {
- const auto& v = request.value;
- if (v.int32Values.size() < 2) {
- ALOGE("%s: expected property ID in int32Values", __func__);
- return StatusCode::INVALID_ARG;
+VehiclePropValue LinearFakeValueGenerator::nextEvent() {
+ mGenCfg.currentValue += mGenCfg.increment;
+ if (mGenCfg.currentValue > mGenCfg.initialValue + mGenCfg.dispersion) {
+ mGenCfg.currentValue = mGenCfg.initialValue - mGenCfg.dispersion;
}
- int32_t propId = v.int32Values[1];
-
- MuxGuard g(mLock);
- if (propId == 0) {
- // Remove all.
- for (auto&& it : mGenCfg) {
- removeLocked(it.first);
- }
- } else {
- removeLocked(propId);
+ VehiclePropValue event = {.prop = mGenCfg.propId};
+ auto& value = event.value;
+ switch (getPropType(event.prop)) {
+ case VehiclePropertyType::INT32:
+ value.int32Values.resize(1);
+ value.int32Values[0] = static_cast<int32_t>(mGenCfg.currentValue);
+ break;
+ case VehiclePropertyType::INT64:
+ value.int64Values.resize(1);
+ value.int64Values[0] = static_cast<int64_t>(mGenCfg.currentValue);
+ break;
+ case VehiclePropertyType::FLOAT:
+ value.floatValues.resize(1);
+ value.floatValues[0] = mGenCfg.currentValue;
+ break;
+ default:
+ ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
}
- return StatusCode::OK;
+ TimePoint eventTime = Clock::now() + mGenCfg.interval;
+ event.timestamp = eventTime.time_since_epoch().count();
+ return event;
}
-void LinearFakeValueGenerator::removeLocked(int propId) {
- if (mGenCfg.erase(propId)) {
- mRecurrentTimer.unregisterRecurrentEvent(propId);
- }
-}
-
-void LinearFakeValueGenerator::onTimer(const std::vector<int32_t>& properties) {
- MuxGuard g(mLock);
-
- for (int32_t propId : properties) {
- auto& cfg = mGenCfg[propId];
- cfg.currentValue += cfg.increment;
- if (cfg.currentValue > cfg.initialValue + cfg.dispersion) {
- cfg.currentValue = cfg.initialValue - cfg.dispersion;
- }
- VehiclePropValue event = {.prop = propId};
- auto& value = event.value;
- switch (getPropType(event.prop)) {
- case VehiclePropertyType::INT32:
- value.int32Values.resize(1);
- value.int32Values[0] = static_cast<int32_t>(cfg.currentValue);
- break;
- case VehiclePropertyType::INT64:
- value.int64Values.resize(1);
- value.int64Values[0] = static_cast<int64_t>(cfg.currentValue);
- break;
- case VehiclePropertyType::FLOAT:
- value.floatValues.resize(1);
- value.floatValues[0] = cfg.currentValue;
- break;
- default:
- ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop);
- continue;
- }
- mOnHalEvent(event);
- }
+bool LinearFakeValueGenerator::hasNext() {
+ return true;
}
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
index fe6d097..d3b666d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h
@@ -17,8 +17,6 @@
#ifndef android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
#define android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_
-#include <vhal_v2_0/RecurrentTimer.h>
-
#include "FakeValueGenerator.h"
namespace android {
@@ -36,27 +34,24 @@
// to the client.
struct GeneratorCfg {
- float initialValue; //
+ int32_t propId;
+ float initialValue;
float currentValue; // Should be in range (initialValue +/- dispersion).
float dispersion; // Defines minimum and maximum value based on initial value.
float increment; // Value that we will be added to currentValue with each timer tick.
+ Nanos interval;
};
public:
- LinearFakeValueGenerator(const OnHalEvent& onHalEvent);
+ LinearFakeValueGenerator(const VehiclePropValue& request);
~LinearFakeValueGenerator() = default;
- StatusCode start(const VehiclePropValue& request) override;
- StatusCode stop(const VehiclePropValue& request) override;
+
+ VehiclePropValue nextEvent();
+
+ bool hasNext();
private:
- void removeLocked(int propId);
- void onTimer(const std::vector<int32_t>& properties);
-
-private:
- mutable std::mutex mLock;
- OnHalEvent mOnHalEvent;
- RecurrentTimer mRecurrentTimer;
- std::unordered_map<int32_t, GeneratorCfg> mGenCfg;
+ GeneratorCfg mGenCfg;
};
} // namespace impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
index 5a9b254..f024287 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.cpp
@@ -33,23 +33,28 @@
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() {
@@ -60,16 +65,13 @@
numBytes = qemu_pipe_frame_recv(mPipeFd, msg.data(), msg.size());
if (numBytes == MAX_RX_MSG_SZ) {
- ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ);
+ ALOGE("%s: Received max size = %d", __FUNCTION__, MAX_RX_MSG_SZ);
} else if (numBytes > 0) {
msg.resize(numBytes);
return msg;
} else {
ALOGD("%s: Connection terminated on pipe %d, numBytes=%d", __FUNCTION__, mPipeFd, numBytes);
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mPipeFd = -1;
- }
+ mPipeFd = -1;
}
return std::vector<uint8_t>();
@@ -78,11 +80,8 @@
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 (mPipeFd != -1) {
+ retVal = qemu_pipe_frame_send(mPipeFd, data.data(), data.size());
}
if (retVal < 0) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
index bcd32d0..c8eabb8 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PipeComm.h
@@ -19,7 +19,7 @@
#include <mutex>
#include <vector>
-#include "CommBase.h"
+#include "CommConn.h"
namespace android {
namespace hardware {
@@ -30,38 +30,25 @@
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 {
-public:
- PipeComm();
+class PipeComm : public CommConn {
+ public:
+ 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;
-private:
- std::mutex mMutex;
+ inline bool isOpen() override { return mPipeFd > 0; }
+
+ private:
int mPipeFd;
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
index 42c1c78..9eb8894 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.cpp
@@ -18,6 +18,7 @@
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <android/log.h>
+#include <arpa/inet.h>
#include <log/log.h>
#include <netinet/in.h>
#include <sys/socket.h>
@@ -35,45 +36,46 @@
namespace impl {
-SocketComm::SocketComm() {
- // Initialize member vars
- mCurSockFd = -1;
- mExit = 0;
- mSockFd = -1;
-}
-
+SocketComm::SocketComm(MessageProcessor* messageProcessor)
+ : mListenFd(-1), mMessageProcessor(messageProcessor) {}
SocketComm::~SocketComm() {
- stop();
}
-int SocketComm::connect() {
- sockaddr_in cliAddr;
- socklen_t cliLen = sizeof(cliAddr);
- int cSockFd = accept(mSockFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
-
- if (cSockFd >= 0) {
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mCurSockFd = cSockFd;
- }
- ALOGD("%s: Incoming connection received on socket %d", __FUNCTION__, cSockFd);
- } else {
- cSockFd = -1;
+void SocketComm::start() {
+ if (!listen()) {
+ return;
}
- return cSockFd;
+ mListenThread = std::make_unique<std::thread>(std::bind(&SocketComm::listenThread, this));
}
-int SocketComm::open() {
+void SocketComm::stop() {
+ if (mListenFd > 0) {
+ ::close(mListenFd);
+ if (mListenThread->joinable()) {
+ mListenThread->join();
+ }
+ mListenFd = -1;
+ }
+}
+
+void SocketComm::sendMessage(emulator::EmulatorMessage const& msg) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) {
+ conn->sendMessage(msg);
+ }
+}
+
+bool SocketComm::listen() {
int retVal;
struct sockaddr_in servAddr;
- mSockFd = socket(AF_INET, SOCK_STREAM, 0);
- if (mSockFd < 0) {
- ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mSockFd, errno);
- mSockFd = -1;
- return -errno;
+ mListenFd = socket(AF_INET, SOCK_STREAM, 0);
+ if (mListenFd < 0) {
+ ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno);
+ mListenFd = -1;
+ return false;
}
memset(&servAddr, 0, sizeof(servAddr));
@@ -81,82 +83,114 @@
servAddr.sin_addr.s_addr = INADDR_ANY;
servAddr.sin_port = htons(DEBUG_SOCKET);
- retVal = bind(mSockFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
+ retVal = bind(mListenFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
if(retVal < 0) {
ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno);
+ close(mListenFd);
+ mListenFd = -1;
+ return false;
+ }
+
+ ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET);
+ ::listen(mListenFd, 1);
+ return true;
+}
+
+SocketConn* SocketComm::accept() {
+ sockaddr_in cliAddr;
+ socklen_t cliLen = sizeof(cliAddr);
+ int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
+
+ if (sfd > 0) {
+ char addr[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN);
+
+ ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port);
+ return new SocketConn(mMessageProcessor, sfd);
+ }
+
+ return nullptr;
+}
+
+void SocketComm::listenThread() {
+ while (true) {
+ SocketConn* conn = accept();
+ if (conn == nullptr) {
+ return;
+ }
+
+ conn->start();
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn));
+ }
+ }
+}
+
+/**
+ * Called occasionally to clean up connections that have been closed.
+ */
+void SocketComm::removeClosedConnections() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ std::remove_if(mOpenConnections.begin(), mOpenConnections.end(),
+ [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); });
+}
+
+SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd)
+ : CommConn(messageProcessor), mSockFd(sfd) {}
+
+/**
+ * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns
+ * an empty buffer, otherwise will return exactly the given number of bytes.
+ */
+std::vector<uint8_t> readExactly(int fd, int numBytes) {
+ std::vector<uint8_t> buffer(numBytes);
+ int totalRead = 0;
+ int offset = 0;
+ while (totalRead < numBytes) {
+ int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset);
+ if (numRead == 0) {
+ buffer.resize(0);
+ return buffer;
+ }
+
+ totalRead += numRead;
+ }
+ return buffer;
+}
+
+/**
+ * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns
+ * -1.
+ */
+int32_t readInt(int fd) {
+ std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t));
+ if (buffer.size() == 0) {
+ return -1;
+ }
+
+ int32_t value = *reinterpret_cast<int32_t*>(buffer.data());
+ return ntohl(value);
+}
+
+std::vector<uint8_t> SocketConn::read() {
+ int32_t msgSize = readInt(mSockFd);
+ if (msgSize <= 0) {
+ ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd);
+ return std::vector<uint8_t>();
+ }
+
+ return readExactly(mSockFd, msgSize);
+}
+
+void SocketConn::stop() {
+ if (mSockFd > 0) {
close(mSockFd);
mSockFd = -1;
- return -errno;
- }
-
- listen(mSockFd, 1);
-
- // Set the socket to be non-blocking so we can poll it continouously
- fcntl(mSockFd, F_SETFL, O_NONBLOCK);
-
- return 0;
-}
-
-std::vector<uint8_t> SocketComm::read() {
- int32_t msgSize;
- int numBytes = 0;
-
- // This is a variable length message.
- // Read the number of bytes to rx over the socket
- numBytes = ::read(mCurSockFd, &msgSize, sizeof(msgSize));
- msgSize = ntohl(msgSize);
-
- if (numBytes != sizeof(msgSize)) {
- // This happens when connection is closed
- ALOGD("%s: numBytes=%d, expected=4", __FUNCTION__, numBytes);
- ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mCurSockFd);
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mCurSockFd = -1;
- }
-
- return std::vector<uint8_t>();
- }
-
- std::vector<uint8_t> msg = std::vector<uint8_t>(msgSize);
-
- numBytes = ::read(mCurSockFd, msg.data(), msgSize);
-
- if ((numBytes == msgSize) && (msgSize > 0)) {
- // Received a message.
- return msg;
- } else {
- // This happens when connection is closed
- ALOGD("%s: numBytes=%d, msgSize=%d", __FUNCTION__, numBytes, msgSize);
- ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mCurSockFd);
- {
- std::lock_guard<std::mutex> lock(mMutex);
- mCurSockFd = -1;
- }
-
- return std::vector<uint8_t>();
}
}
-void SocketComm::stop() {
- if (mExit == 0) {
- std::lock_guard<std::mutex> lock(mMutex);
- mExit = 1;
-
- // Close emulator socket if it is open
- if (mCurSockFd != -1) {
- close(mCurSockFd);
- mCurSockFd = -1;
- }
-
- if (mSockFd != -1) {
- close(mSockFd);
- mSockFd = -1;
- }
- }
-}
-
-int SocketComm::write(const std::vector<uint8_t>& data) {
+int SocketConn::write(const std::vector<uint8_t>& data) {
static constexpr int MSG_HEADER_LEN = 4;
int retVal = 0;
union {
@@ -168,19 +202,17 @@
msgLen = static_cast<uint32_t>(data.size());
msgLen = htonl(msgLen);
- std::lock_guard<std::mutex> lock(mMutex);
- if (mCurSockFd != -1) {
- retVal = ::write(mCurSockFd, msgLenBytes, MSG_HEADER_LEN);
+ if (mSockFd > 0) {
+ retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN);
if (retVal == MSG_HEADER_LEN) {
- retVal = ::write(mCurSockFd, data.data(), data.size());
+ retVal = ::write(mSockFd, data.data(), data.size());
}
}
return retVal;
}
-
} // impl
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
index 12cfb29..88b852b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/SocketComm.h
@@ -18,8 +18,9 @@
#define android_hardware_automotive_vehicle_V2_0_impl_SocketComm_H_
#include <mutex>
+#include <thread>
#include <vector>
-#include "CommBase.h"
+#include "CommConn.h"
namespace android {
namespace hardware {
@@ -29,29 +30,60 @@
namespace impl {
+class SocketConn;
+
/**
- * SocketComm opens a socket via adb's TCP port forwarding to enable a Host PC to connect to
- * the VehicleHAL.
+ * SocketComm opens a socket, and listens for connections from clients. Typically the client will be
+ * adb's TCP port-forwarding to enable a host PC to connect to the VehicleHAL.
*/
-class SocketComm : public CommBase {
-public:
- SocketComm();
+class SocketComm {
+ public:
+ SocketComm(MessageProcessor* messageProcessor);
virtual ~SocketComm();
+ void start();
+ void stop();
+
/**
- * Creates a connection to the other side.
+ * Serialized and send the given message to all connected clients.
+ */
+ void sendMessage(emulator::EmulatorMessage const& msg);
+
+ private:
+ int mListenFd;
+ std::unique_ptr<std::thread> mListenThread;
+ std::vector<std::unique_ptr<SocketConn>> mOpenConnections;
+ MessageProcessor* mMessageProcessor;
+ std::mutex mMutex;
+
+ /**
+ * Opens the socket and begins listening.
+ *
+ * @return bool Returns true on success.
+ */
+ bool listen();
+
+ /**
+ * Blocks and waits for a connection from a client, returns a new SocketConn with the connection
+ * or null, if the connection has been closed.
*
* @return int Returns fd or socket number if connection is successful.
* Otherwise, returns -1 if no connection is availble.
*/
- int connect() override;
+ SocketConn* accept();
- /**
- * Opens a socket and begins listening.
- *
- * @return int Returns 0 on success.
- */
- int open() override;
+ void listenThread();
+
+ void removeClosedConnections();
+};
+
+/**
+ * SocketConn represents a single connection to a client.
+ */
+class SocketConn : public CommConn {
+ public:
+ SocketConn(MessageProcessor* messageProcessor, int sfd);
+ virtual ~SocketConn() = default;
/**
* Blocking call to read data from the connection.
@@ -75,10 +107,9 @@
*/
int write(const std::vector<uint8_t>& data) override;
-private:
- int mCurSockFd;
- std::atomic<int> mExit;
- std::mutex mMutex;
+ inline bool isOpen() override { return mSockFd > 0; }
+
+ private:
int mSockFd;
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
index bf7be09..356a6b9 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "VehicleEmulator_v2_0"
#include <android/log.h>
-#include <algorithm>
#include <android-base/properties.h>
+#include <log/log.h>
#include <utils/SystemClock.h>
+#include <algorithm>
#include <vhal_v2_0/VehicleUtils.h>
@@ -35,32 +36,45 @@
namespace impl {
-std::unique_ptr<CommBase> CommFactory::create() {
- bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
+VehicleEmulator::VehicleEmulator(EmulatedVehicleHalIface* hal) : mHal{hal} {
+ mHal->registerEmulator(this);
- if (isEmulator) {
- return std::make_unique<PipeComm>();
- } else {
- return std::make_unique<SocketComm>();
+ ALOGI("Starting SocketComm");
+ mSocketComm = std::make_unique<SocketComm>(this);
+ mSocketComm->start();
+
+ if (android::base::GetBoolProperty("ro.kernel.qemu", false)) {
+ ALOGI("Starting PipeComm");
+ mPipeComm = std::make_unique<PipeComm>(this);
+ mPipeComm->start();
}
}
VehicleEmulator::~VehicleEmulator() {
- mExit = true; // Notify thread to finish and wait for it to terminate.
- mComm->stop(); // Close emulator socket if it is open.
- if (mThread.joinable()) mThread.join();
+ mSocketComm->stop();
+ if (mPipeComm) {
+ mPipeComm->stop();
+ }
}
+/**
+ * This is called by the HAL when a property changes. We need to notify our clients that it has
+ * changed.
+ */
void VehicleEmulator::doSetValueFromClient(const VehiclePropValue& propValue) {
emulator::EmulatorMessage msg;
emulator::VehiclePropValue *val = msg.add_value();
populateProtoVehiclePropValue(val, &propValue);
msg.set_status(emulator::RESULT_OK);
msg.set_msg_type(emulator::SET_PROPERTY_ASYNC);
- txMsg(msg);
+
+ mSocketComm->sendMessage(msg);
+ if (mPipeComm) {
+ mPipeComm->sendMessage(msg);
+ }
}
-void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg,
+void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage const& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg) {
std::vector<VehiclePropConfig> configs = mHal->listProperties();
emulator::VehiclePropGet getProp = rxMsg.prop(0);
@@ -79,7 +93,7 @@
}
}
-void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
VehicleEmulator::EmulatorMessage& respMsg) {
std::vector<VehiclePropConfig> configs = mHal->listProperties();
@@ -92,8 +106,8 @@
}
}
-void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
- VehicleEmulator::EmulatorMessage& respMsg) {
+void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
+ VehicleEmulator::EmulatorMessage& respMsg) {
int32_t areaId = 0;
emulator::VehiclePropGet getProp = rxMsg.prop(0);
int32_t propId = getProp.prop();
@@ -119,8 +133,8 @@
respMsg.set_status(status);
}
-void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
- VehicleEmulator::EmulatorMessage& respMsg) {
+void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage const& /* rxMsg */,
+ VehicleEmulator::EmulatorMessage& respMsg) {
respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
respMsg.set_status(emulator::RESULT_OK);
@@ -132,7 +146,7 @@
}
}
-void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage const& rxMsg,
VehicleEmulator::EmulatorMessage& respMsg) {
emulator::VehiclePropValue protoVal = rxMsg.value(0);
VehiclePropValue val = {
@@ -173,58 +187,28 @@
respMsg.set_status(halRes ? emulator::RESULT_OK : emulator::ERROR_INVALID_PROPERTY);
}
-void VehicleEmulator::txMsg(emulator::EmulatorMessage& txMsg) {
- int numBytes = txMsg.ByteSize();
- std::vector<uint8_t> msg(static_cast<size_t>(numBytes));
-
- if (!txMsg.SerializeToArray(msg.data(), static_cast<int32_t>(msg.size()))) {
- ALOGE("%s: SerializeToString failed!", __func__);
- return;
- }
-
- if (mExit) {
- ALOGW("%s: unable to transmit a message, connection closed", __func__);
- return;
- }
-
- // Send the message
- int retVal = mComm->write(msg);
- if (retVal < 0) {
- ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
- }
-}
-
-void VehicleEmulator::parseRxProtoBuf(std::vector<uint8_t>& msg) {
- emulator::EmulatorMessage rxMsg;
- emulator::EmulatorMessage respMsg;
-
- if (rxMsg.ParseFromArray(msg.data(), static_cast<int32_t>(msg.size()))) {
- switch (rxMsg.msg_type()) {
- case emulator::GET_CONFIG_CMD:
- doGetConfig(rxMsg, respMsg);
- break;
- case emulator::GET_CONFIG_ALL_CMD:
- doGetConfigAll(rxMsg, respMsg);
- break;
- case emulator::GET_PROPERTY_CMD:
- doGetProperty(rxMsg, respMsg);
- break;
- case emulator::GET_PROPERTY_ALL_CMD:
- doGetPropertyAll(rxMsg, respMsg);
- break;
- case emulator::SET_PROPERTY_CMD:
- doSetProperty(rxMsg, respMsg);
- break;
- default:
- ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
- respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
- break;
- }
-
- // Send the reply
- txMsg(respMsg);
- } else {
- ALOGE("%s: ParseFromString() failed. msgSize=%d", __func__, static_cast<int>(msg.size()));
+void VehicleEmulator::processMessage(emulator::EmulatorMessage const& rxMsg,
+ emulator::EmulatorMessage& respMsg) {
+ switch (rxMsg.msg_type()) {
+ case emulator::GET_CONFIG_CMD:
+ doGetConfig(rxMsg, respMsg);
+ break;
+ case emulator::GET_CONFIG_ALL_CMD:
+ doGetConfigAll(rxMsg, respMsg);
+ break;
+ case emulator::GET_PROPERTY_CMD:
+ doGetProperty(rxMsg, respMsg);
+ break;
+ case emulator::GET_PROPERTY_ALL_CMD:
+ doGetPropertyAll(rxMsg, respMsg);
+ break;
+ case emulator::SET_PROPERTY_CMD:
+ doSetProperty(rxMsg, respMsg);
+ break;
+ default:
+ ALOGW("%s: Unknown message received, type = %d", __func__, rxMsg.msg_type());
+ respMsg.set_status(emulator::ERROR_UNIMPLEMENTED_CMD);
+ break;
}
}
@@ -316,40 +300,6 @@
}
}
-void VehicleEmulator::rxMsg() {
- while (!mExit) {
- std::vector<uint8_t> msg = mComm->read();
-
- if (msg.size() > 0) {
- // Received a message.
- parseRxProtoBuf(msg);
- } else {
- // This happens when connection is closed
- ALOGD("%s: msgSize=%zu", __func__, msg.size());
- break;
- }
- }
-}
-
-void VehicleEmulator::rxThread() {
- if (mExit) return;
-
- int retVal = mComm->open();
- if (retVal != 0) mExit = true;
-
- // Comms are properly opened
- while (!mExit) {
- retVal = mComm->connect();
-
- if (retVal >= 0) {
- rxMsg();
- }
-
- // Check every 100ms for a new connection
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
-}
-
} // impl
} // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
index 1a8cfe2..58e387a 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.h
@@ -24,7 +24,9 @@
#include "vhal_v2_0/VehicleHal.h"
-#include "CommBase.h"
+#include "CommConn.h"
+#include "PipeComm.h"
+#include "SocketComm.h"
#include "VehicleHalProto.pb.h"
namespace android {
@@ -61,48 +63,36 @@
VehicleEmulator* mEmulator;
};
-struct CommFactory {
- static std::unique_ptr<CommBase> create();
-};
-
/**
* Emulates vehicle by providing controlling interface from host side either through ADB or Pipe.
*/
-class VehicleEmulator {
-public:
- VehicleEmulator(EmulatedVehicleHalIface* hal,
- std::unique_ptr<CommBase> comm = CommFactory::create())
- : mHal { hal },
- mComm(comm.release()),
- mThread { &VehicleEmulator::rxThread, this} {
- mHal->registerEmulator(this);
- }
+class VehicleEmulator : public MessageProcessor {
+ public:
+ VehicleEmulator(EmulatedVehicleHalIface* hal);
virtual ~VehicleEmulator();
void doSetValueFromClient(const VehiclePropValue& propValue);
+ void processMessage(emulator::EmulatorMessage const& rxMsg,
+ emulator::EmulatorMessage& respMsg) override;
-private:
+ private:
+ friend class ConnectionThread;
using EmulatorMessage = emulator::EmulatorMessage;
- void doGetConfig(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
- void doGetConfigAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
- void doGetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
- void doGetPropertyAll(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
- void doSetProperty(EmulatorMessage& rxMsg, EmulatorMessage& respMsg);
- void txMsg(emulator::EmulatorMessage& txMsg);
- void parseRxProtoBuf(std::vector<uint8_t>& msg);
+ void doGetConfig(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
+ void doGetConfigAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
+ void doGetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
+ void doGetPropertyAll(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
+ void doSetProperty(EmulatorMessage const& rxMsg, EmulatorMessage& respMsg);
void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
const VehiclePropConfig& cfg);
void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
const VehiclePropValue* val);
- void rxMsg();
- void rxThread();
private:
- std::atomic<bool> mExit { false };
EmulatedVehicleHalIface* mHal;
- std::unique_ptr<CommBase> mComm;
- std::thread mThread;
+ std::unique_ptr<SocketComm> mSocketComm;
+ std::unique_ptr<PipeComm> mPipeComm;
};
} // impl
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
new file mode 100644
index 0000000..61bf247
--- /dev/null
+++ b/biometrics/face/1.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.biometrics.face@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IBiometricsFace.hal",
+ "IBiometricsFaceClientCallback.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "FaceAcquiredInfo",
+ "FaceError",
+ "OptionalUint64",
+ "Status",
+ "UserHandle",
+ ],
+ gen_java: true,
+}
+
diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal
new file mode 100644
index 0000000..fbdb210
--- /dev/null
+++ b/biometrics/face/1.0/IBiometricsFace.hal
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+import IBiometricsFaceClientCallback;
+
+// TODO(b/78538290): Update comments with state machine transitions when ready.
+// TODO(b/78537981): Update comments with callback interaction contract.
+// TODO(b/79496983): Update comments with status returns fully enumerated.
+/**
+ * The HAL interface for biometric face authentication.
+ */
+interface IBiometricsFace {
+
+ /**
+ * Sets the current client callback.
+ *
+ * Registers a user function that must receive notifications from the HAL.
+ * There is usually only one client (FaceService). This call must block
+ * if the HAL state machine is in busy state until the HAL leaves the
+ * busy state.
+ *
+ * All callback methods pass a deviceId to differentiate callback
+ * invocations in the case where multiple sensors exist.
+ *
+ * @param clientCallback The client defined callback to register.
+ * @return result, with its "value" parameter representing a "deviceId",
+ * which must be unique for a given sensor.
+ */
+ @callflow(next={"setActiveUser"})
+ @entry
+ setCallback(IBiometricsFaceClientCallback clientCallback)
+ generates (OptionalUint64 result);
+
+ /**
+ * Sets the active user, which all subsequent HAL operations are applied to.
+ *
+ * HAL service implementors must ensure that operations are restricted to
+ * the given user. Clients must not call any part of this interface, except
+ * for setCallback(), without first having set an active user. The
+ * implementation is responsible for cancelling the current operation and
+ * returning to the idle state. Calling this method with the same userId
+ * should have no effect on the state machine.
+ *
+ * @param userId A non-negative user identifier that must be unique and
+ * persistent for a given user.
+ * @param storePath filesystem path to the template storage directory.
+ */
+ @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"})
+ setActiveUser(int32_t userId, string storePath) generates (Status status);
+
+ /**
+ * Begins a pre-enrollment request.
+ *
+ * Generates a unique and cryptographically secure random token used to
+ * indicate the start of an enrollment transaction. preEnroll() and
+ * postEnroll() specify a pin/pattern/password cleared time window where
+ * enrollment is allowed.
+ *
+ * preEnroll() generates a challenge which must then be wrapped by the
+ * gatekeeper after verifying a successful strong authentication attempt,
+ * which generates a Hardware Authentication Token. The challenge prevents
+ * spoofing and replay attacks and ensures that we only update a user’s face
+ * template if the operation was preceded by some kind of strong credential
+ * confirmation (e.g. device password).
+ *
+ * @return result, with its "value" parameter representing a "challenge": a
+ * unique and cryptographically secure random token.
+ */
+ @callflow(next={"enroll", "postEnroll"})
+ preEnroll() generates (OptionalUint64 result);
+
+ /**
+ * Enrolls a user's face.
+ *
+ * Note that this interface permits implementations where multiple faces can
+ * be enrolled for a single user. However, allowing multiple faces to be
+ * enrolled can be a severe security vulnerability and hence, most
+ * implementations must ensure that only a single face be enrolled at a
+ * given time. Multi-enrollment must only be used where there is a clear
+ * necessity for a shared use case, e.g. TVs or cars.
+ *
+ * Note that the Hardware Authentication Token must still be valid after
+ * this call, and must be explicitly invalidated by a call to postEnroll().
+ * This allows clients to immediately reattempt enrollment (for example, if
+ * a user wasn’t satisfied with their enrollment) without having to go
+ * through another strong authentication flow.
+ *
+ * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
+ * method.
+ *
+ * @param hat A valid Hardware Authentication Token, generated as a result
+ * of a preEnroll() challenge being wrapped by the gatekeeper after a
+ * sucessful strong authentication request.
+ * @param timeoutSec A timeout in seconds, after which this enrollment
+ * attempt is cancelled. Note that the client still needs to
+ * call postEnroll() to terminate the enrollment session.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"cancel", "enroll", "postEnroll", "remove"})
+ enroll(vec<uint8_t> hat, uint32_t timeoutSec) generates (Status status);
+
+ /**
+ * Finishes the enrollment session and invalidates the challenge generated
+ * by preEnroll().
+ *
+ * Clients must call this method once enrollment is complete, and the user's
+ * face template no longer needs to be updated.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"authenticate", "setActiveUser", "enumerate", "remove"})
+ postEnroll() generates (Status status);
+
+ /**
+ * Returns an identifier associated with the current face set.
+ *
+ * The authenticator ID must change whenever a new face is enrolled. The
+ * authenticator ID must not be changed when a face is deleted. The
+ * authenticator ID must be an entropy-encoded random number which all
+ * current templates are tied to. The authenticator ID must be immutable
+ * outside of an active enrollment window to prevent replay attacks.
+ *
+ * @return result, with its value parameter representing an
+ * "authenticatorId": an identifier associated to the user's current
+ * face enrollment.
+ */
+ @callflow(next={"authenticate"})
+ getAuthenticatorId() generates (OptionalUint64 result);
+
+ /**
+ * Cancels a pending enrollment or authentication request.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"authenticate", "enroll", "enumerate", "remove",
+ "setActiveUser"})
+ cancel() generates (Status status);
+
+ /**
+ * Enumerates all face templates associated with the active user.
+ *
+ * The onEnumerate() callback method is invoked once for each face template
+ * found.
+ *
+ * @return status The status of this method call.
+ */
+ @callflow(next={"remove", "enroll", "authenticate", "setActiveUser"})
+ enumerate() generates (Status status);
+
+ /**
+ * Removes a face template or all face templates associated with the active
+ * user.
+ *
+ * This method triggers the IBiometricsFaceClientCallback#onRemoved() method.
+ *
+ * @param faceId The id correpsonding to the face to be removed; or 0 if all
+ * faces are to be removed.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"enumerate", "authenticate", "cancel", "getAuthenticatorId",
+ "setActiveUser"})
+ remove(uint32_t faceId) generates (Status status);
+
+ /**
+ * Authenticates the active user.
+ *
+ * An optional operationId can be specified as a token from the transaction
+ * being authorized.
+ *
+ * @param operationId A non-zero operation id associated with a crypto
+ * object instance; or 0 if not being used.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"cancel", "preEnroll", "remove"})
+ authenticate(uint64_t operationId) generates (Status status);
+};
diff --git a/biometrics/face/1.0/IBiometricsFaceClientCallback.hal b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
new file mode 100644
index 0000000..93848c5
--- /dev/null
+++ b/biometrics/face/1.0/IBiometricsFaceClientCallback.hal
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+/**
+ * This callback interface is used by clients to recieve updates from the face
+ * HAL.
+ */
+interface IBiometricsFaceClientCallback {
+
+ /**
+ * A callback invoked when one enrollment step has been completed.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this enrollment step.
+ * @param faceId The id of the face template being enrolled.
+ * @param userId The active user id for the template being enrolled.
+ * @param remaining The number of remaining steps before enrolllment is
+ * complete or 0 if enrollment has completed successfully.
+ */
+ oneway onEnrollResult(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ uint32_t remaining);
+
+ /**
+ * A callback invoked when a face has been successfully authenticated.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this autentication attempt.
+ * @param faceId The id of the face template that passed the authentication
+ * challenge.
+ * @param userId The active user id for the authenticated face.
+ * @param token The hardware authentication token associated with this
+ * authenticate operation.
+ */
+ oneway onAuthenticated(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ vec<uint8_t> token);
+
+ /**
+ * A callback invoked when a face is acquired.
+ *
+ * If a non-critical, recoverable error occurs during an enrollment or
+ * authentication attempt, the HAL implementation must invoke this callback
+ * to allow clients to inform the user that some actionable change must be
+ * made.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that acquired a face.
+ * @param userId The id of the active user associated with the attempted
+ * face acquisition.
+ * @param acquiredInfo A message about the quality of the acquired image.
+ * @param vendorCode An optional vendor-specific message. This is only valid
+ * when acquiredInfo == FaceAcquiredInfo.VENDOR. This message is opaque
+ * to the framework, and vendors must provide code to handle it. For
+ * example this can be used to guide enrollment in Settings or provide
+ * a message during authentication that is vendor-specific. The vendor
+ * is expected to provide help strings to cover all known values.
+ */
+ oneway onAcquired(uint64_t deviceId, int32_t userId,
+ FaceAcquiredInfo acquiredInfo, int32_t vendorCode);
+
+ /**
+ * A callback invoked when an error has occured.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service where this error occured.
+ * @param userId The id of the active user when the error occured, or
+ * UserHandle::NONE if an active user had not been set yet.
+ * @param error A message about the error that occurred.
+ * @param vendorCode An optional, vendor-speicifc error message. Only valid
+ * when error == FaceError.VENDOR. This message is opaque to the
+ * framework, and vendors must provide code to handle it. For example,
+ * this scan be used to show the user an error message specific to the
+ * device. The vendor is expected to provide error strings to cover
+ * all known values.
+ */
+ oneway onError(uint64_t deviceId, int32_t userId, FaceError error,
+ int32_t vendorCode);
+
+ /**
+ * A callback invoked when a face template has been removed.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this removal.
+ * @param faceId The id of the face template that was removed.
+ * @param userId The active user id for the removed face template.
+ * @param remaining The number of face templates remaining after this
+ * removal, or 0 if there are no more.
+ */
+ oneway onRemoved(uint64_t deviceId, uint32_t faceId, int32_t userId,
+ uint32_t remaining);
+
+ /**
+ * A callback invoked to enumerate all current face templates.
+ *
+ * @param deviceId A unique id associated with the HAL implementation
+ * service that processed this enumeration.
+ * @param faceIds A list of ids of all currently enrolled face templates.
+ * @param userId The active user id for the enumerated face template.
+ */
+ oneway onEnumerate(uint64_t deviceId, vec<uint32_t> faceIds,
+ int32_t userId);
+};
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
new file mode 100644
index 0000000..08af919
--- /dev/null
+++ b/biometrics/face/1.0/types.hal
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face@1.0;
+
+/*
+ * In the event setActiveUser is not called, all error messages will return
+ * this userId.
+ */
+enum UserHandle : int32_t {
+ NONE = -1
+};
+
+/**
+ * Status codes returned directly by the HIDL method calls upon critical errors
+ * where the callback cannot be invoked. Most errors should sent through the
+ * onError callback using one of the FaceErrors below.
+ */
+enum Status : uint32_t {
+ /**
+ * The method was invoked successfully.
+ */
+ OK = 0,
+
+ /**
+ * One of the arguments to the method call is invalid.
+ */
+ ILLEGAL_ARGUMENT = 1,
+
+ /**
+ * This face HAL does not support this operation.
+ */
+ OPERATION_NOT_SUPPORTED = 2,
+
+ /**
+ * The HAL has encountered an internal error and cannot complete the request.
+ */
+ INTERNAL_ERROR = 3
+};
+
+/**
+ * Face errors represent events that can't be immediately recovered by user
+ * intervention. These are returned in the onError callback.
+ *
+ * Upon receiving a face error, clients must terminate the current operation and
+ * notify the user where possible.
+ */
+enum FaceError : int32_t {
+
+ /**
+ * A hardware error has occured that cannot be resolved. Try again later.
+ */
+ HW_UNAVAILABLE = 1,
+
+ /**
+ * The current enroll or authenticate operation could not be completed;
+ * the sensor was unable to process the current image.
+ */
+ UNABLE_TO_PROCESS = 2,
+
+ /**
+ * The current operation took too long to complete. This is intended to
+ * prevent programs from blocking the face HAL indefinitely. The timeout is
+ * framework and sensor-specific, but is generally on the order of 30
+ * seconds.
+ */
+ TIMEOUT = 3,
+
+ /**
+ * The current operation could not be completed because there is not enough
+ * storage space remaining to do so.
+ */
+ NO_SPACE = 4,
+
+ /**
+ * The current operation has been cancelled. This may happen if a new
+ * request (authenticate, remove) is initiated while an on-going operation
+ * is in progress, or if cancel() was called.
+ */
+ CANCELED = 5,
+
+ /**
+ * The current remove operation could not be completed; the face template
+ * provided could not be removed.
+ */
+ UNABLE_TO_REMOVE = 6,
+
+ /**
+ * Face authentication is locked out due to too many unsuccessful attempts.
+ */
+ LOCKOUT = 7,
+
+ /**
+ * Used to enable a vendor-specific error message.
+ */
+ VENDOR = 8,
+};
+
+/**
+ * Face acquisition information provides feedback for the current enrollment
+ * or authentication operation.
+ *
+ * This information indicates that the user can take immediate action to resolve
+ * an issue, and clients must ensure that this information is surfaced to the
+ * user.
+ */
+enum FaceAcquiredInfo : int32_t {
+
+ /**
+ * The face acquired was good; no further user interaction is necessary.
+ */
+ GOOD = 0,
+
+ /**
+ * The face data acquired was too noisy or did not have sufficient detail.
+ * This is a catch-all for all acquisition errors not captured by the other
+ * constants.
+ */
+ INSUFFICIENT = 1,
+
+ /**
+ * Because there was too much ambient light, the captured face data was too
+ * bright. It's reasonable to return this after multiple
+ * FaceAcquiredInfo.INSUFFICIENT.
+ *
+ * The user is expected to take action to retry the operation in better
+ * lighting conditions when this is returned.
+ */
+ TOO_BRIGHT = 2,
+
+ /**
+ * Because there was not enough illumination, the captured face data was too
+ * dark. It's reasonable to return this after multiple
+ * FaceAcquiredInfo.INSUFFICIENT.
+ *
+ * The user is expected to take action to retry the operation in better
+ * lighting conditions when this is returned.
+ */
+ TOO_DARK = 3,
+
+ /**
+ * The detected face is too close to the sensor, and the image cannot be
+ * processed.
+ *
+ * The user is expected to be informed to move further from the sensor when
+ * this is returned.
+ */
+ TOO_CLOSE = 4,
+
+ /**
+ * The detected face is too small, as the user might be too far away from
+ * the sensor.
+ *
+ * The user is expected to be informed to move closer to the sensor when
+ * this is returned.
+ */
+ TOO_FAR = 5,
+
+ /**
+ * Only the upper part of the face was detected. The sensor's field of view
+ * is too high.
+ *
+ * The user should be informed to move up with respect to the sensor when
+ * this is returned.
+ */
+ FACE_TOO_HIGH = 6,
+
+ /**
+ * Only the lower part of the face was detected. The sensor's field of view
+ * is too low.
+ *
+ * The user should be informed to move down with respect to the sensor when
+ * this is returned.
+ */
+ FACE_TOO_LOW = 7,
+
+ /**
+ * Only the right part of the face was detected. The sensor's field of view
+ * is too far right.
+ *
+ * The user should be informed to move to the right with respect to the
+ * sensor when this is returned.
+ */
+ FACE_TOO_RIGHT = 8,
+
+ /**
+ * Only the left part of the face was detected. The sensor's field of view
+ * is too far left.
+ *
+ * The user should be informed to move to the left with respect to the
+ * sensor when this is returned.
+ */
+ FACE_TOO_LEFT = 9,
+
+ /**
+ * The user's face was directed away from the sensor. The user should be
+ * informed to face the sensor when this is returned.
+ */
+ POOR_GAZE = 10,
+
+ /**
+ * No face was detected within the sensor's field of view.
+ *
+ * The user should be informed to point the sensor to a face when this is
+ * returned.
+ */
+ NOT_DETECTED = 11,
+
+ /**
+ * Too much motion was detected.
+ *
+ * The user should be informed to keep their face steady relative to the
+ * sensor.
+ */
+ TOO_MUCH_MOTION = 12,
+
+ /**
+ * The sensor needs to be recalibrated.
+ */
+ RECALIBRATE = 13,
+
+ /**
+ * Used to enable a vendor-specific acquisition message.
+ */
+ VENDOR = 14
+};
+
+/**
+ * Result structure with an additional uint64_t field. See documentation in
+ * setCallback(), preEnroll(), and getAuthenticatorId() for usage of the value.
+ */
+struct OptionalUint64 {
+ /**
+ * The return status.
+ */
+ Status status;
+
+ /**
+ * This value is only meaningful if status is OK.
+ */
+ uint64_t value;
+};
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index ee7ffaa..e093822 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -290,8 +290,14 @@
UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
// android.jpeg
- // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
- const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
+ const int32_t jpegAvailableThumbnailSizes[] = {0, 0,
+ 176, 144,
+ 240, 144,
+ 256, 144,
+ 240, 160,
+ 256, 154,
+ 240, 240,
+ 320, 240};
UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
ARRAY_SIZE(jpegAvailableThumbnailSizes));
@@ -787,7 +793,8 @@
std::vector<SupportedV4L2Format>
ExternalCameraDevice::getCandidateSupportedFormatsLocked(
int fd, CroppingType cropType,
- const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits) {
+ const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+ const Size& minStreamSize) {
std::vector<SupportedV4L2Format> outFmts;
struct v4l2_fmtdesc fmtdesc {
.index = 0,
@@ -822,6 +829,11 @@
if (frameSize.discrete.height > frameSize.discrete.width) {
continue;
}
+ // Discard all formats which is smaller than minStreamSize
+ if (frameSize.discrete.width < minStreamSize.width
+ || frameSize.discrete.height < minStreamSize.height) {
+ continue;
+ }
SupportedV4L2Format format {
.width = frameSize.discrete.width,
.height = frameSize.discrete.height,
@@ -864,9 +876,9 @@
void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
std::vector<SupportedV4L2Format> horizontalFmts =
- getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits);
+ getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize);
std::vector<SupportedV4L2Format> verticalFmts =
- getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits);
+ getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize);
size_t horiSize = horizontalFmts.size();
size_t vertSize = verticalFmts.size();
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 2e2f73b..680c95a 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -267,6 +267,15 @@
ret.fpsLimits = limits;
}
+ XMLElement *minStreamSize = deviceCfg->FirstChildElement("MinimumStreamSize");
+ if (minStreamSize == nullptr) {
+ ALOGI("%s: no minimum stream size specified", __FUNCTION__);
+ } else {
+ ret.minStreamSize = {
+ minStreamSize->UnsignedAttribute("width", /*Default*/0),
+ minStreamSize->UnsignedAttribute("height", /*Default*/0)};
+ }
+
ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d,"
" num video buffers %d, num still buffers %d",
__FUNCTION__, ret.maxJpegBufSize,
@@ -275,6 +284,8 @@
ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__,
limit.size.width, limit.size.height, limit.fpsUpperBound);
}
+ ALOGI("%s: minStreamSize: %dx%d" , __FUNCTION__,
+ ret.minStreamSize.width, ret.minStreamSize.height);
return ret;
}
@@ -285,6 +296,7 @@
fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0});
fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5});
fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0});
+ minStreamSize = {0, 0};
}
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index a52f0e4..ff0cfb3 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -96,7 +96,8 @@
// Get candidate supported formats list of input cropping type.
static std::vector<SupportedV4L2Format> getCandidateSupportedFormatsLocked(
int fd, CroppingType cropType,
- const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits);
+ const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+ const Size& minStreamSize);
// Trim supported format list by the cropping type. Also sort output formats by width/height
static void trimSupportedFormats(CroppingType cropType,
/*inout*/std::vector<SupportedV4L2Format>* pFmts);
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 37e7cfb..5754ccb 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -77,6 +77,9 @@
};
std::vector<FpsLimitation> fpsLimits;
+ // Minimum output stream size
+ Size minStreamSize;
+
private:
ExternalCameraConfig();
};
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index bf2e447..3051c53 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -70,6 +70,18 @@
include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := framework_compatibility_matrix.current.xml
+LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_CONFIG_DATA_PATHS := \
+ 4.4.0:$(my_kernel_config_data)/android-4.4 \
+ 4.9.0:$(my_kernel_config_data)/android-4.9 \
+ 4.14.0:$(my_kernel_config_data)/android-4.14 \
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
my_kernel_config_data :=
# Framework Compatibility Matrix (common to all FCM versions)
@@ -120,6 +132,7 @@
framework_compatibility_matrix.1.xml \
framework_compatibility_matrix.2.xml \
framework_compatibility_matrix.3.xml \
+ framework_compatibility_matrix.current.xml \
framework_compatibility_matrix.device.xml
# Phony target that installs all framework compatibility matrix files
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
new file mode 100644
index 0000000..f14fcea
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -0,0 +1,458 @@
+<compatibility-matrix version="1.0" type="framework" level="4">
+ <hal format="hidl" optional="false">
+ <name>android.hardware.audio</name>
+ <version>4.0</version>
+ <interface>
+ <name>IDevicesFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.audio.effect</name>
+ <version>4.0</version>
+ <interface>
+ <name>IEffectsFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.authsecret</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAuthSecret</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.audiocontrol</name>
+ <version>1.0</version>
+ <interface>
+ <name>IAudioControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.evs</name>
+ <version>1.0</version>
+ <interface>
+ <name>IEvsEnumerator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.automotive.vehicle</name>
+ <version>2.0</version>
+ <interface>
+ <name>IVehicle</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.biometrics.fingerprint</name>
+ <version>2.1</version>
+ <interface>
+ <name>IBiometricsFingerprint</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.bluetooth</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBluetoothHci</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.bluetooth.a2dp</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBluetoothAudioOffload</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.boot</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBootControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.broadcastradio</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IBroadcastRadioFactory</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.camera.provider</name>
+ <version>2.4</version>
+ <interface>
+ <name>ICameraProvider</name>
+ <regex-instance>[^/]+/[0-9]+</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.cas</name>
+ <version>1.0</version>
+ <interface>
+ <name>IMediaCasService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.configstore</name>
+ <version>1.1</version>
+ <interface>
+ <name>ISurfaceFlingerConfigs</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.confirmationui</name>
+ <version>1.0</version>
+ <interface>
+ <name>IConfirmationUI</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.contexthub</name>
+ <version>1.0</version>
+ <interface>
+ <name>IContexthub</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.drm</name>
+ <version>1.0</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.drm</name>
+ <version>1.1</version>
+ <interface>
+ <name>ICryptoFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ <interface>
+ <name>IDrmFactory</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.dumpstate</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDumpstateDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.gatekeeper</name>
+ <version>1.0</version>
+ <interface>
+ <name>IGatekeeper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.gnss</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IGnss</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.allocator</name>
+ <version>2.0</version>
+ <interface>
+ <name>IAllocator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.composer</name>
+ <version>2.1</version>
+ <interface>
+ <name>IComposer</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.graphics.mapper</name>
+ <version>2.0</version>
+ <interface>
+ <name>IMapper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.health</name>
+ <version>2.0</version>
+ <interface>
+ <name>IHealth</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.ir</name>
+ <version>1.0</version>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.keymaster</name>
+ <version>3.0</version>
+ <version>4.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.keymaster</name>
+ <version>4.0</version>
+ <interface>
+ <name>IKeymasterDevice</name>
+ <instance>strongbox</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.light</name>
+ <version>2.0</version>
+ <interface>
+ <name>ILight</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="false">
+ <name>android.hardware.media.omx</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOmx</name>
+ <instance>default</instance>
+ </interface>
+ <interface>
+ <name>IOmxStore</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.memtrack</name>
+ <version>1.0</version>
+ <interface>
+ <name>IMemtrack</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.neuralnetworks</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDevice</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.nfc</name>
+ <version>1.1</version>
+ <interface>
+ <name>INfc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.oemlock</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOemLock</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.power</name>
+ <version>1.0-3</version>
+ <interface>
+ <name>IPower</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.radio</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IRadio</name>
+ <instance>slot1</instance>
+ <instance>slot2</instance>
+ <instance>slot3</instance>
+ </interface>
+ <interface>
+ <name>ISap</name>
+ <instance>slot1</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.radio.config</name>
+ <version>1.0</version>
+ <interface>
+ <name>IRadioConfig</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.renderscript</name>
+ <version>1.0</version>
+ <interface>
+ <name>IDevice</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISecureElement</name>
+ <regex-instance>eSE[1-9][0-9]*</regex-instance>
+ <regex-instance>SIM[1-9][0-9]*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.sensors</name>
+ <version>1.0</version>
+ <interface>
+ <name>ISensors</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.soundtrigger</name>
+ <version>2.0-1</version>
+ <interface>
+ <name>ISoundTriggerHw</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tetheroffload.config</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffloadConfig</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tetheroffload.control</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffloadControl</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.thermal</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IThermal</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tv.cec</name>
+ <version>1.0</version>
+ <interface>
+ <name>IHdmiCec</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.tv.input</name>
+ <version>1.0</version>
+ <interface>
+ <name>ITvInput</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.usb</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>IUsb</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.usb.gadget</name>
+ <version>1.0</version>
+ <interface>
+ <name>IUsbGadget</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.vibrator</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IVibrator</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.vr</name>
+ <version>1.0</version>
+ <interface>
+ <name>IVr</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.weaver</name>
+ <version>1.0</version>
+ <interface>
+ <name>IWeaver</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi</name>
+ <version>1.0-2</version>
+ <interface>
+ <name>IWifi</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.hostapd</name>
+ <version>1.0</version>
+ <interface>
+ <name>IHostapd</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.offload</name>
+ <version>1.0</version>
+ <interface>
+ <name>IOffload</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
+ <name>android.hardware.wifi.supplicant</name>
+ <version>1.0-1</version>
+ <interface>
+ <name>ISupplicant</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</compatibility-matrix>
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index f9c868d..666653b 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -52,7 +52,6 @@
Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
uint32_t bufferId) {
sp<IMemory> hidlMemory = mapMemory(base);
- ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
// allow mapMemory to return nullptr
mSharedBufferMap[bufferId] = hidlMemory;
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 2f531b4..43a5378 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -25,21 +25,19 @@
namespace V2_1 {
namespace vts {
-Composer::Composer() {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
- init();
-}
+Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
-Composer::Composer(const std::string& name) {
- mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
- init();
-}
+Composer::Composer(const std::string& name)
+ : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name)) {}
-void Composer::init() {
- ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
+Composer::Composer(const sp<IComposer>& composer) : mComposer(composer) {
+ // ASSERT_* can only be used in functions returning void.
+ [this] {
+ ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
- std::vector<IComposer::Capability> capabilities = getCapabilities();
- mCapabilities.insert(capabilities.begin(), capabilities.end());
+ std::vector<IComposer::Capability> capabilities = getCapabilities();
+ mCapabilities.insert(capabilities.begin(), capabilities.end());
+ }();
}
sp<IComposer> Composer::getRaw() const {
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
index 8d5493e..c97be76 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h
@@ -57,10 +57,10 @@
std::unique_ptr<ComposerClient> createClient();
protected:
- sp<IComposer> mComposer;
+ explicit Composer(const sp<IComposer>& composer);
private:
- void init();
+ const sp<IComposer> mComposer;
std::unordered_set<IComposer::Capability> mCapabilities;
};
@@ -68,7 +68,7 @@
// A wrapper to IComposerClient.
class ComposerClient {
public:
- ComposerClient(const sp<IComposerClient>& client);
+ explicit ComposerClient(const sp<IComposerClient>& client);
~ComposerClient();
sp<IComposerClient> getRaw() const;
@@ -116,7 +116,7 @@
std::unordered_map<Display, DisplayResource> mDisplayResources;
private:
- sp<IComposerClient> mClient;
+ const sp<IComposerClient> mClient;
};
} // namespace vts
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 6a32071..f2596a4 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -27,32 +27,31 @@
namespace V2_2 {
namespace vts {
-using android::hardware::details::canCastInterface;
-using android::hardware::details::getDescriptor;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
+using details::canCastInterface;
+using details::getDescriptor;
-std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
- std::unique_ptr<ComposerClient_v2_2> client;
- mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+std::unique_ptr<ComposerClient> Composer::createClient() {
+ std::unique_ptr<ComposerClient> client;
+ getRaw()->createClient([&](const auto& tmpError, const auto& tmpClient) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
ALOGV("tmpClient is a %s", getDescriptor(&(*tmpClient)).c_str());
ASSERT_TRUE(canCastInterface(
&(*tmpClient), "android.hardware.graphics.composer@2.2::IComposerClient", false))
<< "Cannot create 2.2 IComposerClient";
- client = std::make_unique<ComposerClient_v2_2>(IComposerClient::castFrom(tmpClient, true));
+ client = std::make_unique<ComposerClient>(IComposerClient::castFrom(tmpClient, true));
});
return client;
}
-sp<V2_2::IComposerClient> ComposerClient_v2_2::getRaw() const {
- return mClient_v2_2;
+sp<IComposerClient> ComposerClient::getRaw() const {
+ return mClient;
}
-std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFrameMetadataKeys(
+std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient::getPerFrameMetadataKeys(
Display display) {
std::vector<IComposerClient::PerFrameMetadataKey> keys;
- mClient_v2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
+ mClient->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR metadata keys";
keys = tmpKeys;
});
@@ -60,43 +59,42 @@
return keys;
}
-void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader,
- V2_2::CommandWriterBase* writer) {
+void ComposerClient::execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer) {
bool queueChanged = false;
uint32_t commandLength = 0;
hidl_vec<hidl_handle> commandHandles;
ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
if (queueChanged) {
- auto ret = mClient_v2_2->setInputCommandQueue(*writer->getMQDescriptor());
+ auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
return;
}
- mClient_v2_2->executeCommands(commandLength, commandHandles,
- [&](const auto& tmpError, const auto& tmpOutQueueChanged,
- const auto& tmpOutLength, const auto& tmpOutHandles) {
- ASSERT_EQ(Error::NONE, tmpError);
+ mClient->executeCommands(commandLength, commandHandles,
+ [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+ const auto& tmpOutLength, const auto& tmpOutHandles) {
+ ASSERT_EQ(Error::NONE, tmpError);
- if (tmpOutQueueChanged) {
- mClient_v2_2->getOutputCommandQueue(
- [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError);
- reader->setMQDescriptor(tmpDescriptor);
- });
- }
+ if (tmpOutQueueChanged) {
+ mClient->getOutputCommandQueue(
+ [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ reader->setMQDescriptor(tmpDescriptor);
+ });
+ }
- ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
- reader->parse();
- });
+ ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+ reader->parse();
+ });
}
-Display ComposerClient_v2_2::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
- PixelFormat formatHint,
- uint32_t outputBufferSlotCount,
- PixelFormat* outFormat) {
+Display ComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
+ PixelFormat formatHint,
+ uint32_t outputBufferSlotCount,
+ PixelFormat* outFormat) {
Display display = 0;
- mClient_v2_2->createVirtualDisplay_2_2(
+ mClient->createVirtualDisplay_2_2(
width, height, formatHint, outputBufferSlotCount,
[&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
@@ -110,29 +108,27 @@
return display;
}
-bool ComposerClient_v2_2::getClientTargetSupport_2_2(Display display, uint32_t width,
- uint32_t height, PixelFormat format,
- Dataspace dataspace) {
- Error error =
- mClient_v2_2->getClientTargetSupport_2_2(display, width, height, format, dataspace);
+bool ComposerClient::getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+ PixelFormat format, Dataspace dataspace) {
+ Error error = mClient->getClientTargetSupport_2_2(display, width, height, format, dataspace);
return error == Error::NONE;
}
-void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) {
- Error error = mClient_v2_2->setPowerMode_2_2(display, mode);
+void ComposerClient::setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) {
+ Error error = mClient->setPowerMode_2_2(display, mode);
ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode";
}
-void ComposerClient_v2_2::setReadbackBuffer(Display display, const native_handle_t* buffer,
- int32_t /* releaseFence */) {
+void ComposerClient::setReadbackBuffer(Display display, const native_handle_t* buffer,
+ int32_t /* releaseFence */) {
// Ignoring fence, HIDL doesn't care
- Error error = mClient_v2_2->setReadbackBuffer(display, buffer, nullptr);
+ Error error = mClient->setReadbackBuffer(display, buffer, nullptr);
ASSERT_EQ(Error::NONE, error) << "failed to setReadbackBuffer";
}
-void ComposerClient_v2_2::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
- Dataspace* outDataspace) {
- mClient_v2_2->getReadbackBufferAttributes(
+void ComposerClient::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+ Dataspace* outDataspace) {
+ mClient->getReadbackBufferAttributes(
display,
[&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes";
@@ -141,42 +137,41 @@
});
}
-void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFence) {
+void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) {
hidl_handle handle;
- mClient_v2_2->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
+ mClient->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence";
handle = tmpHandle;
});
*outFence = 0;
}
-std::vector<ColorMode> ComposerClient_v2_2::getColorModes(Display display) {
+std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
std::vector<ColorMode> modes;
- mClient_v2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
+ mClient->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes";
modes = tmpModes;
});
return modes;
}
-std::vector<RenderIntent> ComposerClient_v2_2::getRenderIntents(Display display, ColorMode mode) {
+std::vector<RenderIntent> ComposerClient::getRenderIntents(Display display, ColorMode mode) {
std::vector<RenderIntent> intents;
- mClient_v2_2->getRenderIntents(
- display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
- intents = tmpIntents;
- });
+ mClient->getRenderIntents(display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
+ intents = tmpIntents;
+ });
return intents;
}
-void ComposerClient_v2_2::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
- Error error = mClient_v2_2->setColorMode_2_2(display, mode, intent);
+void ComposerClient::setColorMode(Display display, ColorMode mode, RenderIntent intent) {
+ Error error = mClient->setColorMode_2_2(display, mode, intent);
ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode";
}
-std::array<float, 16> ComposerClient_v2_2::getDataspaceSaturationMatrix(Dataspace dataspace) {
+std::array<float, 16> ComposerClient::getDataspaceSaturationMatrix(Dataspace dataspace) {
std::array<float, 16> matrix;
- mClient_v2_2->getDataspaceSaturationMatrix(
+ mClient->getDataspaceSaturationMatrix(
dataspace, [&](const auto& tmpError, const auto& tmpMatrix) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get datasapce saturation matrix";
std::copy_n(tmpMatrix.data(), matrix.size(), matrix.begin());
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 1c6d7ae..2633021 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -36,36 +36,31 @@
namespace V2_2 {
namespace vts {
-using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
-using android::hardware::graphics::common::V1_1::PixelFormat;
-using android::hardware::graphics::common::V1_1::RenderIntent;
-using android::hardware::graphics::composer::V2_2::IComposer;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
+using common::V1_0::Hdr;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
-class ComposerClient_v2_2;
+class ComposerClient;
-// Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
-// Everything else is the same
-class Composer_v2_2 : public V2_1::vts::Composer {
+// A wrapper to IComposer.
+class Composer : public V2_1::vts::Composer {
public:
- Composer_v2_2() : V2_1::vts::Composer(){};
- explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){};
+ using V2_1::vts::Composer::Composer;
- std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
+ std::unique_ptr<ComposerClient> createClient();
};
// A wrapper to IComposerClient.
-class ComposerClient_v2_2
- : public android::hardware::graphics::composer::V2_1::vts::ComposerClient {
+class ComposerClient : public V2_1::vts::ComposerClient {
public:
- ComposerClient_v2_2(const sp<IComposerClient>& client)
- : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
+ explicit ComposerClient(const sp<IComposerClient>& client)
+ : V2_1::vts::ComposerClient(client), mClient(client) {}
- sp<V2_2::IComposerClient> getRaw() const;
+ sp<IComposerClient> getRaw() const;
- void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+ void execute(V2_1::vts::TestCommandReader* reader, CommandWriterBase* writer);
std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
@@ -73,7 +68,7 @@
uint32_t outputBufferSlotCount, PixelFormat* outFormat);
bool getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
PixelFormat format, Dataspace dataspace);
- void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode);
+ void setPowerMode_2_2(Display display, IComposerClient::PowerMode mode);
void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
Dataspace* outDataspace);
@@ -86,7 +81,7 @@
std::array<float, 16> getDataspaceSaturationMatrix(Dataspace dataspace);
private:
- sp<V2_2::IComposerClient> mClient_v2_2;
+ const sp<IComposerClient> mClient;
};
} // namespace vts
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 23bf558..e3b7f55 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -32,17 +32,15 @@
namespace vts {
namespace {
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::ColorTransform;
-using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
-using android::hardware::graphics::common::V1_1::PixelFormat;
-using android::hardware::graphics::common::V1_1::RenderIntent;
-using android::hardware::graphics::composer::V2_2::IComposerClient;
-using android::hardware::graphics::mapper::V2_1::IMapper;
-using android::hardware::graphics::mapper::V2_1::vts::Gralloc;
-using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
+using common::V1_0::BufferUsage;
+using common::V1_0::ColorTransform;
+using common::V1_0::Transform;
+using common::V1_1::ColorMode;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using mapper::V2_1::IMapper;
+using mapper::V2_1::vts::Gralloc;
// Test environment for graphics.composer
class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
@@ -65,9 +63,9 @@
protected:
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(
- mComposer = std::make_unique<Composer_v2_2>(
+ mComposer = std::make_unique<Composer>(
GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
- ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
mComposerClient->registerCallback(mComposerCallback);
@@ -96,8 +94,8 @@
// use the slot count usually set by SF
static constexpr uint32_t kBufferSlotCount = 64;
- std::unique_ptr<Composer_v2_2> mComposer;
- std::unique_ptr<ComposerClient_v2_2> mComposerClient;
+ std::unique_ptr<Composer> mComposer;
+ std::unique_ptr<ComposerClient> mComposerClient;
sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
// the first display and is assumed never to be removed
Display mPrimaryDisplay;
@@ -125,7 +123,7 @@
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
- mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
+ mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<V2_1::vts::TestCommandReader>();
}
@@ -143,9 +141,9 @@
return mGralloc->allocate(info);
}
- void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
+ void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
- std::unique_ptr<V2_2::CommandWriterBase> mWriter;
+ std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
private:
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
new file mode 100644
index 0000000..23061dd
--- /dev/null
+++ b/graphics/composer/2.3/Android.bp
@@ -0,0 +1,21 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.graphics.composer@2.3",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IComposer.hal",
+ "IComposerClient.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/graphics/composer/2.3/IComposer.hal b/graphics/composer/2.3/IComposer.hal
new file mode 100644
index 0000000..90b2427
--- /dev/null
+++ b/graphics/composer/2.3/IComposer.hal
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.3;
+
+import IComposerClient;
+
+import @2.1::Error;
+import @2.2::IComposer;
+
+interface IComposer extends @2.2::IComposer {
+
+ /**
+ * Creates a v2.3 client of the composer. Supersedes @2.1::createClient.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * NO_RESOURCES when the client could not be created.
+ * @return client is the newly created client.
+ */
+ @entry
+ @callflow(next="*")
+ createClient_2_3() generates (Error error, IComposerClient client);
+
+};
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
new file mode 100644
index 0000000..77dd3ee
--- /dev/null
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.3;
+
+import @2.2::IComposerClient;
+import @2.1::Display;
+import @2.1::Error;
+
+interface IComposerClient extends @2.2::IComposerClient {
+
+ /**
+ * Returns the port and data that describe a physical display. The port is
+ * a unique number that identifies a physical connector (e.g. eDP, HDMI)
+ * for display output. The data blob is parsed to determine its format,
+ * typically EDID 1.3 as specified in VESA E-EDID Standard Release A
+ * Revision 1.
+ *
+ * @param display is the display to query.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when an invalid display handle was passed in.
+ * UNSUPPORTED when identification data is unavailable.
+ * @return port is the connector to which the display is connected.
+ * @return data is the EDID 1.3 blob identifying the display.
+ */
+ @callflow(next="*")
+ getDisplayIdentificationData(Display display)
+ generates (Error error,
+ uint8_t port,
+ vec<uint8_t> data);
+
+};
diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp
new file mode 100644
index 0000000..ad49ec3
--- /dev/null
+++ b/graphics/composer/2.3/default/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+
+cc_binary {
+ name: "android.hardware.graphics.composer@2.3-service",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.3-service.rc"],
+ header_libs: [
+ "android.hardware.graphics.composer@2.3-passthrough",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.graphics.mapper@2.0",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
diff --git a/graphics/composer/2.3/default/OWNERS b/graphics/composer/2.3/default/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/composer/2.3/default/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
new file mode 100644
index 0000000..08e32d8
--- /dev/null
+++ b/graphics/composer/2.3/default/android.hardware.graphics.composer@2.3-service.rc
@@ -0,0 +1,6 @@
+service vendor.hwcomposer-2-3 /vendor/bin/hw/android.hardware.graphics.composer@2.3-service
+ class hal animation
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/graphics/composer/2.3/default/service.cpp b/graphics/composer/2.3/default/service.cpp
new file mode 100644
index 0000000..347d8be
--- /dev/null
+++ b/graphics/composer/2.3/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 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.
+ */
+
+#include <sched.h>
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <binder/ProcessState.h>
+#include <composer-passthrough/2.3/HwcLoader.h>
+#include <hidl/HidlTransportSupport.h>
+
+using android::hardware::graphics::composer::V2_3::IComposer;
+using android::hardware::graphics::composer::V2_3::passthrough::HwcLoader;
+
+int main() {
+ // the conventional HAL might start binder services
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+ android::ProcessState::self()->startThreadPool();
+
+ // same as SF main thread
+ struct sched_param param = {0};
+ param.sched_priority = 2;
+ if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO: %d", errno);
+ }
+
+ android::hardware::configureRpcThreadpool(4, true /* will join */);
+
+ android::sp<IComposer> composer = HwcLoader::load();
+ if (composer == nullptr) {
+ return 1;
+ }
+ if (composer->registerAsService() != android::NO_ERROR) {
+ ALOGE("failed to register service");
+ return 1;
+ }
+
+ android::hardware::joinRpcThreadpool();
+
+ ALOGE("service is terminating");
+ return 1;
+}
diff --git a/graphics/composer/2.3/utils/OWNERS b/graphics/composer/2.3/utils/OWNERS
new file mode 100644
index 0000000..234bc75
--- /dev/null
+++ b/graphics/composer/2.3/utils/OWNERS
@@ -0,0 +1,7 @@
+# Graphics team
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp
new file mode 100644
index 0000000..aa46df1
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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.
+//
+
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.3-hal",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.3",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.graphics.composer@2.3",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h
new file mode 100644
index 0000000..8e11a5a
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/Composer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Composer.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <composer-hal/2.2/Composer.h>
+#include <composer-hal/2.3/ComposerClient.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+namespace detail {
+
+// ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerImpl : public V2_2::hal::detail::ComposerImpl<Interface, Hal> {
+ public:
+ static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) {
+ return std::make_unique<ComposerImpl>(std::move(hal));
+ }
+
+ explicit ComposerImpl(std::unique_ptr<Hal> hal) : BaseType2_2(std::move(hal)) {}
+
+ // IComposer 2.3 interface
+
+ Return<void> createClient_2_3(IComposer::createClient_2_3_cb hidl_cb) override {
+ std::unique_lock<std::mutex> lock(mClientMutex);
+ if (!waitForClientDestroyedLocked(lock)) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ sp<ComposerClient> client = ComposerClient::create(mHal.get()).release();
+ if (!client) {
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ auto clientDestroyed = [this]() { onClientDestroyed(); };
+ client->setOnClientDestroyed(clientDestroyed);
+
+ mClient = client;
+ hidl_cb(Error::NONE, client);
+ return Void();
+ }
+
+ private:
+ using BaseType2_2 = V2_2::hal::detail::ComposerImpl<Interface, Hal>;
+ using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>;
+
+ using BaseType2_1::mClient;
+ using BaseType2_1::mClientMutex;
+ using BaseType2_1::mHal;
+ using BaseType2_1::onClientDestroyed;
+ using BaseType2_1::waitForClientDestroyedLocked;
+};
+
+} // namespace detail
+
+using Composer = detail::ComposerImpl<IComposer, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
new file mode 100644
index 0000000..e717d84
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "ComposerClient.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-hal/2.3/ComposerClient.h>
+#include <composer-hal/2.3/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+namespace detail {
+
+// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
+template <typename Interface, typename Hal>
+class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl<Interface, Hal> {
+ public:
+ static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
+ auto client = std::make_unique<ComposerClientImpl>(hal);
+ return client->init() ? std::move(client) : nullptr;
+ }
+
+ ComposerClientImpl(Hal* hal) : BaseType2_2(hal) {}
+
+ // IComposerClient 2.3 interface
+
+ Return<void> getDisplayIdentificationData(
+ Display display, IComposerClient::getDisplayIdentificationData_cb hidl_cb) override {
+ uint8_t port = 0;
+ std::vector<uint8_t> data;
+ Error error = mHal->getDisplayIdentificationData(display, &port, &data);
+ hidl_cb(error, port, data);
+ return Void();
+ }
+
+ private:
+ using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl<Interface, Hal>;
+ using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
+
+ using BaseType2_1::mHal;
+};
+
+} // namespace detail
+
+using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
new file mode 100644
index 0000000..37ea0a3
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <composer-hal/2.2/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+using V2_1::Display;
+using V2_1::Error;
+
+class ComposerHal : public V2_2::hal::ComposerHal {
+ public:
+ virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) = 0;
+};
+
+} // namespace hal
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/passthrough/Android.bp b/graphics/composer/2.3/utils/passthrough/Android.bp
new file mode 100644
index 0000000..3ae6b16
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/Android.bp
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.3-passthrough",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ header_libs: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-passthrough",
+ "android.hardware.graphics.composer@2.3-hal",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
new file mode 100644
index 0000000..53f2d1b
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcHal.h included without LOG_TAG"
+#endif
+
+#include <type_traits>
+
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+namespace detail {
+
+using V2_1::Display;
+using V2_1::Error;
+
+// HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2
+template <typename Hal>
+class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
+ public:
+ Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) override {
+ if (!mDispatch.getDisplayIdentificationData) {
+ return Error::UNSUPPORTED;
+ }
+
+ uint32_t size = 0;
+ int32_t error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, nullptr);
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ std::vector<uint8_t> data(size);
+ error =
+ mDispatch.getDisplayIdentificationData(mDevice, display, outPort, &size, data.data());
+ if (error != HWC2_ERROR_NONE) {
+ return static_cast<Error>(error);
+ }
+
+ data.resize(size);
+ *outData = std::move(data);
+ return Error::NONE;
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_2::initDispatch()) {
+ return false;
+ }
+
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
+ &mDispatch.getDisplayIdentificationData);
+ return true;
+ }
+
+ private:
+ struct {
+ HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
+ } mDispatch = {};
+
+ using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
+ using BaseType2_1::mDevice;
+};
+
+} // namespace detail
+
+using HwcHal = detail::HwcHalImpl<hal::ComposerHal>;
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
new file mode 100644
index 0000000..afef475
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "HwcLoader.h included without LOG_TAG"
+#endif
+
+#include <composer-hal/2.3/Composer.h>
+#include <composer-hal/2.3/ComposerHal.h>
+#include <composer-passthrough/2.2/HwcLoader.h>
+#include <composer-passthrough/2.3/HwcHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace passthrough {
+
+class HwcLoader : public V2_2::passthrough::HwcLoader {
+ public:
+ static IComposer* load() {
+ const hw_module_t* module = loadModule();
+ if (!module) {
+ return nullptr;
+ }
+
+ auto hal = createHalWithAdapter(module);
+ if (!hal) {
+ return nullptr;
+ }
+
+ return createComposer(std::move(hal)).release();
+ }
+
+ // create a ComposerHal instance
+ static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) {
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithModule(module) ? std::move(hal) : nullptr;
+ }
+
+ // create a ComposerHal instance, insert an adapter if necessary
+ static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
+ bool adapted;
+ hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
+ if (!device) {
+ return nullptr;
+ }
+ auto hal = std::make_unique<HwcHal>();
+ return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
+ }
+
+ // create an IComposer instance
+ static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) {
+ return hal::Composer::create(std::move(hal));
+ }
+};
+
+} // namespace passthrough
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
new file mode 100644
index 0000000..0553258
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -0,0 +1,41 @@
+//
+// 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.
+//
+
+cc_library_static {
+ name: "android.hardware.graphics.composer@2.3-vts",
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "ComposerVts.cpp",
+ ],
+ static_libs: [
+ "VtsHalHidlTargetTestBase",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.2-vts",
+ "android.hardware.graphics.composer@2.3",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+ cflags: [
+ "-O0",
+ "-g",
+ "-DLOG_TAG=\"ComposerVts\"",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
new file mode 100644
index 0000000..f1d3a50
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include <composer-vts/2.3/ComposerVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+
+using V2_1::Error;
+
+Composer::Composer() : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>()) {}
+
+Composer::Composer(const std::string& name)
+ : Composer(::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name)) {}
+
+Composer::Composer(const sp<IComposer>& composer)
+ : V2_2::vts::Composer(composer), mComposer(composer) {}
+
+std::unique_ptr<ComposerClient> Composer::createClient() {
+ std::unique_ptr<ComposerClient> client;
+ mComposer->createClient_2_3([&client](const auto& tmpError, const auto& tmpClient) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+ client = std::make_unique<ComposerClient>(tmpClient);
+ });
+
+ return client;
+}
+
+bool ComposerClient::getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) {
+ bool supported = true;
+ mClient->getDisplayIdentificationData(
+ display, [&](const auto& tmpError, const auto& tmpPort, const auto& tmpData) {
+ if (tmpError == Error::UNSUPPORTED) {
+ supported = false;
+ return;
+ }
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get display identification data";
+
+ *outPort = tmpPort;
+ *outData = tmpData;
+ ASSERT_FALSE(outData->empty()) << "data is empty";
+ });
+
+ return supported;
+}
+
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
new file mode 100644
index 0000000..103b85a
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+
+using V2_1::Display;
+using V2_3::IComposer;
+using V2_3::IComposerClient;
+
+class ComposerClient;
+
+// A wrapper to IComposer.
+class Composer : public V2_2::vts::Composer {
+ public:
+ Composer();
+ explicit Composer(const std::string& name);
+
+ std::unique_ptr<ComposerClient> createClient();
+
+ protected:
+ explicit Composer(const sp<IComposer>& composer);
+
+ private:
+ const sp<IComposer> mComposer;
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient : public V2_2::vts::ComposerClient {
+ public:
+ explicit ComposerClient(const sp<IComposerClient>& client)
+ : V2_2::vts::ComposerClient(client), mClient(client) {}
+
+ bool getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData);
+
+ private:
+ const sp<IComposerClient> mClient;
+};
+
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
new file mode 100644
index 0000000..df696c9
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -0,0 +1,44 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "VtsHalGraphicsComposerV2_3TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalGraphicsComposerV2_3TargetTest.cpp"],
+
+ // TODO(b/64437680): Assume these libs are always available on the device.
+ shared_libs: [
+ "libfmq",
+ "libhidltransport",
+ "libsync",
+ ],
+ static_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.1-vts",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.2-vts",
+ "android.hardware.graphics.composer@2.3",
+ "android.hardware.graphics.composer@2.3-vts",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.0-vts",
+ "android.hardware.graphics.mapper@2.1",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+}
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
new file mode 100644
index 0000000..234bc75
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+# Graphics team
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
new file mode 100644
index 0000000..f4e34f0
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -0,0 +1,133 @@
+/*
+ * 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 "graphics_composer_hidl_hal_test@2.3"
+
+#include <algorithm>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.3/ComposerVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace vts {
+namespace {
+
+// Test environment for graphics.composer
+class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static GraphicsComposerHidlEnvironment* Instance() {
+ static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<IComposer>(); }
+
+ private:
+ GraphicsComposerHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
+};
+
+class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposer = std::make_unique<Composer>(
+ GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+
+ mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
+ mComposerClient->registerCallback(mComposerCallback);
+
+ // assume the first display is primary and is never removed
+ mPrimaryDisplay = waitForFirstDisplay();
+
+ // explicitly disable vsync
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerCallback->setVsyncAllowed(false);
+ }
+
+ void TearDown() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
+ }
+
+ std::unique_ptr<Composer> mComposer;
+ std::unique_ptr<ComposerClient> mComposerClient;
+ sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
+ // the first display and is assumed never to be removed
+ Display mPrimaryDisplay;
+
+ private:
+ Display waitForFirstDisplay() {
+ while (true) {
+ std::vector<Display> displays = mComposerCallback->getDisplays();
+ if (displays.empty()) {
+ usleep(5 * 1000);
+ continue;
+ }
+
+ return displays[0];
+ }
+ }
+};
+
+/**
+ * Test IComposerClient::getDisplayIdentificationData.
+ *
+ * TODO: Check that ports are unique for multiple displays.
+ */
+TEST_F(GraphicsComposerHidlTest, GetDisplayIdentificationData) {
+ uint8_t port0;
+ std::vector<uint8_t> data0;
+ if (mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port0, &data0)) {
+ uint8_t port1;
+ std::vector<uint8_t> data1;
+ ASSERT_TRUE(mComposerClient->getDisplayIdentificationData(mPrimaryDisplay, &port1, &data1));
+
+ ASSERT_EQ(port0, port1) << "ports are not stable";
+ ASSERT_TRUE(data0.size() == data1.size() &&
+ std::equal(data0.begin(), data0.end(), data1.begin()))
+ << "data is not stable";
+ }
+}
+
+} // namespace
+} // namespace vts
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ using android::hardware::graphics::composer::V2_3::vts::GraphicsComposerHidlEnvironment;
+ ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ return status;
+}
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 34a96a0..88a9e26 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -470,7 +470,7 @@
status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
OMX_StateExecuting);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index c1863d5..1575ba2 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -41,6 +41,8 @@
/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
* expects the events to be received within this duration */
#define DEFAULT_TIMEOUT 100000
+// b/70933963
+#define RELAXED_TIMEOUT 400000
/* Time interval between successive Input/Output enqueues */
#define DEFAULT_TIMEOUT_Q 2000
/* While the component is amidst a process call, asynchronous commands like
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 7750a12..4ddc833 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -1149,15 +1149,13 @@
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
// do not enable the port until all the buffers are supplied
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
- &pBuffer[0], &pBuffer[1]);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status,
android::hardware::media::omx::V1_0::Status::TIMED_OUT);
ASSERT_NO_FATAL_FAILURE(allocatePortBuffers(
omxNode, &pBuffer[i - portBase], i, portMode[i - portBase]));
- status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
- &pBuffer[0], &pBuffer[1]);
+ status = observer->dequeueMessage(&msg, RELAXED_TIMEOUT, &pBuffer[0], &pBuffer[1]);
ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
ASSERT_EQ(msg.type, Message::Type::EVENT);
ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/1.0/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/1.1/vts/functional/OWNERS b/wifi/1.1/vts/functional/OWNERS
deleted file mode 100644
index 2878acc..0000000
--- a/wifi/1.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-rpius@google.com
-quiche@google.com
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
index 3919690..8c5371b 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.2/default/Android.mk
@@ -107,11 +107,11 @@
LOCAL_STATIC_LIBRARIES := \
libgmock \
libgtest \
+ libhidlbase \
android.hardware.wifi@1.0-service-lib
LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
- libhidlbase \
libhidltransport \
liblog \
libnl \
diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh
index 966a6a7..5906193 100755
--- a/wifi/1.2/default/tests/runtests.sh
+++ b/wifi/1.2/default/tests/runtests.sh
@@ -18,33 +18,9 @@
echo "You need to source and lunch before you can use this script"
exit 1
fi
+set -e
-echo "Running tests"
-set -e # fail early
-
-#NOTE We can't actually run these commands, since they rely on functions added by
-#build / envsetup.sh to the bash shell environment.
-echo "+ mmma -j32 $ANDROID_BUILD_TOP/"
-make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk \
- MODULES-IN-hardware-interfaces-wifi-1.2-default
-
-set -x # print commands
-
-adb wait-for-device
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests
adb root
-adb wait-for-device
-
-#'disable-verity' will appear in 'adb remount' output if
-#dm - verity is enabled and needs to be disabled.
-if adb remount | grep 'disable-verity'; then
- adb disable-verity
- adb reboot
- adb wait-for-device
- adb root
- adb wait-for-device
- adb remount
-fi
-
-adb sync
-
+adb sync data
adb shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 3bd0557..c4da184 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -111,16 +111,16 @@
bool removeOldFilesInternal() {
time_t now = time(0);
const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
- DIR* dir_dump = opendir(kTombstoneFolderPath);
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(
+ opendir(kTombstoneFolderPath), closedir);
if (!dir_dump) {
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
return false;
}
- unique_fd dir_auto_closer(dirfd(dir_dump));
struct dirent* dp;
bool success = true;
std::list<std::pair<const time_t, std::string>> valid_files;
- while ((dp = readdir(dir_dump))) {
+ while ((dp = readdir(dir_dump.get()))) {
if (dp->d_type != DT_REG) {
continue;
}
@@ -246,13 +246,13 @@
size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
struct dirent* dp;
size_t n_error = 0;
- DIR* dir_dump = opendir(input_dir);
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir),
+ closedir);
if (!dir_dump) {
LOG(ERROR) << "Failed to open directory: " << strerror(errno);
return ++n_error;
}
- unique_fd dir_auto_closer(dirfd(dir_dump));
- while ((dp = readdir(dir_dump))) {
+ while ((dp = readdir(dir_dump.get()))) {
if (dp->d_type != DT_REG) {
continue;
}
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index 811c857..8bfb148 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,4 +1,2 @@
rpius@google.com
-quiche@google.com
-arabawy@google.com
-yim@google.com
\ No newline at end of file
+etancohen@google.com