Merge "Emergency Function HAL (continued)" am: f461463b39 am: a22dacfc17
am: 873df862c0
Change-Id: Id441e551314a5b14a7cdfaa3570cddc8d6bb94ef
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 531e44e..0900eea 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -66,3 +66,6 @@
$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
$(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.0.policy)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/seccomp_policy/configstore@1.1.policy)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.configstore@1.1-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.configstore@1.1-service.rc)
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/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index 43d7fe1..e6ae03e 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -31,12 +31,14 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := \
+ libcutils \
libbinder \
libhidlbase \
libhidltransport \
liblog \
libutils \
libhardware \
+ libhwbinder \
android.hardware.audio@2.0 \
android.hardware.audio@4.0 \
android.hardware.audio.common@2.0 \
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index c7ce638..ff1394e 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -24,16 +24,26 @@
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
#include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
#include <binder/ProcessState.h>
+#include <cutils/properties.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
using namespace android::hardware;
using android::OK;
int main(int /* argc */, char* /* argv */ []) {
- android::ProcessState::initWithDriver("/dev/vndbinder");
+ ::android::ProcessState::initWithDriver("/dev/vndbinder");
// start a threadpool for vndbinder interactions
- android::ProcessState::self()->startThreadPool();
+ ::android::ProcessState::self()->startThreadPool();
+
+ const int32_t defaultValue = -1;
+ int32_t value =
+ property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
+ if (value != defaultValue) {
+ ALOGD("Configuring hwbinder with mmap size %d KBytes", value);
+ ProcessState::initWithMmapSize(static_cast<size_t>(value) * 1024);
+ }
configureRpcThreadpool(16, true /*callerWillJoin*/);
bool fail = registerPassthroughServiceImplementation<audio::V4_0::IDevicesFactory>() != OK &&
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index f84e1e2..3a7c284 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -65,8 +65,8 @@
using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-using ::android::hardware::kSynchronizedReadWrite;
using ::android::hardware::IPCThreadState;
+using ::android::hardware::kSynchronizedReadWrite;
using ::android::hardware::MessageQueue;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
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/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..e0b54d0 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,10 @@
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 FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE;
+constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR;
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;
@@ -44,10 +48,28 @@
constexpr int ALL_WHEELS =
(int)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT |
VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR);
+constexpr int SEAT_1_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT);
+constexpr int SEAT_1_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT);
constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT |
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);
+constexpr int FUEL_DOOR_REAR_LEFT = (int)PortLocationType::REAR_LEFT;
+constexpr int CHARGE_PORT_FRONT_LEFT = (int)PortLocationType::FRONT_LEFT;
+constexpr int LIGHT_STATE_ON = (int)VehicleLightState::ON;
+constexpr int LIGHT_SWITCH_AUTO = (int)VehicleLightSwitch::AUTOMATIC;
+constexpr int WHEEL_FRONT_LEFT = (int)VehicleAreaWheel::LEFT_FRONT;
+constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT;
+constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR;
+constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
/**
* This property is used for test purpose to generate fake events. Here is the test package that
@@ -70,33 +92,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,
@@ -133,8 +161,9 @@
.prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
- .initialValue = {.floatValues = {15000}}},
+ .initialValue = {.floatValues = {15000.0f}}},
{.config =
{
@@ -149,8 +178,9 @@
.prop = toInt(VehicleProperty::INFO_EV_BATTERY_CAPACITY),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
- .initialValue = {.floatValues = {150000}}},
+ .initialValue = {.floatValues = {150000.0f}}},
{.config =
{
@@ -162,6 +192,24 @@
{.config =
{
+ .prop = toInt(VehicleProperty::INFO_FUEL_DOOR_LOCATION),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {FUEL_DOOR_REAR_LEFT}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::INFO_EV_PORT_LOCATION),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {CHARGE_PORT_FRONT_LEFT}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::INFO_MAKE),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::STATIC,
@@ -179,6 +227,16 @@
{.config =
{
+ .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ // this was a zoned property on an old vhal, but it is meant to be global
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {SEAT_1_LEFT}}},
+
+ {.config =
+ {
.prop = toInt(VehicleProperty::PERF_ODOMETER),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -202,14 +260,16 @@
.prop = toInt(VehicleProperty::FUEL_LEVEL),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
- .initialValue = {.floatValues = {15000}}},
+ .initialValue = {.floatValues = {15000.0f}}},
{.config =
{
.prop = toInt(VehicleProperty::FUEL_DOOR_OPEN),
- .access = VehiclePropertyAccess::READ,
+ .access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
.initialValue = {.int32Values = {0}}},
@@ -218,14 +278,16 @@
.prop = toInt(VehicleProperty::EV_BATTERY_LEVEL),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
- .initialValue = {.floatValues = {150000}}},
+ .initialValue = {.floatValues = {150000.0f}}},
{.config =
{
.prop = toInt(VehicleProperty::EV_CHARGE_PORT_OPEN),
- .access = VehiclePropertyAccess::READ,
+ .access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
.initialValue = {.int32Values = {0}}},
@@ -234,6 +296,7 @@
.prop = toInt(VehicleProperty::EV_CHARGE_PORT_CONNECTED),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
.initialValue = {.int32Values = {0}}},
@@ -242,8 +305,37 @@
.prop = toInt(VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
- .initialValue = {.floatValues = {0}}},
+ .initialValue = {.floatValues = {0.0f}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::RANGE_REMAINING),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.floatValues = {100.0f}}}, // units in meters
+
+ {.config =
+ {.prop = toInt(VehicleProperty::TIRE_PRESSURE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+ .areaConfigs =
+ {VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_FRONT_RIGHT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_LEFT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
+ },
+ VehicleAreaConfig{
+ .areaId = WHEEL_REAR_RIGHT, .minFloatValue = 100.0f, .maxFloatValue = 300.0f,
+ }}},
+ .initialValue = {.floatValues = {200}}}, // units in kPa
{.config =
{
@@ -266,6 +358,7 @@
.prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
},
.initialValue = {.int32Values = {0}}},
@@ -355,6 +448,24 @@
.areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
.initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
+ {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION_AVAILABLE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ .areaConfigs = {VehicleAreaConfig{.areaId = HVAC_ALL}}},
+ .initialValue = {.int32Values = {FAN_DIRECTION_FACE, FAN_DIRECTION_FLOOR,
+ FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR}}},
+
+ {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_VENTILATION),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = SEAT_1_LEFT, .minInt32Value = 0, .maxInt32Value = 3,
+ },
+ VehicleAreaConfig{
+ .areaId = SEAT_1_RIGHT, .minInt32Value = 0, .maxInt32Value = 3,
+ }}},
+ .initialValue = {.int32Values = {0}}}, // 0 is off and +ve values indicate ventilation level.
+
{.config = {.prop = toInt(VehicleProperty::HVAC_STEERING_WHEEL_HEAT),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -362,14 +473,29 @@
.areaId = (0), .minInt32Value = -2, .maxInt32Value = 2}}},
.initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling
+ {.config = {.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = SEAT_1_LEFT, .minInt32Value = -2, .maxInt32Value = 2,
+ },
+ VehicleAreaConfig{
+ .areaId = SEAT_1_RIGHT, .minInt32Value = -2, .maxInt32Value = 2,
+ }}},
+ .initialValue = {.int32Values = {0}}}, // +ve values for heating and -ve for cooling
+
{.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
.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}}}}},
@@ -520,9 +646,126 @@
.configArray = {1}},
},
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HEADLIGHTS_STATE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_STATE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::FOG_LIGHTS_STATE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HAZARD_LIGHTS_STATE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_STATE_ON}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HEADLIGHTS_SWITCH),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HIGH_BEAM_LIGHTS_SWITCH),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::FOG_LIGHTS_SWITCH),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
+ {.config =
+ {
+ .prop = toInt(VehicleProperty::HAZARD_LIGHTS_SWITCH),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+ },
+ .initialValue = {.int32Values = {LIGHT_SWITCH_AUTO}}},
+
{.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/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 57179df..4d07386 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -306,6 +306,37 @@
| VehicleArea:GLOBAL),
/**
+ * Speed of the vehicle for displays
+ *
+ * Some cars display a slightly slower speed than the actual speed. This is
+ * usually displayed on the speedometer.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:METER_PER_SEC
+ */
+ PERF_VEHICLE_SPEED_DISPLAY = (
+ 0x0208
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:FLOAT
+ | VehicleArea:GLOBAL),
+
+ /**
+ * Steering angle of the vehicle
+ *
+ * Angle is in degrees. Left is negative.
+ *
+ * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+ * @access VehiclePropertyAccess:READ
+ * @unit VehicleUnit:DEGREES
+ */
+ PERF_STEERING_ANGLE = (
+ 0x0209
+ | VehiclePropertyGroup:SYSTEM
+ | VehiclePropertyType:FLOAT
+ | VehicleArea:GLOBAL),
+
+ /**
* Temperature of engine coolant
*
* @change_mode VehiclePropertyChangeMode:CONTINUOUS
@@ -587,7 +618,13 @@
*
* This property corresponds to the low fuel warning on the dashboard.
* Once FUEL_LEVEL_LOW is set, it should not be cleared until more fuel is
- * added to the vehicle.
+ * added to the vehicle. This property may take into account all fuel
+ * sources for a vehicle - for example:
+ *
+ * For a gas powered vehicle, this property is based soley on gas level.
+ * For a battery powered vehicle, this property is based solely on battery level.
+ * For a hybrid vehicle, this property may be based on the combination of gas and battery
+ * levels, at the OEM's discretion.
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
* @access VehiclePropertyAccess:READ
@@ -2399,13 +2436,15 @@
NANO_SECS = 0x50,
SECS = 0x53,
YEAR = 0x59,
- KILOPASCAL = 0x70,
// Electrical Units
WATT_HOUR = 0x60,
MILLIAMPERE = 0x61,
MILLIVOLT = 0x62,
MILLIWATTS = 0x63,
+
+ KILOPASCAL = 0x70,
+ DEGREES = 0x80,
};
/**
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
new file mode 100644
index 0000000..45dbad9
--- /dev/null
+++ b/biometrics/face/1.0/Android.bp
@@ -0,0 +1,27 @@
+// 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",
+ "OptionalBool",
+ "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..1c7bfb9
--- /dev/null
+++ b/biometrics/face/1.0/IBiometricsFace.hal
@@ -0,0 +1,236 @@
+/*
+ * 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", "generateChallenge", "enumerate", "remove"})
+ setActiveUser(int32_t userId, string storePath) generates (Status status);
+
+ /**
+ * Begins a secure transaction request, e.g. enrollment.
+ *
+ * Generates a unique and cryptographically secure random token used to
+ * indicate the start of a secure transaction. generateChallenge() and
+ * revokeChallenge() specify a pin/pattern/password cleared time window where
+ * the secure transaction is allowed.
+ *
+ * generateChallenge() 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).
+ *
+ * @param challengeTimeoutSec A timeout in seconds, after which the driver
+ * must invalidate the challenge. This is to prevent bugs or crashes in
+ * the system from leaving a challenge enabled indefinitely.
+ * @return result, with its "value" parameter representing a "challenge": a
+ * unique and cryptographically secure random token.
+ */
+ @callflow(next={"enroll", "revokeChallenge", "setRequireAttention"})
+ generateChallenge(uint32_t challengeTimeoutSec)
+ 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
+ * revokeChallenge(). 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 generateChallenge() 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 revokeChallenge() to terminate the enrollment session.
+ * @param requireAttention When set to true, requires user attention (e.g.
+ * eyes open and looking at the device) for enrollment to complete, as
+ * well as subsequent authentication. This is expected to be enabled by
+ * default to improve security and decrease falsing (unintentional face
+ * detection). This feature can be disabled at the user's request
+ * during enrollment, e.g. for accessibility reasons. When enabled,
+ * the FaceAcquiredInfo#POOR_GAZE message must be sent when the user's
+ * attention has not been established. The UI should inform the user
+ * to look at the device.
+ * @return status The status of this method call.
+ */
+ @callflow(next={"cancel", "enroll", "revokeChallenge", "remove"})
+ enroll(vec<uint8_t> hat, uint32_t timeoutSec, bool requireAttention)
+ generates (Status status);
+
+ /**
+ * Finishes the secure transaction by invalidating the challenge generated
+ * by generateChallenge().
+ *
+ * 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"})
+ revokeChallenge() generates (Status status);
+
+ /**
+ * Requires that all subsequent authenticate calls to first have the
+ * user's attention. This method does not affect enroll, which has its
+ * own requireAttention parameter.
+ *
+ * Changes the state of previous enrollment setting. Because this may
+ * decrease security, the user must enter their password before this method
+ * is invoked (see @param HAT). The driver must verify the HAT before
+ * changing the requireAttention state.
+ * Note: In some cases it may not be possible to change the state of this
+ * flag without re-enrolling. For example, if the user didn't provide
+ * attention during the original enrollment. This flag reflects the same
+ * persistent state as the one passed to enroll().
+ *
+ * @param requireAttention When set to true, requires user attention for
+ * authentication to succeed.
+ * @param hat A valid Hardware Authentication Token, generated as a result
+ * of getChallenge().
+ * @return status The status of this method call.
+ */
+ setRequireAttention(bool requireAttention, vec<uint8_t> hat)
+ generates(Status status);
+
+ /**
+ * Retrieves the current requireAttention state.
+ *
+ * @return result, with its value parameter representing the current
+ * requireAttention state.
+ */
+ getRequireAttention(vec<uint8_t> hat) generates (OptionalBool result);
+
+ /**
+ * 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", "generateChallenge", "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..2628af9
--- /dev/null
+++ b/biometrics/face/1.0/types.hal
@@ -0,0 +1,283 @@
+/*
+ * 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,
+
+ /**
+ * The operation could not be completed because there are no enrolled
+ * templates.
+ */
+ NOT_ENROLLED = 4
+};
+
+/**
+ * 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 eyes have strayed away from the sensor. If this message is
+ * sent, the user should be informed to look at the device. If the user
+ * can't be found in the frame, one of the other acquisition messages
+ * must be sent, e.g. NOT_DETECTED.
+ */
+ 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 re-calibrated. This is an unexpected condition,
+ * and must only be sent if a serious, uncorrectable, and unrecoverable
+ * calibration issue is detected which requires user intervention, e.g.
+ * re-enrolling. The expected response to this message is to direct the
+ * user to re-enroll.
+ */
+ 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;
+};
+
+/**
+ * Result structure with an addition bool field. See documentation in
+ * getRequireAttention() for usage of the value.
+ */
+struct OptionalBool {
+ /**
+ * The return status.
+ */
+ Status status;
+
+ /**
+ * This value is only meaningful if status is OK.
+ */
+ bool value;
+};
\ No newline at end of file
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index dc4e0f0..eb840a7 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -319,6 +319,41 @@
return OK;
}
+int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo) {
+ ATRACE_CALL();
+ Mutex::Autolock lock(mCameraInfoLock);
+ if (physicalCameraId < 0) {
+ ALOGE("%s: Invalid physical camera ID %d", __FUNCTION__, physicalCameraId);
+ return -EINVAL;
+ }
+
+ // Only query physical camera info for 2.5 version for newer
+ int apiVersion = mModule->common.module_api_version;
+ if (apiVersion < CAMERA_MODULE_API_VERSION_2_5) {
+ ALOGE("%s: Module version must be at least 2.5 to handle getPhysicalCameraInfo",
+ __FUNCTION__);
+ return -ENODEV;
+ }
+
+ ssize_t index = mPhysicalCameraInfoMap.indexOfKey(physicalCameraId);
+ if (index == NAME_NOT_FOUND) {
+ // Get physical camera characteristics, and cache it
+ camera_metadata_t *info = nullptr;
+ ATRACE_BEGIN("camera_module->get_physical_camera_info");
+ int ret = mModule->get_physical_camera_info(physicalCameraId, &info);
+ ATRACE_END();
+ if (ret != 0) {
+ return ret;
+ }
+
+ index = mPhysicalCameraInfoMap.add(physicalCameraId, info);
+ }
+
+ assert(index != NAME_NOT_FOUND);
+ *physicalInfo = mPhysicalCameraInfoMap[index];
+ return OK;
+}
+
int CameraModule::getDeviceVersion(int cameraId) {
ssize_t index = mDeviceVersionMap.indexOfKey(cameraId);
if (index == NAME_NOT_FOUND) {
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index deebd09..ed853bf 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -65,6 +65,7 @@
void *getDso();
// Only used by CameraProvider
void removeCamera(int cameraId);
+ int getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo);
private:
// Derive camera characteristics keys defined after HAL device version
@@ -76,6 +77,7 @@
camera_module_t *mModule;
KeyedVector<int, camera_info> mCameraInfoMap;
KeyedVector<int, int> mDeviceVersionMap;
+ KeyedVector<int, camera_metadata_t*> mPhysicalCameraInfoMap;
Mutex mCameraInfoLock;
};
diff --git a/camera/device/3.2/ICameraDevice.hal b/camera/device/3.2/ICameraDevice.hal
index 1f523e4..5236bb1 100644
--- a/camera/device/3.2/ICameraDevice.hal
+++ b/camera/device/3.2/ICameraDevice.hal
@@ -148,7 +148,9 @@
* session handle for active operations.
*
* @param callback Interface to invoke by the HAL for device asynchronous
- * events.
+ * events. For HALs newer than version 3.2, HAL must use castFrom
+ * method to check the exact version of callback sent by camera service.
+ *
* @return status Status code for the operation, one of:
* OK:
* On a successful open of the camera device.
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index 477a3cc..225e52b 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -149,9 +149,8 @@
* - Including too many output streams of a certain format.
* - Unsupported rotation configuration
* - Stream sizes/formats don't satisfy the
- * camera3_stream_configuration_t->operation_mode requirements
- * for non-NORMAL mode, or the requested operation_mode is not
- * supported by the HAL.
+ * StreamConfigurationMode requirements for non-NORMAL mode, or
+ * the requested operation_mode is not supported by the HAL.
* - Unsupported usage flag
* The camera service cannot filter out all possible illegal stream
* configurations, since some devices may support more simultaneous
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index dfbb976..2e80ce8 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -101,7 +101,7 @@
}
// Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
-Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb) {
+Return<void> CameraDevice::getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb) {
Status status = initStatus();
CameraResourceCost resCost;
if (status == Status::OK) {
@@ -141,7 +141,8 @@
return Void();
}
-Return<void> CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) {
+Return<void> CameraDevice::getCameraCharacteristics(
+ ICameraDevice::getCameraCharacteristics_cb _hidl_cb) {
Status status = initStatus();
CameraMetadata cameraCharacteristics;
if (status == Status::OK) {
@@ -172,7 +173,8 @@
return status;
}
-Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) {
+Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback,
+ ICameraDevice::open_cb _hidl_cb) {
Status status = initStatus();
sp<CameraDeviceSession> session = nullptr;
diff --git a/camera/device/3.2/default/CameraDevice_3_2.h b/camera/device/3.2/default/CameraDevice_3_2.h
index 9534707..f474533 100644
--- a/camera/device/3.2/default/CameraDevice_3_2.h
+++ b/camera/device/3.2/default/CameraDevice_3_2.h
@@ -51,7 +51,7 @@
/*
* The camera device HAL implementation is opened lazily (via the open call)
*/
-struct CameraDevice : public ICameraDevice {
+struct CameraDevice : public virtual RefBase {
// Called by provider HAL. Provider HAL must ensure the uniqueness of
// CameraDevice object per cameraId, or there could be multiple CameraDevice
// trying to access the same physical camera.
@@ -60,7 +60,14 @@
CameraDevice(sp<CameraModule> module,
const std::string& cameraId,
const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
- ~CameraDevice();
+ virtual ~CameraDevice();
+
+ // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+ // dealing with minor version revs and simultaneous implementation and interface inheritance
+ virtual sp<ICameraDevice> getInterface() {
+ return new TrampolineDeviceInterface_3_2(this);
+ }
+
// Caller must use this method to check if CameraDevice ctor failed
bool isInitFailed() { return mInitFail; }
// Used by provider HAL to signal external camera disconnected
@@ -68,16 +75,16 @@
/* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
// The following method can be called without opening the actual camera device
- Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
- Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
- Return<Status> setTorchMode(TorchMode mode) override;
+ Return<void> getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb);
+ Return<void> getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb);
+ Return<Status> setTorchMode(TorchMode mode);
// Open the device HAL and also return a default capture session
- Return<void> open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) override;
+ Return<void> open(const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb);
// Forward the dump call to the opened session, or do nothing
- Return<void> dumpState(const ::android::hardware::hidl_handle& fd) override;
+ Return<void> dumpState(const ::android::hardware::hidl_handle& fd);
/* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
protected:
@@ -106,6 +113,39 @@
static Status getHidlStatus(int);
Status initStatus() const;
+
+private:
+ struct TrampolineDeviceInterface_3_2 : public ICameraDevice {
+ TrampolineDeviceInterface_3_2(sp<CameraDevice> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+ override {
+ return mParent->getResourceCost(_hidl_cb);
+ }
+
+ virtual Return<void> getCameraCharacteristics(
+ V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getCameraCharacteristics(_hidl_cb);
+ }
+
+ virtual Return<Status> setTorchMode(TorchMode mode) override {
+ return mParent->setTorchMode(mode);
+ }
+
+ virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+ V3_2::ICameraDevice::open_cb _hidl_cb) override {
+ return mParent->open(callback, _hidl_cb);
+ }
+
+ virtual Return<void> dumpState(const hidl_handle& fd) override {
+ return mParent->dumpState(fd);
+ }
+
+ private:
+ sp<CameraDevice> mParent;
+ };
+
};
} // namespace implementation
diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal
index c41d90e..e1663e6 100644
--- a/camera/device/3.4/ICameraDeviceSession.hal
+++ b/camera/device/3.4/ICameraDeviceSession.hal
@@ -54,7 +54,7 @@
* - Including too many output streams of a certain format.
* - Unsupported rotation configuration
* - Stream sizes/formats don't satisfy the
- * camera3_stream_configuration_t->operation_mode requirements
+ * StreamConfigurationMode requirements
* for non-NORMAL mode, or the requested operation_mode is not
* supported by the HAL.
* - Unsupported usage flag
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 28ca0f3..350f48b 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -344,17 +344,31 @@
ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb) {
V3_2::StreamConfiguration config_v32;
V3_3::HalStreamConfiguration outStreams_v33;
+ V3_4::HalStreamConfiguration outStreams;
Mutex::Autolock _il(mInterfaceLock);
config_v32.operationMode = requestedConfiguration.operationMode;
config_v32.streams.resize(requestedConfiguration.streams.size());
+ uint32_t blobBufferSize = 0;
+ int numStallStream = 0;
for (size_t i = 0; i < config_v32.streams.size(); i++) {
config_v32.streams[i] = requestedConfiguration.streams[i].v3_2;
+ if (config_v32.streams[i].format == PixelFormat::BLOB) {
+ blobBufferSize = requestedConfiguration.streams[i].bufferSize;
+ numStallStream++;
+ }
}
- Status status = configureStreams(config_v32, &outStreams_v33);
+ // Fail early if there are multiple BLOB streams
+ if (numStallStream > kMaxStallStream) {
+ ALOGE("%s: too many stall streams (expect <= %d, got %d)", __FUNCTION__,
+ kMaxStallStream, numStallStream);
+ _hidl_cb(Status::ILLEGAL_ARGUMENT, outStreams);
+ return Void();
+ }
- V3_4::HalStreamConfiguration outStreams;
+ Status status = configureStreams(config_v32, &outStreams_v33, blobBufferSize);
+
outStreams.streams.resize(outStreams_v33.streams.size());
for (size_t i = 0; i < outStreams.streams.size(); i++) {
outStreams.streams[i].v3_3 = outStreams_v33.streams[i];
@@ -1592,8 +1606,9 @@
* main image needs to hold APP1, headers, and at most a poorly
* compressed image */
const ssize_t maxThumbCodeSize = 64 * 1024;
- const ssize_t maxJpegCodeSize = parent->getJpegBufferSize(jpegSize.width,
- jpegSize.height);
+ const ssize_t maxJpegCodeSize = mBlobBufferSize == 0 ?
+ parent->getJpegBufferSize(jpegSize.width, jpegSize.height) :
+ mBlobBufferSize;
/* Check that getJpegBufferSize did not return an error */
if (maxJpegCodeSize < 0) {
@@ -1855,7 +1870,8 @@
Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers(
const Size& v4lSize, const Size& thumbSize,
- const hidl_vec<Stream>& streams) {
+ const hidl_vec<Stream>& streams,
+ uint32_t blobBufferSize) {
std::lock_guard<std::mutex> lk(mBufferLock);
if (mScaledYu12Frames.size() != 0) {
ALOGE("%s: intermediate buffer pool has %zu inflight buffers! (expect 0)",
@@ -1924,6 +1940,8 @@
it = mIntermediateBuffers.erase(it);
}
}
+
+ mBlobBufferSize = blobBufferSize;
return Status::OK;
}
@@ -2420,7 +2438,9 @@
}
Status ExternalCameraDeviceSession::configureStreams(
- const V3_2::StreamConfiguration& config, V3_3::HalStreamConfiguration* out) {
+ const V3_2::StreamConfiguration& config,
+ V3_3::HalStreamConfiguration* out,
+ uint32_t blobBufferSize) {
ATRACE_CALL();
if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) {
ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode);
@@ -2582,7 +2602,7 @@
}
status = mOutputThread->allocateIntermediateBuffers(v4lSize,
- mMaxThumbResolution, config.streams);
+ mMaxThumbResolution, config.streams, blobBufferSize);
if (status != Status::OK) {
ALOGE("%s: allocating intermediate buffers failed!", __FUNCTION__);
return status;
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index 0b94c11..6e56596 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -177,7 +177,10 @@
Status initStatus() const;
status_t initDefaultRequests();
status_t fillCaptureResult(common::V1_0::helper::CameraMetadata& md, nsecs_t timestamp);
- Status configureStreams(const V3_2::StreamConfiguration&, V3_3::HalStreamConfiguration* out);
+ Status configureStreams(const V3_2::StreamConfiguration&,
+ V3_3::HalStreamConfiguration* out,
+ // Only filled by configureStreams_3_4, and only one blob stream supported
+ uint32_t blobBufferSize = 0);
// fps = 0.0 means default, which is
// slowest fps that is at least 30, or fastest fps if 30 is not supported
int configureV4l2StreamLocked(const SupportedV4L2Format& fmt, double fps = 0.0);
@@ -225,7 +228,8 @@
Status allocateIntermediateBuffers(
const Size& v4lSize, const Size& thumbSize,
- const hidl_vec<Stream>& streams);
+ const hidl_vec<Stream>& streams,
+ uint32_t blobBufferSize);
Status submitRequest(const std::shared_ptr<HalRequest>&);
void flush();
void dump(int fd);
@@ -289,6 +293,7 @@
std::unordered_map<Size, sp<AllocatedFrame>, SizeHasher> mScaledYu12Frames;
YCbCrLayout mYu12FrameLayout;
YCbCrLayout mYu12ThumbFrameLayout;
+ uint32_t mBlobBufferSize = 0; // 0 -> HAL derive buffer size, else: use given size
std::string mExifMake;
std::string mExifModel;
diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp
new file mode 100644
index 0000000..2a9ba05
--- /dev/null
+++ b/camera/device/3.5/Android.bp
@@ -0,0 +1,33 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.camera.device@3.5",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "ICameraDevice.hal",
+ "ICameraDeviceCallback.hal",
+ "ICameraDeviceSession.hal",
+ ],
+ interfaces: [
+ "android.hardware.camera.common@1.0",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.graphics.common@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "BufferRequest",
+ "BufferRequestStatus",
+ "StreamBufferRequestError",
+ "StreamBufferRet",
+ "StreamBuffersVal",
+ "StreamConfiguration",
+ ],
+ gen_java: false,
+}
+
diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal
new file mode 100644
index 0000000..e7e8dd3
--- /dev/null
+++ b/camera/device/3.5/ICameraDevice.hal
@@ -0,0 +1,62 @@
+/*
+ * 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.camera.device@3.5;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.2::CameraMetadata;
+import @3.2::ICameraDevice;
+
+/**
+ * Camera device interface
+ *
+ * Supports the android.hardware.Camera API, and the android.hardware.camera2
+ * API at LIMITED or better hardware level.
+ *
+ */
+interface ICameraDevice extends @3.2::ICameraDevice {
+
+ /**
+ * getPhysicalCameraCharacteristics:
+ *
+ * Return the static camera information for a physical camera ID backing
+ * this logical camera device. This information may not change between consecutive calls.
+ *
+ * Note that HAL must support this function for physical camera IDs that are
+ * not exposed via ICameraProvider::getCameraIdList().
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On a successful query of the camera device characteristics
+ * INTERNAL_ERROR:
+ * The camera device cannot be opened due to an internal
+ * error.
+ * CAMERA_DISCONNECTED:
+ * An external camera device has been disconnected, and is no longer
+ * available. This camera device interface is now stale, and a new
+ * instance must be acquired if the device is reconnected. All
+ * subsequent calls on this interface must return
+ * CAMERA_DISCONNECTED.
+ *
+ * @return cameraCharacteristics
+ * The static metadata for this logical camera device's physical device, or an empty
+ * metadata structure if status is not OK.
+ *
+ */
+ getPhysicalCameraCharacteristics(string physicalCameraId)
+ generates (Status status, CameraMetadata cameraCharacteristics);
+
+};
diff --git a/camera/device/3.5/ICameraDeviceCallback.hal b/camera/device/3.5/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..aa4ad22
--- /dev/null
+++ b/camera/device/3.5/ICameraDeviceCallback.hal
@@ -0,0 +1,70 @@
+/*
+ * 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.camera.device@3.5;
+
+import @3.2::StreamBuffer;
+import @3.4::ICameraDeviceCallback;
+
+/**
+ * Callback methods for the HAL to call into the framework.
+ */
+interface ICameraDeviceCallback extends @3.4::ICameraDeviceCallback {
+
+ /**
+ * requestStreamBuffers:
+ *
+ * Synchronous callback for HAL to ask for output buffers from camera service.
+ *
+ * This call may be serialized in camera service so it is strongly
+ * recommended to only call this method from one thread.
+ *
+ * When camera device advertises
+ * (CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion ==
+ * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5), HAL
+ * can use this method to request buffers from camera service.
+ *
+ * @return status Status code for the operation, one of:
+ * OK: all requested buffers are returned
+ * FAILED_PARTIAL: some streams failed while some succeeds. Check
+ * individual StreamBufferRet for details.
+ * FAILED_CONFIGURING: the request failed because camera servicve is
+ * performing configureStreams and no buffers are returned.
+ * FAILED_UNKNOWN: the request failed for unknown reason and no buffers
+ * are returned.
+ *
+ * Performance requirements:
+ * This is a blocking call that takes more time with more buffers requested.
+ * HAL must not request large amount of buffers on a latency critical code
+ * path. It is highly recommended to use a dedicated thread to perform
+ * all requestStreamBuffers calls, and adjust the thread priority and/or
+ * timing of making the call in order for buffers to arrive before HAL is
+ * ready to fill the buffer.
+ */
+ requestStreamBuffers(vec<BufferRequest> bufReqs)
+ generates (BufferRequestStatus st, vec<StreamBufferRet> buffers);
+
+ /**
+ * returnStreamBuffers:
+ *
+ * Synchronous callback for HAL to return output buffers to camera service.
+ *
+ * If this method is called during a configureStreams call, it must be blocked
+ * until camera service finishes the ongoing configureStreams call.
+ */
+ returnStreamBuffers(vec<StreamBuffer> buffers);
+
+};
diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal
new file mode 100644
index 0000000..b2b71cd
--- /dev/null
+++ b/camera/device/3.5/ICameraDeviceSession.hal
@@ -0,0 +1,102 @@
+/*
+ * 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.camera.device@3.5;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.4::ICameraDeviceSession;
+import @3.4::HalStreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ */
+interface ICameraDeviceSession extends @3.4::ICameraDeviceSession {
+
+ /**
+ * configureStreams_3_5:
+ *
+ * Identical to @3.4::ICameraDeviceSession.configureStreams, except that:
+ *
+ * - a streamConfigCounter counter is provided to check for race condition
+ * between configureStreams_3_5 and signalStreamFlush call.
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On successful stream configuration.
+ * INTERNAL_ERROR:
+ * If there has been a fatal error and the device is no longer
+ * operational. Only close() can be called successfully by the
+ * framework after this error is returned.
+ * ILLEGAL_ARGUMENT:
+ * If the requested stream configuration is invalid. Some examples
+ * of invalid stream configurations include:
+ * - Including more than 1 INPUT stream
+ * - Not including any OUTPUT streams
+ * - Including streams with unsupported formats, or an unsupported
+ * size for that format.
+ * - Including too many output streams of a certain format.
+ * - Unsupported rotation configuration
+ * - Stream sizes/formats don't satisfy the
+ * StreamConfigurationMode requirements
+ * for non-NORMAL mode, or the requested operation_mode is not
+ * supported by the HAL.
+ * - Unsupported usage flag
+ * The camera service cannot filter out all possible illegal stream
+ * configurations, since some devices may support more simultaneous
+ * streams or larger stream resolutions than the minimum required
+ * for a given camera device hardware level. The HAL must return an
+ * ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+ * ready to accept a future valid stream configuration in a later
+ * configureStreams call.
+ * @return halConfiguration The stream parameters desired by the HAL for
+ * each stream, including maximum buffers, the usage flags, and the
+ * override format.
+ */
+ configureStreams_3_5(@3.5::StreamConfiguration requestedConfiguration)
+ generates (Status status,
+ @3.4::HalStreamConfiguration halConfiguration);
+
+
+ /**
+ * signalStreamFlush:
+ *
+ * Signaling HAL camera service is about to perform configureStreams_3_5 and
+ * HAL must return all buffers of designated streams. HAL must finish
+ * inflight requests normally and return all buffers that belongs to the
+ * designated streams through processCaptureResult or returnStreamBuffer
+ * API in a timely manner, or camera service will run into a fatal error.
+ *
+ * Note that this call serves as an optional hint and camera service may
+ * skip sending this call if all buffers are already returned.
+ *
+ * @param streamIds The ID of streams camera service need all of its
+ * buffers returned.
+ *
+ * @param streamConfigCounter Note that due to concurrency nature, it is
+ * possible the signalStreamFlush call arrives later than the
+ * corresponding configureStreams_3_5 call, HAL must check
+ * streamConfigCounter for such race condition. If the counter is less
+ * than the counter in the last configureStreams_3_5 call HAL last
+ * received, the call is stale and HAL should just return this call.
+ */
+ oneway signalStreamFlush(
+ vec<int32_t> streamIds,
+ uint32_t streamConfigCounter
+ );
+};
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
new file mode 100644
index 0000000..09cf3a4
--- /dev/null
+++ b/camera/device/3.5/default/Android.bp
@@ -0,0 +1,54 @@
+//
+// 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: "camera.device@3.5-impl_headers",
+ vendor: true,
+ export_include_dirs: ["include/device_v3_5_impl"]
+}
+
+cc_library_shared {
+ name: "camera.device@3.5-impl",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+ vendor: true,
+ srcs: [
+ "CameraDevice.cpp",
+ "CameraDeviceSession.cpp",
+ ],
+ shared_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "libcutils",
+ "camera.device@3.2-impl",
+ "camera.device@3.3-impl",
+ "camera.device@3.4-impl",
+ "android.hardware.camera.device@3.2",
+ "android.hardware.camera.device@3.3",
+ "android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
+ "android.hardware.camera.provider@2.4",
+ "android.hardware.graphics.mapper@2.0",
+ "liblog",
+ "libhardware",
+ "libcamera_metadata",
+ ],
+ static_libs: [
+ "android.hardware.camera.common@1.0-helper",
+ ],
+ local_include_dirs: ["include/device_v3_5_impl"],
+}
diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp
new file mode 100644
index 0000000..c5d6c57
--- /dev/null
+++ b/camera/device/3.5/default/CameraDevice.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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 "CamDev@3.5-impl"
+#include <log/log.h>
+
+#include "CameraModule.h"
+#include "CameraDevice_3_5.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+
+CameraDevice::CameraDevice(sp<CameraModule> module, const std::string& cameraId,
+ const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
+ V3_4::implementation::CameraDevice(module, cameraId, cameraDeviceNames) {
+}
+
+CameraDevice::~CameraDevice() {
+}
+
+sp<V3_2::implementation::CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
+ const camera_metadata_t* deviceInfo,
+ const sp<V3_2::ICameraDeviceCallback>& callback) {
+ sp<CameraDeviceSession> session = new CameraDeviceSession(device, deviceInfo, callback);
+ IF_ALOGV() {
+ session->getInterface()->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Session interface chain:");
+ for (auto iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+ return session;
+}
+
+Return<void> CameraDevice::getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) {
+ Status status = initStatus();
+ CameraMetadata cameraCharacteristics;
+ if (status == Status::OK) {
+ // Require module 2.5+ version.
+ if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_5) {
+ ALOGE("%s: get_physical_camera_info must be called on camera module 2.5 or newer",
+ __FUNCTION__);
+ status = Status::INTERNAL_ERROR;
+ } else {
+ char *end;
+ errno = 0;
+ long id = strtol(physicalCameraId.c_str(), &end, 0);
+ if (id > INT_MAX || (errno == ERANGE && id == LONG_MAX) ||
+ id < INT_MIN || (errno == ERANGE && id == LONG_MIN) ||
+ *end != '\0') {
+ ALOGE("%s: Invalid physicalCameraId %s", __FUNCTION__, physicalCameraId.c_str());
+ status = Status::ILLEGAL_ARGUMENT;
+ } else {
+ camera_metadata_t *physicalInfo = nullptr;
+ int ret = mModule->getPhysicalCameraInfo((int)id, &physicalInfo);
+ if (ret == OK) {
+ V3_2::implementation::convertToHidl(physicalInfo, &cameraCharacteristics);
+ } else {
+ ALOGE("%s: Failed to get physical camera %s info: %s (%d)!", __FUNCTION__,
+ physicalCameraId.c_str(), strerror(-ret), ret);
+ status = Status::INTERNAL_ERROR;
+ }
+ }
+ }
+ }
+ _hidl_cb(status, cameraCharacteristics);
+ return Void();
+}
+
+// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
new file mode 100644
index 0000000..5336ca9
--- /dev/null
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "CamDevSession@3.5-impl"
+#include <android/log.h>
+
+#include <utils/Trace.h>
+#include "CameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+CameraDeviceSession::CameraDeviceSession(
+ camera3_device_t* device,
+ const camera_metadata_t* deviceInfo,
+ const sp<V3_2::ICameraDeviceCallback>& callback) :
+ V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
+
+ mHasCallback_3_5 = false;
+
+ auto castResult = ICameraDeviceCallback::castFrom(callback);
+ if (castResult.isOk()) {
+ sp<ICameraDeviceCallback> callback3_5 = castResult;
+ if (callback3_5 != nullptr) {
+ mHasCallback_3_5 = true;
+ }
+ }
+}
+
+CameraDeviceSession::~CameraDeviceSession() {
+}
+
+Return<void> CameraDeviceSession::configureStreams_3_5(
+ const StreamConfiguration& /*requestedConfiguration*/,
+ ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb) {
+ HalStreamConfiguration outStreams;
+ _hidl_cb(Status::OPERATION_NOT_SUPPORTED, outStreams);
+ return Void();
+}
+
+Return<void> CameraDeviceSession::signalStreamFlush(
+ const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
new file mode 100644
index 0000000..ec34769
--- /dev/null
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -0,0 +1,157 @@
+/*
+ * 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_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
+
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_5::StreamConfiguration;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
+
+ CameraDeviceSession(camera3_device_t*,
+ const camera_metadata_t* deviceInfo,
+ const sp<V3_2::ICameraDeviceCallback>&);
+ virtual ~CameraDeviceSession();
+
+ virtual sp<V3_2::ICameraDeviceSession> getInterface() override {
+ return new TrampolineSessionInterface_3_5(this);
+ }
+
+protected:
+ // Methods from v3.4 and earlier will trampoline to inherited implementation
+ Return<void> configureStreams_3_5(
+ const StreamConfiguration& requestedConfiguration,
+ ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
+
+ Return<void> signalStreamFlush(
+ const hidl_vec<int32_t>& requests,
+ uint32_t streamConfigCounter);
+
+
+ // Whether this camera device session is created with version 3.5 callback.
+ bool mHasCallback_3_5;
+
+private:
+
+ struct TrampolineSessionInterface_3_5 : public ICameraDeviceSession {
+ TrampolineSessionInterface_3_5(sp<CameraDeviceSession> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> constructDefaultRequestSettings(
+ V3_2::RequestTemplate type,
+ V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+ return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams(
+ const V3_2::StreamConfiguration& requestedConfiguration,
+ V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+ return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> processCaptureRequest_3_4(
+ const hidl_vec<V3_4::CaptureRequest>& requests,
+ const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+ ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+ return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+ }
+
+ virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+ const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+ V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+ return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+ }
+
+ virtual Return<void> getCaptureRequestMetadataQueue(
+ V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override {
+ return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+ }
+
+ virtual Return<void> getCaptureResultMetadataQueue(
+ V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override {
+ return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+ }
+
+ virtual Return<Status> flush() override {
+ return mParent->flush();
+ }
+
+ virtual Return<void> close() override {
+ return mParent->close();
+ }
+
+ virtual Return<void> configureStreams_3_3(
+ const V3_2::StreamConfiguration& requestedConfiguration,
+ configureStreams_3_3_cb _hidl_cb) override {
+ return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams_3_4(
+ const V3_4::StreamConfiguration& requestedConfiguration,
+ configureStreams_3_4_cb _hidl_cb) override {
+ return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> configureStreams_3_5(
+ const StreamConfiguration& requestedConfiguration,
+ configureStreams_3_5_cb _hidl_cb) override {
+ return mParent->configureStreams_3_5(requestedConfiguration, _hidl_cb);
+ }
+
+ virtual Return<void> signalStreamFlush(
+ const hidl_vec<int32_t>& requests,
+ uint32_t streamConfigCounter) override {
+ return mParent->signalStreamFlush(requests, streamConfigCounter);
+ }
+
+ private:
+ sp<CameraDeviceSession> mParent;
+ };
+};
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
new file mode 100644
index 0000000..6bdc60f
--- /dev/null
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
@@ -0,0 +1,111 @@
+/*
+ * 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_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
+
+#include "CameraDeviceSession.h"
+#include <../../../../3.4/default/include/device_v3_4_impl/CameraDevice_3_4.h>
+
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::sp;
+
+struct CameraDevice : public V3_4::implementation::CameraDevice {
+ // Called by provider HAL.
+ // Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
+ // be multiple CameraDevice trying to access the same physical camera. Also, provider will have
+ // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
+ // camera is detached.
+ // Delegates nearly all work to CameraDevice_3_4
+ CameraDevice(sp<CameraModule> module,
+ const std::string& cameraId,
+ const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
+ virtual ~CameraDevice();
+
+ virtual sp<V3_2::ICameraDevice> getInterface() override {
+ return new TrampolineDeviceInterface_3_5(this);
+ }
+
+protected:
+ virtual sp<V3_2::implementation::CameraDeviceSession> createSession(camera3_device_t*,
+ const camera_metadata_t* deviceInfo,
+ const sp<V3_2::ICameraDeviceCallback>&) override;
+
+ Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb);
+
+private:
+ struct TrampolineDeviceInterface_3_5 : public ICameraDevice {
+ TrampolineDeviceInterface_3_5(sp<CameraDevice> parent) :
+ mParent(parent) {}
+
+ virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+ override {
+ return mParent->getResourceCost(_hidl_cb);
+ }
+
+ virtual Return<void> getCameraCharacteristics(
+ V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getCameraCharacteristics(_hidl_cb);
+ }
+
+ virtual Return<Status> setTorchMode(TorchMode mode) override {
+ return mParent->setTorchMode(mode);
+ }
+
+ virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+ V3_2::ICameraDevice::open_cb _hidl_cb) override {
+ return mParent->open(callback, _hidl_cb);
+ }
+
+ virtual Return<void> dumpState(const hidl_handle& fd) override {
+ return mParent->dumpState(fd);
+ }
+
+ virtual Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+ V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override {
+ return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb);
+ }
+ private:
+ sp<CameraDevice> mParent;
+ };
+};
+
+} // namespace implementation
+} // namespace V3_5
+} // namespace device
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal
new file mode 100644
index 0000000..613187d
--- /dev/null
+++ b/camera/device/3.5/types.hal
@@ -0,0 +1,131 @@
+/*
+ * 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.camera.device@3.5;
+
+import @3.2::StreamBuffer;
+import @3.4::StreamConfiguration;
+
+/**
+ * StreamConfiguration:
+ *
+ * Identical to @3.4::StreamConfiguration, except that it contains streamConfigCounter
+ */
+struct StreamConfiguration {
+ @3.4::StreamConfiguration v3_4;
+
+ /**
+ * An incrementing counter used for HAL to keep track of the stream
+ * configuration and the paired oneway signalStreamFlush call. When the
+ * counter in signalStreamFlush call is less than the counter here, that
+ * signalStreamFlush call is stale.
+ */
+ uint32_t streamConfigCounter;
+};
+
+enum StreamBufferRequestError : uint32_t {
+ /**
+ * Get buffer failed due to timeout waiting for an available buffer. This is
+ * likely due to the client application holding too many buffers, or the
+ * system is under memory pressure.
+ * This is not a fatal error. HAL may try to request buffer for this stream
+ * later. If HAL cannot get a buffer for certain capture request in time
+ * due to this error, HAL can send an ERROR_REQUEST to camera service and
+ * drop processing that request.
+ */
+ NO_BUFFER_AVAILABLE = 1,
+
+ /**
+ * Get buffer failed due to HAL has reached its maxBuffer count. This is not
+ * a fatal error. HAL may try to request buffer for this stream again after
+ * it returns at least one buffer of that stream to camera service.
+ */
+ MAX_BUFFER_EXCEEDED = 2,
+
+ /**
+ * Get buffer failed due to the stream is disconnected by client
+ * application, has been removed, or not recognized by camera service.
+ * This means application is no longer interested in this stream.
+ * Requesting buffer for this stream must never succeed after this error is
+ * returned. HAL must safely return all buffers of this stream after
+ * getting this error. If HAL gets another capture request later targeting
+ * a disconnected stream, HAL must send an ERROR_REQUEST to camera service
+ * and drop processing that request.
+ */
+ STREAM_DISCONNECTED = 3,
+
+ /**
+ * Get buffer failed for unknown reasons. This is a fatal error and HAL must
+ * send ERROR_DEVICE to camera service and be ready to be closed.
+ */
+ UNKNOWN_ERROR = 4
+};
+
+/**
+ * Per-stream return value for requestStreamBuffers.
+ * For each stream, either an StreamBufferRequestError error code, or all
+ * requested buffers for this stream is returned, so buffers.size() must be
+ * equal to BufferRequest::numBuffersRequested of corresponding stream.
+ */
+safe_union StreamBuffersVal {
+ StreamBufferRequestError error;
+ vec<@3.2::StreamBuffer> buffers;
+};
+
+struct StreamBufferRet {
+ int32_t streamId;
+ StreamBuffersVal val;
+};
+
+enum BufferRequestStatus : uint32_t {
+ /**
+ * Method call succeeded and all requested buffers are returned.
+ */
+ OK = 0,
+
+ /**
+ * Method call failed for some streams. Check per stream status for each
+ * returned StreamBufferRet.
+ */
+ FAILED_PARTIAL = 1,
+
+ /**
+ * Method call failed for all streams and no buffers are returned at all.
+ * Camera service is about to or is performing configureStreams. HAL must
+ * wait until next configureStreams call is finished before requesting
+ * buffers again.
+ */
+ FAILED_CONFIGURING = 2,
+
+ /**
+ * Method call failed for all streams and no buffers are returned at all.
+ * Failure due to bad BufferRequest input, eg: unknown streamId or repeated
+ * streamId.
+ */
+ FAILED_ILLEGAL_ARGUMENTS = 3,
+
+ /**
+ * Method call failed for all streams and no buffers are returned at all.
+ * Failure due to unknown reason.
+ */
+ FAILED_UNKNOWN = 4,
+};
+
+struct BufferRequest {
+ int32_t streamId;
+ uint32_t numBuffersRequested;
+};
+
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index 04edfe9..a37e132 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -109,8 +109,8 @@
/** android.statistics.oisDataMode [dynamic, enum, public]
*
- * <p>A control for selecting whether OIS position information is included in output
- * result metadata.</p>
+ * <p>A control for selecting whether optical stabilization (OIS) position
+ * information is included in output result metadata.</p>
*/
ANDROID_STATISTICS_OIS_DATA_MODE = android.hardware.camera.metadata@3.2::CameraMetadataTag:ANDROID_STATISTICS_END,
diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp
new file mode 100644
index 0000000..388df68
--- /dev/null
+++ b/camera/metadata/3.4/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.camera.metadata@3.4",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ ],
+ interfaces: [
+ "android.hardware.camera.metadata@3.2",
+ "android.hardware.camera.metadata@3.3",
+ ],
+ types: [
+ "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion",
+ "CameraMetadataTag",
+ ],
+ gen_java: true,
+}
+
diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal
new file mode 100644
index 0000000..b228de8
--- /dev/null
+++ b/camera/metadata/3.4/types.hal
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.4;
+
+/* Include definitions from all prior minor HAL metadata revisions */
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.3::CameraMetadataTag {
+ /** android.request.characteristicKeysNeedingPermission [static, int32[], hidden]
+ *
+ * <p>A list of camera characteristics keys that are only available
+ * in case the camera client has camera permission.</p>
+ */
+ ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_REQUEST_END_3_3,
+
+ ANDROID_REQUEST_END_3_4,
+
+ /** android.info.supportedBufferManagementVersion [static, enum, system]
+ *
+ * <p>The version of buffer management API this camera device supports and opts into.</p>
+ */
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_INFO_END_3_3,
+
+ ANDROID_INFO_END_3_4,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
+
+/** android.info.supportedBufferManagementVersion enumeration values
+ * @see ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION
+ */
+enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t {
+ ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5,
+};
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index ae24d78..de02d78 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -14,10 +14,12 @@
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
"camera.device@1.0-impl",
"camera.device@3.2-impl",
"camera.device@3.3-impl",
"camera.device@3.4-impl",
+ "camera.device@3.5-impl",
"camera.device@3.4-external-impl",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
@@ -31,6 +33,7 @@
],
header_libs: [
"camera.device@3.4-impl_headers",
+ "camera.device@3.5-impl_headers",
"camera.device@3.4-external-impl_headers"
],
static_libs: [
@@ -56,6 +59,7 @@
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
],
@@ -80,6 +84,7 @@
"android.hardware.camera.device@3.2",
"android.hardware.camera.device@3.3",
"android.hardware.camera.device@3.4",
+ "android.hardware.camera.device@3.5",
"android.hardware.camera.provider@2.4",
"android.hardware.camera.common@1.0",
],
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 6313939..488b9af 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -23,6 +23,7 @@
#include "CameraDevice_1_0.h"
#include "CameraDevice_3_3.h"
#include "CameraDevice_3_4.h"
+#include "CameraDevice_3_5.h"
#include <cutils/properties.h>
#include <string.h>
#include <utils/Trace.h>
@@ -43,6 +44,7 @@
const char *kHAL3_2 = "3.2";
const char *kHAL3_3 = "3.3";
const char *kHAL3_4 = "3.4";
+const char *kHAL3_5 = "3.5";
const char *kHAL1_0 = "1.0";
const int kMaxCameraDeviceNameLen = 128;
const int kMaxCameraIdLen = 16;
@@ -250,7 +252,11 @@
int versionMajor = isV1 ? 1 : 3;
int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) {
- versionMinor = 4;
+ if (mModule->getModuleApiVersion() == CAMERA_MODULE_API_VERSION_2_5) {
+ versionMinor = 5;
+ } else {
+ versionMinor = 4;
+ }
}
char deviceName[kMaxCameraDeviceNameLen];
snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
@@ -546,63 +552,69 @@
return Void();
}
- sp<android::hardware::camera::device::V3_2::ICameraDevice> device;
- if (deviceVersion == kHAL3_4) {
+ // ICameraDevice 3.4 or upper
+ sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl;
+ if (deviceVersion >= kHAL3_4) {
ALOGV("Constructing v3.4 camera device");
- sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
- new android::hardware::camera::device::V3_4::implementation::CameraDevice(
+ if (deviceVersion == kHAL3_4) {
+ deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
+ } else if (deviceVersion == kHAL3_5) {
+ deviceImpl = new android::hardware::camera::device::V3_5::implementation::CameraDevice(
+ mModule, cameraId, mCameraDeviceNames);
+ }
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
- device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
-
- device = deviceImpl;
- _hidl_cb (Status::OK, device);
+ IF_ALOGV() {
+ deviceImpl->getInterface()->interfaceChain([](
+ ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+ ALOGV("Device interface chain:");
+ for (auto iface : interfaceChain) {
+ ALOGV(" %s", iface.c_str());
+ }
+ });
+ }
+ _hidl_cb (Status::OK, deviceImpl->getInterface());
return Void();
}
+ // ICameraDevice 3.2 and 3.3
// Since some Treble HAL revisions can map to the same legacy HAL version(s), we default
// to the newest possible Treble HAL revision, but allow for override if needed via
// system property.
switch (mPreferredHal3MinorVersion) {
case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2
ALOGV("Constructing v3.2 camera device");
- sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
- new android::hardware::camera::device::V3_2::implementation::CameraDevice(
+ deviceImpl = new android::hardware::camera::device::V3_2::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
- device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
- device = deviceImpl;
break;
}
case 3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3
ALOGV("Constructing v3.3 camera device");
- sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
- new android::hardware::camera::device::V3_3::implementation::CameraDevice(
+ deviceImpl = new android::hardware::camera::device::V3_3::implementation::CameraDevice(
mModule, cameraId, mCameraDeviceNames);
if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
- device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
- device = deviceImpl;
break;
}
default:
ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
- device = nullptr;
_hidl_cb(Status::INTERNAL_ERROR, nullptr);
return Void();
}
- _hidl_cb (Status::OK, device);
+
+ _hidl_cb (Status::OK, deviceImpl->getInterface());
return Void();
}
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 71b78f4..fd9396c 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -2088,6 +2088,14 @@
} else {
ADD_FAILURE() << "Get camera hardware level failed!";
}
+
+ entry.count = 0;
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION, &entry);
+ if ((0 == retcode) || (entry.count > 0)) {
+ ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION "
+ << " per API contract should never be set by Hal!";
+ }
});
ASSERT_TRUE(ret.isOk());
}
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index e13d293..fc7bad6 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -445,7 +445,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.wifi.hostapd</name>
- <version>1.0</version>
+ <version>1.0-1</version>
<interface>
<name>IHostapd</name>
<instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 0d60be6..ff5b3e8 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -56,6 +56,14 @@
</interface>
</hal>
<hal format="hidl" optional="true">
+ <name>android.hardware.biometrics.face</name>
+ <version>1.0</version>
+ <interface>
+ <name>IBiometricsFace</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="hidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
<version>2.1</version>
<interface>
@@ -113,7 +121,7 @@
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.configstore</name>
- <version>1.1</version>
+ <version>1.2</version>
<interface>
<name>ISurfaceFlingerConfigs</name>
<instance>default</instance>
@@ -216,16 +224,20 @@
</interface>
</hal>
<hal format="hidl" optional="true">
- <name>android.hardware.health.filesystem</name>
+ <name>android.hardware.health.storage</name>
<version>1.0</version>
<interface>
- <name>IFileSystem</name>
+ <name>IStorage</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.ir</name>
<version>1.0</version>
+ <interface>
+ <name>IConsumerIr</name>
+ <instance>default</instance>
+ </interface>
</hal>
<hal format="hidl" optional="false">
<name>android.hardware.keymaster</name>
@@ -441,7 +453,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.wifi</name>
- <version>1.0-2</version>
+ <version>1.0-3</version>
<interface>
<name>IWifi</name>
<instance>default</instance>
diff --git a/configstore/1.1/default/SurfaceFlingerConfigs.h b/configstore/1.1/default/SurfaceFlingerConfigs.h
deleted file mode 100644
index 3714e81..0000000
--- a/configstore/1.1/default/SurfaceFlingerConfigs.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
-#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
-
-#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace configstore {
-namespace V1_1 {
-namespace implementation {
-
-using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs {
- // Methods from
- // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs follow.
- Return<void> vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) override;
- Return<void> vsyncSfEventPhaseOffsetNs(vsyncSfEventPhaseOffsetNs_cb _hidl_cb) override;
- Return<void> useContextPriority(useContextPriority_cb _hidl_cb) override;
- Return<void> hasWideColorDisplay(hasWideColorDisplay_cb _hidl_cb) override;
- Return<void> hasHDRDisplay(hasHDRDisplay_cb _hidl_cb) override;
- Return<void> presentTimeOffsetFromVSyncNs(presentTimeOffsetFromVSyncNs_cb _hidl_cb) override;
- Return<void> useHwcForRGBtoYUV(useHwcForRGBtoYUV_cb _hidl_cb) override;
- Return<void> maxVirtualDisplaySize(maxVirtualDisplaySize_cb _hidl_cb) override;
- Return<void> hasSyncFramework(hasSyncFramework_cb _hidl_cb) override;
- Return<void> useVrFlinger(useVrFlinger_cb _hidl_cb) override;
- Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
- Return<void> startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override;
-
- // Methods from
- // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow.
- Return<void> primaryDisplayOrientation(primaryDisplayOrientation_cb _hidl_cb) override;
-
- // Methods from ::android::hidl::base::V1_0::IBase follow.
-};
-
-} // namespace implementation
-} // namespace V1_1
-} // namespace configstore
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp
new file mode 100644
index 0000000..cc5644c
--- /dev/null
+++ b/configstore/1.2/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.configstore@1.2",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "ISurfaceFlingerConfigs.hal",
+ ],
+ interfaces: [
+ "android.hardware.configstore@1.1",
+ "android.hardware.configstore@1.0",
+ "android.hardware.graphics.common@1.1",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
\ No newline at end of file
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
new file mode 100644
index 0000000..c879155
--- /dev/null
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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.configstore@1.2;
+
+import android.hardware.graphics.common@1.1::Dataspace;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import @1.1::ISurfaceFlingerConfigs;
+import @1.0::OptionalBool;
+
+/**
+ * New revision of ISurfaceFlingerConfigs
+ */
+interface ISurfaceFlingerConfigs extends @1.1::ISurfaceFlingerConfigs {
+ /**
+ * useColorManagement indicates whether SurfaceFlinger should manage color
+ * by switching to appropriate color mode automatically depending on the
+ * Dataspace of the surfaces on screen.
+ * This function must return true when hasWideColorDisplay or hasHDRDisplay
+ * return true.
+ */
+ useColorManagement() generates (OptionalBool value);
+
+ /**
+ * Returns the default data space and default pixel format that
+ * SurfaceFlinger expects to receive and output.
+ * To determine the default data space and default pixel format,
+ * there are a few things we recommend to consider:
+ *
+ * 1. Hardware composer's capability to composite contents with the
+ * data space and pixel format efficiently;
+ * 2. Hardware composer's ability to composite contents when sRGB contents
+ * and the chosen data space contents coexist;
+ * 3. For better blending, consider using pixel format where the alpha
+ * channel has as many bits as the RGB color channel.
+ *
+ * @return dataSpace is the default data space that SurfaceFlinger expects.
+ * The data space must not be Dataspace::UNKNOWN, if unspecified,
+ * the default data space is Dataspace::V0_SRGB;
+ * @return pixelFormat is the default pixel format that SurfaceFlinger
+ * expects. If unspecified, the default pixel format is
+ * PixelFormat::RGBA_8888.
+ */
+ getCompositionPreference()
+ generates (Dataspace dataSpace, PixelFormat pixelFormat);
+};
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.2/default/Android.mk
similarity index 67%
rename from configstore/1.1/default/Android.mk
rename to configstore/1.2/default/Android.mk
index 40f621b..b807357 100644
--- a/configstore/1.1/default/Android.mk
+++ b/configstore/1.2/default/Android.mk
@@ -2,15 +2,15 @@
################################################################################
include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.1-service
+LOCAL_MODULE := android.hardware.configstore@1.2-service
# seccomp is not required for coverage build.
ifneq ($(NATIVE_COVERAGE),true)
-LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy
+LOCAL_REQUIRED_MODULES_arm64 := configstore.policy
endif
-LOCAL_PROPRIETARY_MODULE := true
+LOCAL_VENDOR_MODULE := true
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc
+LOCAL_INIT_RC := android.hardware.configstore@1.2-service.rc
LOCAL_SRC_FILES:= service.cpp
include $(LOCAL_PATH)/surfaceflinger.mk
@@ -23,16 +23,17 @@
liblog \
libutils \
android.hardware.configstore@1.0 \
- android.hardware.configstore@1.1
+ android.hardware.configstore@1.1 \
+ android.hardware.configstore@1.2
include $(BUILD_EXECUTABLE)
# seccomp filter for configstore
ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64))
include $(CLEAR_VARS)
-LOCAL_MODULE := configstore@1.1.policy
+LOCAL_MODULE := configstore.policy
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
-LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
+LOCAL_SRC_FILES := seccomp_policy/configstore-$(TARGET_ARCH).policy
include $(BUILD_PREBUILT)
endif
diff --git a/configstore/1.1/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
similarity index 79%
rename from configstore/1.1/default/SurfaceFlingerConfigs.cpp
rename to configstore/1.2/default/SurfaceFlingerConfigs.cpp
index da3081c..ae19dc0 100644
--- a/configstore/1.1/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -17,16 +17,19 @@
#include "SurfaceFlingerConfigs.h"
#include <android/hardware/configstore/1.1/types.h>
+#include <android/hardware/graphics/common/1.1/types.h>
#include <log/log.h>
namespace android {
namespace hardware {
namespace configstore {
-namespace V1_1 {
+namespace V1_2 {
namespace implementation {
-// Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs
-// follow.
+using ::android::hardware::graphics::common::V1_1::Dataspace;
+using ::android::hardware::graphics::common::V1_1::PixelFormat;
+
+// ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
Return<void> SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) {
#ifdef VSYNC_EVENT_PHASE_OFFSET_NS
_hidl_cb({true, VSYNC_EVENT_PHASE_OFFSET_NS});
@@ -142,8 +145,7 @@
return Void();
}
-// Methods from ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs
-// follow.
+// ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs implementation.
#ifdef PRIMARY_DISPLAY_ORIENTATION
static_assert(PRIMARY_DISPLAY_ORIENTATION == 0 || PRIMARY_DISPLAY_ORIENTATION == 90 ||
@@ -191,10 +193,37 @@
return Void();
}
-// Methods from ::android::hidl::base::V1_0::IBase follow.
+// ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs implementation.
+Return<void> SurfaceFlingerConfigs::useColorManagement(useColorManagement_cb _hidl_cb) {
+#if defined(USE_COLOR_MANAGEMENT) || defined(HAS_WIDE_COLOR_DISPLAY) || defined(HAS_HDR_DISPLAY)
+ _hidl_cb({true, true});
+#else
+ _hidl_cb({true, false});
+#endif
+ return Void();
+}
+
+#ifdef COMPOSITION_DATA_SPACE
+static_assert(COMPOSITION_DATA_SPACE != 0, "Expected composition data space must not be UNKNOWN");
+#endif
+
+Return<void> SurfaceFlingerConfigs::getCompositionPreference(getCompositionPreference_cb _hidl_cb) {
+ Dataspace dataSpace = Dataspace::V0_SRGB;
+ PixelFormat pixelFormat = PixelFormat::RGBA_8888;
+
+#ifdef COMPOSITION_DATA_SPACE
+ dataSpace = static_cast<Dataspace>(COMPOSITION_DATA_SPACE);
+#endif
+
+#ifdef COMPOSITION_PIXEL_FORMAT
+ pixelFormat = static_cast<PixelFormat>(COMPOSITION_PIXEL_FORMAT);
+#endif
+ _hidl_cb(dataSpace, pixelFormat);
+ return Void();
+}
} // namespace implementation
-} // namespace V1_1
+} // namespace V1_2
} // namespace configstore
} // namespace hardware
} // namespace android
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.h b/configstore/1.2/default/SurfaceFlingerConfigs.h
new file mode 100644
index 0000000..7dd8f6d
--- /dev/null
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H
+#define ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H
+
+#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace configstore {
+namespace V1_2 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
+
+struct SurfaceFlingerConfigs : public ISurfaceFlingerConfigs {
+ // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
+ Return<void> vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) override;
+ Return<void> vsyncSfEventPhaseOffsetNs(vsyncSfEventPhaseOffsetNs_cb _hidl_cb) override;
+ Return<void> useContextPriority(useContextPriority_cb _hidl_cb) override;
+ Return<void> hasWideColorDisplay(hasWideColorDisplay_cb _hidl_cb) override;
+ Return<void> hasHDRDisplay(hasHDRDisplay_cb _hidl_cb) override;
+ Return<void> presentTimeOffsetFromVSyncNs(presentTimeOffsetFromVSyncNs_cb _hidl_cb) override;
+ Return<void> useHwcForRGBtoYUV(useHwcForRGBtoYUV_cb _hidl_cb) override;
+ Return<void> maxVirtualDisplaySize(maxVirtualDisplaySize_cb _hidl_cb) override;
+ Return<void> hasSyncFramework(hasSyncFramework_cb _hidl_cb) override;
+ Return<void> useVrFlinger(useVrFlinger_cb _hidl_cb) override;
+ Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
+ Return<void> startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override;
+
+ // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow implementation.
+ Return<void> primaryDisplayOrientation(primaryDisplayOrientation_cb _hidl_cb) override;
+
+ // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation.
+ Return<void> useColorManagement(useColorManagement_cb _hidl_cb) override;
+ Return<void> getCompositionPreference(getCompositionPreference_cb _hidl_cb) override;
+};
+
+} // namespace implementation
+} // namespace V1_2
+} // namespace configstore
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CONFIGSTORE_V1_2_SURFACEFLINGERCONFIGS_H
diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.2/default/android.hardware.configstore@1.2-service.rc
similarity index 83%
rename from configstore/1.1/default/android.hardware.configstore@1.1-service.rc
rename to configstore/1.2/default/android.hardware.configstore@1.2-service.rc
index 105678a..d6c5d10 100644
--- a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
+++ b/configstore/1.2/default/android.hardware.configstore@1.2-service.rc
@@ -1,4 +1,4 @@
-service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service
+service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.2-service
class hal animation
user system
group system
diff --git a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy b/configstore/1.2/default/seccomp_policy/configstore-arm64.policy
similarity index 100%
rename from configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
rename to configstore/1.2/default/seccomp_policy/configstore-arm64.policy
diff --git a/configstore/1.1/default/service.cpp b/configstore/1.2/default/service.cpp
similarity index 80%
rename from configstore/1.1/default/service.cpp
rename to configstore/1.2/default/service.cpp
index 3b4e774..65a42f5 100644
--- a/configstore/1.1/default/service.cpp
+++ b/configstore/1.2/default/service.cpp
@@ -14,27 +14,27 @@
* limitations under the License.
*/
-#define LOG_TAG "android.hardware.configstore@1.1-service"
+#define LOG_TAG "android.hardware.configstore@1.2-service"
-#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.2/ISurfaceFlingerConfigs.h>
#include <hidl/HidlTransportSupport.h>
#include <hwminijail/HardwareMinijail.h>
#include "SurfaceFlingerConfigs.h"
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
-using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs;
-using android::hardware::SetupMinijail;
+using android::OK;
using android::sp;
using android::status_t;
-using android::OK;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::SetupMinijail;
+using android::hardware::configstore::V1_2::ISurfaceFlingerConfigs;
+using android::hardware::configstore::V1_2::implementation::SurfaceFlingerConfigs;
int main() {
configureRpcThreadpool(10, true);
- SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.1.policy");
+ SetupMinijail("/vendor/etc/seccomp_policy/configstore.policy");
sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
status_t status = surfaceFlingerConfigs->registerAsService();
diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk
similarity index 82%
rename from configstore/1.1/default/surfaceflinger.mk
rename to configstore/1.2/default/surfaceflinger.mk
index 35922eb..f323999 100644
--- a/configstore/1.1/default/surfaceflinger.mk
+++ b/configstore/1.2/default/surfaceflinger.mk
@@ -54,3 +54,15 @@
ifneq ($(SF_PRIMARY_DISPLAY_ORIENTATION),)
LOCAL_CFLAGS += -DPRIMARY_DISPLAY_ORIENTATION=$(SF_PRIMARY_DISPLAY_ORIENTATION)
endif
+
+ifeq ($(TARGET_USE_COLOR_MANAGEMENT),true)
+ LOCAL_CFLAGS += -DUSE_COLOR_MANAGEMENT
+endif
+
+ifneq ($(SF_COMPOSITION_DATA_SPACE),)
+ LOCAL_CFLAGS += -DCOMPOSITION_DATA_SPACE=$(SF_COMPOSITION_DATA_SPACE)
+endif
+
+ifneq ($(SF_COMPOSITION_PIXEL_FORMAT),)
+ LOCAL_CFLAGS += -DCOMPOSITION_PIXEL_FORMAT=$(SF_COMPOSITION_PIXEL_FORMAT)
+endif
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index 178f245..e0d4aa8 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -30,12 +30,14 @@
shared_libs: [
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
+ "android.hardware.configstore@1.2",
"libbase",
"libhidlbase"
],
export_shared_lib_headers: [
"android.hardware.configstore@1.0",
"android.hardware.configstore@1.1",
+ "android.hardware.configstore@1.2",
"libbase",
"libhidlbase"
],
diff --git a/contexthub/1.0/default/OWNERS b/contexthub/1.0/default/OWNERS
index 49a3204..5373073 100644
--- a/contexthub/1.0/default/OWNERS
+++ b/contexthub/1.0/default/OWNERS
@@ -1,2 +1,4 @@
-ashutoshj@google.com
+aarossig@google.com
+arthuri@google.com
bduddie@google.com
+bstack@google.com
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index ad036b4..ee01441 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -1,6 +1,8 @@
#Context Hub team
-ashutoshj@google.com
+aarossig@google.com
+arthuri@google.com
bduddie@google.com
+bstack@google.com
#VTS team
yim@google.com
diff --git a/current.txt b/current.txt
index 327833f..4709ab3 100644
--- a/current.txt
+++ b/current.txt
@@ -385,6 +385,10 @@
10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
# ABI preserving changes to HALs during Android Q
+2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
+f61b616732d8f374e030f90575d7eba3ecc99d209a05b945949ba892bcb81e1d android.hardware.camera.device@3.2::ICameraDeviceSession
+684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
+a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types
da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
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..250c392 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 {
@@ -295,7 +293,6 @@
if (queueChanged) {
auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
- return;
}
mClient->executeCommands(commandLength, commandHandles,
@@ -314,6 +311,8 @@
ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
reader->parse();
});
+ reader->reset();
+ writer->reset();
}
} // namespace vts
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
index 6f8f1ad..454a89c 100644
--- a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -26,23 +26,55 @@
namespace vts {
void TestCommandReader::parse() {
+ mErrors.clear();
+ mCompositionChanges.clear();
while (!isEmpty()) {
IComposerClient::Command command;
uint16_t length;
ASSERT_TRUE(beginCommand(&command, &length));
switch (command) {
+ case IComposerClient::Command::SELECT_DISPLAY:
+ ASSERT_EQ(2, length);
+ read64(); // display
+ break;
case IComposerClient::Command::SET_ERROR: {
ASSERT_EQ(2, length);
auto loc = read();
auto err = readSigned();
- GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
+ std::pair<uint32_t, uint32_t> error(loc, err);
+ mErrors.push_back(error);
} break;
- case IComposerClient::Command::SELECT_DISPLAY:
case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+ ASSERT_EQ(0, length % 3);
+ for (uint16_t count = 0; count < length / 3; ++count) {
+ uint64_t layerId = read64();
+ uint32_t composition = read();
+
+ std::pair<uint64_t, uint32_t> compositionChange(layerId, composition);
+ mCompositionChanges.push_back(compositionChange);
+ }
+ break;
case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+ ASSERT_EQ(1, length % 3);
+ read(); // displayRequests, ignored for now
+ for (uint16_t count = 0; count < (length - 1) / 3; ++count) {
+ read64(); // layer
+ // silently eat requests to clear the client target, since we won't be testing
+ // client composition anyway
+ ASSERT_EQ(1u, read());
+ }
+ break;
case IComposerClient::Command::SET_PRESENT_FENCE:
+ ASSERT_EQ(1, length);
+ close(readFence());
+ break;
case IComposerClient::Command::SET_RELEASE_FENCES:
+ ASSERT_EQ(0, length % 3);
+ for (uint16_t count = 0; count < length / 3; ++count) {
+ read64();
+ close(readFence());
+ }
break;
default:
GTEST_FAIL() << "unexpected return command " << std::hex
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.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
index 3888eeb..c12debe 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -32,6 +32,9 @@
// Parse all commands in the return command queue. Call GTEST_FAIL() for
// unexpected errors or commands.
void parse();
+
+ std::vector<std::pair<uint32_t, uint32_t>> mErrors;
+ std::vector<std::pair<uint64_t, uint32_t>> mCompositionChanges;
};
} // namespace vts
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 72f3f1b..0a3e88b 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -71,6 +71,7 @@
class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
void SetUp() override {
+ VtsHalHidlTargetTestBase::SetUp();
ASSERT_NO_FATAL_FAILURE(
mComposer = std::make_unique<Composer>(
GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
@@ -85,6 +86,13 @@
// explicitly disable vsync
mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
mComposerCallback->setVsyncAllowed(false);
+
+ mInvalidDisplayId = GetInvalidDisplayId();
+
+ // Although 0 could be an invalid display, a return value of 0
+ // from GetInvalidDisplayId means all other ids are in use, a condition which
+ // we are assuming a device will never have
+ ASSERT_NE(0, mInvalidDisplayId);
}
void TearDown() override {
@@ -93,6 +101,24 @@
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
}
+ VtsHalHidlTargetTestBase::TearDown();
+ }
+
+ // returns an invalid display id (one that has not been registered to a
+ // display. Currently assuming that a device will never have close to
+ // std::numeric_limit<uint64_t>::max() displays registered while running tests
+ Display GetInvalidDisplayId() {
+ std::vector<Display> validDisplays = mComposerCallback->getDisplays();
+
+ uint64_t id = std::numeric_limits<uint64_t>::max();
+ while (id > 0) {
+ if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) {
+ return id;
+ }
+ id--;
+ }
+
+ return 0;
}
// use the slot count usually set by SF
@@ -103,6 +129,7 @@
sp<GraphicsComposerCallback> mComposerCallback;
// the first display and is assumed never to be removed
Display mPrimaryDisplay;
+ Display mInvalidDisplayId;
private:
Display waitForFirstDisplay() {
@@ -172,6 +199,22 @@
}
/**
+ * Test IComposerClient::destroyVirtualDisplay
+ *
+ * Test that passing a bad display handle to destroyVirtualDisplay
+ * returns a BAD_DISPLAY error
+ */
+TEST_F(GraphicsComposerHidlTest, DestroyVirtualDisplayBadDisplay) {
+ if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
+ GTEST_SUCCEED() << "no virtual display support";
+ return;
+ }
+
+ Error error = mComposerClient->getRaw()->destroyVirtualDisplay(mInvalidDisplayId);
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
* Test IComposerClient::createLayer and IComposerClient::destroyLayer.
*
* Test that layers can be created and destroyed.
@@ -185,6 +228,89 @@
}
/**
+ * Test IComposerClient::createLayer
+ *
+ * Test that passing in an invalid display handle to createLayer returns
+ * BAD_DISPLAY.
+ */
+TEST_F(GraphicsComposerHidlTest, CreateLayerBadDisplay) {
+ Error error;
+ mComposerClient->getRaw()->createLayer(
+ mInvalidDisplayId, kBufferSlotCount,
+ [&](const auto& tmpOutError, const auto&) { error = tmpOutError; });
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::destroyLayer
+ *
+ * Test that passing in an invalid display handle to destroyLayer returns
+ * BAD_DISPLAY
+ */
+TEST_F(GraphicsComposerHidlTest, DestroyLayerBadDisplay) {
+ Error error;
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+
+ error = mComposerClient->getRaw()->destroyLayer(mInvalidDisplayId, layer);
+
+ EXPECT_EQ(Error::BAD_DISPLAY, error);
+
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer));
+}
+
+/**
+ * Test IComposerClient::destroyLayer
+ *
+ * Test that passing in an invalid layer handle to destroyLayer returns
+ * BAD_LAYER
+ */
+TEST_F(GraphicsComposerHidlTest, DestroyLayerBadLayerError) {
+ // We haven't created any layers yet, so any id should be invalid
+ Error error = mComposerClient->getRaw()->destroyLayer(mPrimaryDisplay, 1);
+
+ EXPECT_EQ(Error::BAD_LAYER, error);
+}
+
+/**
+ * Test IComposerClient::getActiveConfig
+ *
+ * Test that passing in a bad display handle to getActiveConfig generates a
+ * BAD_DISPLAY error
+ */
+TEST_F(GraphicsComposerHidlTest, GetActiveConfigBadDisplay) {
+ Error error;
+ mComposerClient->getRaw()->getActiveConfig(
+ mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; });
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::getDisplayConfigs
+ *
+ * Test IComposerClient::getDisplayConfigs returns no error
+ * when passed in a valid display
+ */
+TEST_F(GraphicsComposerHidlTest, GetDisplayConfig) {
+ std::vector<Config> configs;
+ ASSERT_NO_FATAL_FAILURE(configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay));
+}
+
+/**
+ * Test IComposerClient::getDisplayConfigs
+ *
+ * Test IComposerClient::getDisplayConfigs returns BAD_DISPLAY
+ * when passed in an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetDisplayConfigBadDisplay) {
+ Error error;
+ mComposerClient->getRaw()->getDisplayConfigs(
+ mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; });
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
* Test IComposerClient::getDisplayName.
*/
TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
@@ -226,6 +352,30 @@
}
/**
+ * Test IComposerClient::getClientTargetSupport
+ *
+ * Test that IComposerClient::getClientTargetSupport returns BAD_DISPLAY when
+ * passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupportBadDisplay) {
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::WIDTH);
+ int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::HEIGHT);
+ ASSERT_LT(0, width);
+ ASSERT_LT(0, height);
+
+ mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+
+ Error error = mComposerClient->getRaw()->getClientTargetSupport(
+ mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN);
+ EXPECT_EQ(Error::BAD_DISPLAY, error);
+ }
+}
+
+/**
* Test IComposerClient::getDisplayAttribute.
*
* Test that IComposerClient::getDisplayAttribute succeeds for the required
@@ -287,6 +437,43 @@
}
/**
+ * Test IComposerClient::setActiveConfig
+ *
+ * Test that config set during IComposerClient::setActiveConfig is maintained
+ * during a display on/off power cycle
+ */
+TEST_F(GraphicsComposerHidlTest, SetActiveConfigPowerCycle) {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::OFF));
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON));
+
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+ ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
+
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::OFF));
+ ASSERT_NO_FATAL_FAILURE(
+ mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON));
+ ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
+ }
+}
+
+/**
+ * Test IComposerClient::getColorMode
+ *
+ * Test that IComposerClient::getColorMode always returns ColorMode::NATIVE
+ */
+TEST_F(GraphicsComposerHidlTest, GetColorModes) {
+ std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+ auto nativeModeLocation = std::find(modes.begin(), modes.end(), ColorMode::NATIVE);
+
+ ASSERT_NE(modes.end(), nativeModeLocation);
+}
+
+/**
* Test IComposerClient::setColorMode.
*
* Test that IComposerClient::setColorMode succeeds for all color modes.
@@ -306,6 +493,45 @@
}
/**
+ * Test IComposerClient::setColorMode
+ *
+ * Test that IComposerClient::setColorMode returns BAD_DISPLAY for
+ * an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorModeBadDisplay) {
+ std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+ for (auto mode : modes) {
+ Error error = mComposerClient->getRaw()->setColorMode(mInvalidDisplayId, mode);
+ EXPECT_EQ(Error::BAD_DISPLAY, error);
+ }
+}
+
+/**
+ * Test IComposerClient::setColorMode
+ *
+ * Test that IComposerClient::setColorMode returns BAD_PARAMETER when passed in
+ * an invalid color mode
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorModeBadParameter) {
+ Error error =
+ mComposerClient->getRaw()->setColorMode(mPrimaryDisplay, static_cast<ColorMode>(-1));
+ ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+/**
+ * Test IComposerClient::getDozeSupport
+ *
+ * Test that IComposerClient::getDozeSupport returns
+ * BAD_DISPLAY when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetDozeSupportBadDisplay) {
+ Error error;
+ mComposerClient->getRaw()->getDozeSupport(
+ mInvalidDisplayId, [&](const auto& tmpOutError, const auto&) { error = tmpOutError; });
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
* Test IComposerClient::setPowerMode.
*
* Test that IComposerClient::setPowerMode succeeds for all power modes.
@@ -328,6 +554,99 @@
}
/**
+ * Test IComposerClient::setPowerMode
+ *
+ * Test IComposerClient::setPowerMode succeeds with different
+ * orderings of power modes
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerModeVariations) {
+ std::vector<IComposerClient::PowerMode> modes;
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ modes.push_back(IComposerClient::PowerMode::ON);
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::ON);
+ modes.push_back(IComposerClient::PowerMode::ON);
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+ if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+ modes.push_back(IComposerClient::PowerMode::DOZE);
+ modes.push_back(IComposerClient::PowerMode::DOZE);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+ modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+ }
+ }
+}
+
+/**
+ * Test IComposerClient::setPowerMode
+ *
+ * Test IComposerClient::setPowerMode returns BAD_DISPLAY when passed an invalid
+ * display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerModeBadDisplay) {
+ Error error =
+ mComposerClient->getRaw()->setPowerMode(mInvalidDisplayId, IComposerClient::PowerMode::ON);
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::setPowerMode
+ *
+ * Test that IComposerClient::setPowerMode returns UNSUPPORTED when passed DOZE
+ * or DOZE_SUSPEND on devices that do not support DOZE/DOZE_SUSPEND
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerModeUnsupported) {
+ if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+ Error error = mComposerClient->getRaw()->setPowerMode(mPrimaryDisplay,
+ IComposerClient::PowerMode::DOZE);
+ EXPECT_EQ(Error::UNSUPPORTED, error);
+
+ error = mComposerClient->getRaw()->setPowerMode(mPrimaryDisplay,
+ IComposerClient::PowerMode::DOZE_SUSPEND);
+ EXPECT_EQ(Error::UNSUPPORTED, error);
+ }
+}
+
+/**
+ * Test IComposerClient::setPowerMode
+ *
+ * Tests that IComposerClient::setPowerMode returns BAD_PARAMETER when passed an invalid
+ * PowerMode
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerModeBadParameter) {
+ Error error = mComposerClient->getRaw()->setPowerMode(
+ mPrimaryDisplay, static_cast<IComposerClient::PowerMode>(-1));
+ ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+/**
* Test IComposerClient::setVsyncEnabled.
*
* Test that IComposerClient::setVsyncEnabled succeeds and there is no
@@ -351,20 +670,29 @@
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+ Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
+ mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ IComposerClient::Attribute::WIDTH);
+ mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ IComposerClient::Attribute::HEIGHT);
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<TestCommandReader>();
}
- void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
+ void TearDown() override {
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
+ }
const native_handle_t* allocate() {
IMapper::BufferDescriptorInfo info{};
- info.width = 64;
- info.height = 64;
+ info.width = mDisplayWidth;
+ info.height = mDisplayHeight;
info.layerCount = 1;
info.format = PixelFormat::RGBA_8888;
info.usage =
- static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY);
return mGralloc->allocate(info);
}
@@ -373,6 +701,8 @@
std::unique_ptr<CommandWriterBase> mWriter;
std::unique_ptr<TestCommandReader> mReader;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
private:
std::unique_ptr<Gralloc> mGralloc;
@@ -459,6 +789,60 @@
}
/**
+ * Test IComposerClient::Command::PRESENT_DISPLAY
+ *
+ * Test that IComposerClient::Command::PRESENT_DISPLAY works without
+ * additional call to validateDisplay when only the layer buffer handle and
+ * surface damage have been set
+ */
+TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON);
+ mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB);
+
+ auto handle = allocate();
+ ASSERT_NE(nullptr, handle);
+
+ IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+ mWriter->setLayerDisplayFrame(displayFrame);
+ mWriter->setLayerPlaneAlpha(1);
+ mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+ mWriter->setLayerTransform(static_cast<Transform>(0));
+ mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, displayFrame));
+ mWriter->setLayerZOrder(10);
+ mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
+ mWriter->setLayerBuffer(0, handle, -1);
+ mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+
+ mWriter->validateDisplay();
+ execute();
+ if (mReader->mCompositionChanges.size() != 0) {
+ GTEST_SUCCEED() << "Composition change requested, skipping test";
+ return;
+ }
+
+ ASSERT_EQ(0, mReader->mErrors.size());
+ mWriter->presentDisplay();
+ execute();
+ ASSERT_EQ(0, mReader->mErrors.size());
+
+ mWriter->selectLayer(layer);
+ auto handle2 = allocate();
+ ASSERT_NE(nullptr, handle2);
+ mWriter->setLayerBuffer(0, handle2, -1);
+ mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+ mWriter->presentDisplay();
+ execute();
+}
+
+/**
* Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
*/
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 6a32071..da99460 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,43 @@
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();
+ });
+ reader->reset();
+ writer->reset();
}
-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 +109,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 +138,40 @@
});
}
-void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFence) {
- hidl_handle handle;
- mClient_v2_2->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
+void ComposerClient::getReadbackBufferFence(Display display, int32_t* outFence) {
+ mClient->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence";
- handle = tmpHandle;
+ const native_handle_t* nativeFenceHandle = tmpHandle.getNativeHandle();
+ *outFence = dup(nativeFenceHandle->data[0]);
});
- *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/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 669fbae..acc9245 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -17,12 +17,15 @@
cc_test {
name: "VtsHalGraphicsComposerV2_2TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
- srcs: ["VtsHalGraphicsComposerV2_2TargetTest.cpp"],
+ srcs: [
+ "VtsHalGraphicsComposerV2_2ReadbackTest.cpp",
+ "VtsHalGraphicsComposerV2_2TargetTest.cpp",
+ ],
// TODO(b/64437680): Assume these libs are always available on the device.
shared_libs: [
"libfmq",
- "libhidltransport",
+ "libhidltransport",
"libsync",
],
static_libs: [
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
new file mode 100644
index 0000000..91318bc
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "graphics_composer_hidl_hal_readback_tests@2.2"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+#include <composer-vts/2.2/ComposerVts.h>
+#include <mapper-vts/2.1/MapperVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace vts {
+namespace {
+
+using android::hardware::hidl_handle;
+using common::V1_1::BufferUsage;
+using common::V1_1::Dataspace;
+using common::V1_1::PixelFormat;
+using mapper::V2_1::IMapper;
+using mapper::V2_1::vts::Gralloc;
+using V2_1::Display;
+using V2_1::Layer;
+using V2_1::vts::TestCommandReader;
+
+// 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 TestLayer {
+ public:
+ TestLayer(std::shared_ptr<ComposerClient> const client, Display display)
+ : mLayer(client->createLayer(display, kBufferSlotCount)),
+ mComposerClient(client),
+ mDisplay(display) {}
+
+ virtual ~TestLayer() { mComposerClient->destroyLayer(mDisplay, mLayer); }
+
+ virtual void write(std::shared_ptr<CommandWriterBase> writer) {
+ writer->selectLayer(mLayer);
+ writer->setLayerDisplayFrame(mDisplayFrame);
+ writer->setLayerZOrder(mZOrder);
+ }
+
+ void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; }
+ void setZOrder(uint32_t z) { mZOrder = z; }
+
+ protected:
+ Layer mLayer;
+ IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
+ uint32_t mZOrder = 0;
+
+ private:
+ std::shared_ptr<ComposerClient> const mComposerClient;
+ const Display mDisplay;
+ static constexpr uint32_t kBufferSlotCount = 64;
+};
+
+class TestColorLayer : public TestLayer {
+ public:
+ TestColorLayer(std::shared_ptr<ComposerClient> const client, Display display)
+ : TestLayer{client, display} {}
+
+ void write(std::shared_ptr<CommandWriterBase> writer) override {
+ TestLayer::write(writer);
+ writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+ writer->setLayerColor(mColor);
+ }
+
+ void setColor(IComposerClient::Color color) { mColor = color; }
+
+ private:
+ IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
+};
+
+class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ using PowerMode = V2_1::IComposerClient::PowerMode;
+ 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();
+ Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
+ mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ IComposerClient::Attribute::WIDTH);
+ mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+ IComposerClient::Attribute::HEIGHT);
+
+ // explicitly disable vsync
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerCallback->setVsyncAllowed(false);
+
+ // set up command writer/reader and gralloc
+ mWriter = std::make_shared<CommandWriterBase>(1024);
+ mReader = std::make_unique<TestCommandReader>();
+ mGralloc = std::make_unique<Gralloc>();
+
+ mComposerClient->getRaw()->getReadbackBufferAttributes(
+ mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) {
+ mHasReadbackBuffer = tmpError == Error::NONE;
+ });
+ }
+
+ ~GraphicsComposerReadbackTest() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
+ }
+
+ void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+
+ void render(const std::vector<std::shared_ptr<TestLayer>>& layers) {
+ for (auto layer : layers) {
+ layer->write(mWriter);
+ }
+ execute();
+ mWriter->validateDisplay();
+ mWriter->presentDisplay();
+ execute();
+ }
+
+ int32_t GetBytesPerPixel(PixelFormat format) {
+ switch (format) {
+ case PixelFormat::RGBA_8888:
+ return 4;
+ case PixelFormat::RGB_888:
+ return 3;
+ default:
+ return -1;
+ }
+ }
+
+ bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
+ const Error error) {
+ if (error == Error::UNSUPPORTED) {
+ return false;
+ }
+ // TODO: add support for RGBA_1010102
+ if (pixelFormat != PixelFormat::RGB_888 && pixelFormat != PixelFormat::RGBA_8888) {
+ return false;
+ }
+ if (dataspace != Dataspace::V0_SRGB) {
+ return false;
+ }
+ return true;
+ }
+
+ void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+ Dataspace* outDataspace) {
+ mComposerClient->getRaw()->getReadbackBufferAttributes(
+ display, [&](const auto&, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
+ *outPixelFormat = tmpOutPixelFormat;
+ *outDataspace = tmpOutDataspace;
+ });
+ }
+
+ void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData,
+ std::vector<IComposerClient::Color> expectedColors) {
+ int32_t bytesPerPixel = GetBytesPerPixel(info.format);
+ ASSERT_NE(-1, bytesPerPixel)
+ << "unexpected pixel format " << static_cast<int32_t>(info.format)
+ << "(expected RGBA_8888 or RGB_888)";
+ for (int row = 0; row < mDisplayHeight; row++) {
+ for (int col = 0; col < mDisplayWidth; col++) {
+ int pixel = row * mDisplayWidth + col;
+ int offset = (row * stride + col) * bytesPerPixel;
+ uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+
+ EXPECT_EQ(expectedColors[pixel].r, pixelColor[0]);
+ EXPECT_EQ(expectedColors[pixel].g, pixelColor[1]);
+ EXPECT_EQ(expectedColors[pixel].b, pixelColor[2]);
+ }
+ }
+ }
+
+ std::unique_ptr<Composer> mComposer;
+ std::shared_ptr<ComposerClient> mComposerClient;
+
+ sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
+ // the first display and is assumed never to be removed
+ Display mPrimaryDisplay;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+ std::shared_ptr<CommandWriterBase> mWriter;
+ std::unique_ptr<TestCommandReader> mReader;
+ std::unique_ptr<Gralloc> mGralloc;
+
+ bool mHasReadbackBuffer;
+
+ private:
+ Display waitForFirstDisplay() {
+ while (true) {
+ std::vector<Display> displays = mComposerCallback->getDisplays();
+ if (displays.empty()) {
+ usleep(5 * 1000);
+ continue;
+ }
+ return displays[0];
+ }
+ }
+};
+
+TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) {
+ if (!mHasReadbackBuffer) {
+ GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+ return;
+ }
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON);
+ mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC);
+
+ auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+ IComposerClient::Color color({0, 0, 0xff, 0xff});
+ IComposerClient::Rect coloredSquare({100, 100, 500, 500});
+ layer->setColor(color);
+ layer->setDisplayFrame(coloredSquare);
+ layer->setZOrder(10);
+
+ std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+ // expected color for each pixel
+ std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+ for (int row = 0; row < mDisplayHeight; row++) {
+ for (int col = 0; col < mDisplayWidth; col++) {
+ int pixel = row * mDisplayWidth + col;
+ if (row >= coloredSquare.top && row < coloredSquare.bottom &&
+ col >= coloredSquare.left && col < coloredSquare.right) {
+ expectedColors[pixel] = color;
+ } else {
+ expectedColors[pixel] = {0, 0, 0, 0xff};
+ }
+ }
+ }
+
+ PixelFormat pixelFormat;
+ Dataspace dataspace;
+
+ getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
+
+ IMapper::BufferDescriptorInfo info;
+ info.width = mDisplayWidth;
+ info.height = mDisplayHeight;
+ info.layerCount = 1;
+ info.format = pixelFormat;
+ info.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
+
+ uint32_t stride;
+ const native_handle_t* buffer = mGralloc->allocate(info, /*import*/ true, &stride);
+ mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
+
+ render(layers);
+
+ int32_t fenceHandle;
+ mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle);
+
+ // lock buffer
+ // Create Rect accessRegion to specify reading the entire buffer
+ IMapper::Rect accessRegion;
+ accessRegion.left = 0;
+ accessRegion.top = 0;
+ accessRegion.width = info.width;
+ accessRegion.height = info.height;
+
+ void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fenceHandle);
+ checkReadbackBuffer(info, stride, bufData, expectedColors);
+ int unlockFence = mGralloc->unlock(buffer);
+
+ if (unlockFence != -1) {
+ close(unlockFence);
+ }
+
+ mWriter->validateDisplay();
+ mWriter->presentDisplay();
+ execute();
+}
+
+} // anonymous namespace
+} // namespace vts
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 23bf558..7834b94 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -18,11 +18,11 @@
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
-#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <composer-vts/2.1/GraphicsComposerCallback.h>
#include <composer-vts/2.1/TestCommandReader.h>
#include <composer-vts/2.2/ComposerVts.h>
-#include <mapper-vts/2.1/MapperVts.h>
+#include <mapper-vts/2.0/MapperVts.h>
namespace android {
namespace hardware {
@@ -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_0::IMapper;
+using mapper::V2_0::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);
@@ -75,14 +73,29 @@
// assume the first display is primary and is never removed
mPrimaryDisplay = waitForFirstDisplay();
+ Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
+ mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::WIDTH);
+ mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::HEIGHT);
+
// explicitly disable vsync
mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
mComposerCallback->setVsyncAllowed(false);
mComposerClient->getRaw()->getReadbackBufferAttributes(
- mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) {
+ mPrimaryDisplay,
+ [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
mHasReadbackBuffer = tmpError == Error::NONE;
+ if (mHasReadbackBuffer) {
+ mReadbackPixelFormat = tmpPixelFormat;
+ mReadbackDataspace = tmpDataspace;
+ ASSERT_LT(static_cast<PixelFormat>(0), mReadbackPixelFormat);
+ ASSERT_NE(Dataspace::UNKNOWN, mReadbackDataspace);
+ }
});
+
+ mInvalidDisplayId = GetInvalidDisplayId();
}
void TearDown() override {
@@ -93,16 +106,39 @@
}
}
+ // returns an invalid display id (one that has not been registered to a
+ // display. Currently assuming that a device will never have close to
+ // std::numeric_limit<uint64_t>::max() displays registered while running tests
+ Display GetInvalidDisplayId() {
+ std::vector<Display> validDisplays = mComposerCallback->getDisplays();
+ uint64_t id = std::numeric_limits<uint64_t>::max();
+ while (id > 0) {
+ if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) {
+ return id;
+ }
+ id--;
+ }
+
+ return 0;
+ }
+
// 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;
+ int32_t mDisplayWidth;
+ int32_t mDisplayHeight;
+
bool mHasReadbackBuffer;
+ uint64_t mInvalidDisplayId;
+ PixelFormat mReadbackPixelFormat;
+ Dataspace mReadbackDataspace;
+
private:
Display waitForFirstDisplay() {
while (true) {
@@ -125,27 +161,30 @@
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>();
}
- void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
+ void TearDown() override {
+ ASSERT_EQ(0, mReader->mErrors.size());
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
+ }
const native_handle_t* allocate() {
IMapper::BufferDescriptorInfo info{};
info.width = 64;
info.height = 64;
info.layerCount = 1;
- info.format = PixelFormat::RGBA_8888;
+ info.format = static_cast<common::V1_0::PixelFormat>(PixelFormat::RGBA_8888);
info.usage =
static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
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:
@@ -191,6 +230,16 @@
{IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
mWriter->setLayerPerFrameMetadata(hidlMetadata);
execute();
+
+ if (mReader->mErrors.size() == 1 &&
+ static_cast<Error>(mReader->mErrors[0].second) == Error::UNSUPPORTED) {
+ mReader->mErrors.clear();
+ GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer));
+ return;
+ }
+
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer));
}
/**
@@ -249,9 +298,35 @@
}
/**
+ * Test IComposerClient::getClientTargetSupport_2_2
+ *
+ * Test that IComposerClient::getClientTargetSupport_2_2 returns
+ * Error::BAD_DISPLAY when passed in an invalid display handle
+ */
+
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2BadDisplay) {
+ std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+ for (auto config : configs) {
+ int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::WIDTH);
+ int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+ IComposerClient::Attribute::HEIGHT);
+ ASSERT_LT(0, width);
+ ASSERT_LT(0, height);
+
+ mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+
+ Error error = mComposerClient->getRaw()->getClientTargetSupport_2_2(
+ mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN);
+
+ EXPECT_EQ(Error::BAD_DISPLAY, error);
+ }
+}
+
+/**
* Test IComposerClient::setPowerMode_2_2.
*/
-TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) {
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2) {
std::vector<IComposerClient::PowerMode> modes;
modes.push_back(IComposerClient::PowerMode::OFF);
modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
@@ -262,25 +337,118 @@
}
}
-TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) {
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 succeeds for different varations
+ * of PowerMode
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Variations) {
+ std::vector<IComposerClient::PowerMode> modes;
+
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ modes.push_back(IComposerClient::PowerMode::OFF);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::ON);
+ modes.push_back(IComposerClient::PowerMode::ON);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
+ modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+ }
+
+ if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::DOZE);
+ modes.push_back(IComposerClient::PowerMode::DOZE);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+ }
+
+ modes.clear();
+
+ modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+ modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+
+ for (auto mode : modes) {
+ ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+ }
+ }
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Tests that IComposerClient::setPowerMode_2_2 returns BAD_DISPLAY when passed an
+ * invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadDisplay) {
+ Error error = mComposerClient->getRaw()->setPowerMode_2_2(mInvalidDisplayId,
+ IComposerClient::PowerMode::ON);
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 returns BAD_PARAMETER when passed
+ * an invalid PowerMode
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadParameter) {
+ Error error = mComposerClient->getRaw()->setPowerMode_2_2(
+ mPrimaryDisplay, static_cast<IComposerClient::PowerMode>(-1));
+ ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 returns UNSUPPORTED when passed
+ * DOZE or DOZE_SUPPORT on a device that does not support these modes
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Unsupported) {
+ if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+ Error error = mComposerClient->getRaw()->setPowerMode_2_2(mPrimaryDisplay,
+ IComposerClient::PowerMode::DOZE);
+ EXPECT_EQ(Error::UNSUPPORTED, error);
+
+ error = mComposerClient->getRaw()->setPowerMode_2_2(
+ mPrimaryDisplay, IComposerClient::PowerMode::DOZE_SUSPEND);
+ EXPECT_EQ(Error::UNSUPPORTED, error);
+ }
+}
+
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test IComposerClient::setReadbackBuffer
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBuffer) {
if (!mHasReadbackBuffer) {
return;
}
- PixelFormat pixelFormat;
- Dataspace dataspace;
- mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
- ASSERT_LT(static_cast<PixelFormat>(0), pixelFormat);
- ASSERT_NE(Dataspace::UNKNOWN, dataspace);
-
IMapper::BufferDescriptorInfo info{};
- Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
- info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
- IComposerClient::Attribute::WIDTH);
- info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
- IComposerClient::Attribute::HEIGHT);
+ info.width = mDisplayWidth;
+ info.height = mDisplayHeight;
info.layerCount = 1;
- info.format = pixelFormat;
+ info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
// BufferUsage::COMPOSER_OUTPUT is missing
info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
@@ -292,7 +460,49 @@
mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
}
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) {
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test that IComposerClient::setReadbackBuffer returns an Error::BAD_DISPLAY
+ * when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) {
+ if (!mHasReadbackBuffer) {
+ return;
+ }
+
+ IMapper::BufferDescriptorInfo info{};
+ info.width = mDisplayWidth;
+ info.height = mDisplayHeight;
+ info.layerCount = 1;
+ info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
+ info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+
+ std::unique_ptr<Gralloc> gralloc;
+ const native_handle_t* buffer;
+ ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
+ ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+
+ Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr);
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test that IComposerClient::setReadbackBuffer returns Error::BAD_PARAMETER
+ * when passed an invalid buffer handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadParameter) {
+ if (!mHasReadbackBuffer) {
+ return;
+ }
+
+ Error error = mComposerClient->getRaw()->setReadbackBuffer(mPrimaryDisplay, nullptr, nullptr);
+ ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+TEST_F(GraphicsComposerHidlTest, GetReadbackBufferFenceInactive) {
if (!mHasReadbackBuffer) {
return;
}
@@ -313,14 +523,38 @@
mWriter->selectDisplay(mPrimaryDisplay);
mWriter->selectLayer(layer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0});
mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0});
+ execute();
+
+ if (mReader->mErrors.size() == 2 &&
+ static_cast<Error>(mReader->mErrors[0].second) == Error::UNSUPPORTED &&
+ static_cast<Error>(mReader->mErrors[1].second) == Error::UNSUPPORTED) {
+ mReader->mErrors.clear();
+ GTEST_SUCCEED() << "SetLayerFloatColor is not supported";
+ return;
+ }
+
+ // ensure setting float color on layer with composition type that is not
+ // SOLID_COLOR does not fail
+ V2_1::Layer clientLayer;
+ ASSERT_NO_FATAL_FAILURE(clientLayer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(clientLayer);
+ mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+ mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0});
+ execute();
+
+ // At this point we know that this function is supported so there should be
+ // no errors (checked upon TearDown)
}
/**
* Test IComposerClient::getDataspaceSaturationMatrix.
*/
-TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) {
+TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrix) {
auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR);
// the last row is known
ASSERT_EQ(0.0f, matrix[12]);
@@ -329,6 +563,19 @@
ASSERT_EQ(1.0f, matrix[15]);
}
+/*
+ * Test IComposerClient::getDataspaceSaturationMatrix
+ *
+ * Test that IComposerClient::getDataspaceSaturationMatrix returns
+ * Error::BAD_PARAMETER when passed a dataspace other than
+ * Dataspace::SRGB_LINEAR
+ */
+TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrixBadParameter) {
+ mComposerClient->getRaw()->getDataspaceSaturationMatrix(
+ Dataspace::UNKNOWN,
+ [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_PARAMETER, tmpError); });
+}
+
/**
* Test IComposerClient::getColorMode_2_2.
*/
@@ -339,10 +586,22 @@
EXPECT_NE(modes.cend(), nativeMode);
}
-/**
- * Test IComposerClient::getRenderIntent.
+/*
+ * Test IComposerClient::getColorMode_2_2
+ *
+ * Test that IComposerClient::getColorMode returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
*/
-TEST_F(GraphicsComposerHidlTest, GetRenderIntent) {
+TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2BadDisplay) {
+ mComposerClient->getRaw()->getColorModes_2_2(
+ mInvalidDisplayId,
+ [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); });
+}
+
+/**
+ * Test IComposerClient::getRenderIntents.
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntents) {
std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
for (auto mode : modes) {
std::vector<RenderIntent> intents =
@@ -366,6 +625,33 @@
}
}
+/*
+ * Test IComposerClient::getRenderIntents
+ *
+ * Test that IComposerClient::getRenderIntent returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadDisplay) {
+ std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+ for (auto mode : modes) {
+ mComposerClient->getRaw()->getRenderIntents(
+ mInvalidDisplayId, mode,
+ [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); });
+ }
+}
+
+/*
+ * Test IComposerClient::getRenderIntents
+ *
+ * Test that IComposerClient::getRenderIntents returns Error::BAD_PARAMETER when
+ * pased either an invalid Color mode or an invalid Render Intent
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadParameter) {
+ mComposerClient->getRaw()->getRenderIntents(
+ mPrimaryDisplay, static_cast<ColorMode>(-1),
+ [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); });
+}
+
/**
* Test IComposerClient::setColorMode_2_2.
*/
@@ -378,6 +664,37 @@
mComposerClient->setColorMode(mPrimaryDisplay, mode, intent);
}
}
+
+ mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_2
+ *
+ * Test that IComposerClient::setColorMode_2_2 returns an Error::BAD_DISPLAY
+ * when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadDisplay) {
+ Error error = mComposerClient->getRaw()->setColorMode_2_2(mInvalidDisplayId, ColorMode::NATIVE,
+ RenderIntent::COLORIMETRIC);
+
+ ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_2
+ *
+ * Test that IComposerClient::setColorMode_2_2 returns Error::BAD_PARAMETER when
+ * passed an invalid Color mode or an invalid render intent
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) {
+ Error colorModeError = mComposerClient->getRaw()->setColorMode_2_2(
+ mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
+ EXPECT_EQ(Error::BAD_PARAMETER, colorModeError);
+
+ Error renderIntentError = mComposerClient->getRaw()->setColorMode_2_2(
+ mPrimaryDisplay, ColorMode::NATIVE, static_cast<RenderIntent>(-1));
+ EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError);
}
} // namespace
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
new file mode 100644
index 0000000..78da099
--- /dev/null
+++ b/graphics/composer/2.3/Android.bp
@@ -0,0 +1,22 @@
+// 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.common@1.1",
+ "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..089438e
--- /dev/null
+++ b/graphics/composer/2.3/IComposerClient.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.graphics.composer@2.3;
+
+import android.hardware.graphics.composer@2.1::IComposerClient.Command;
+import @2.2::IComposerClient;
+import @2.1::Display;
+import @2.1::Error;
+
+interface IComposerClient extends @2.2::IComposerClient {
+
+ enum Command : @2.2::IComposerClient.Command {
+ /**
+ * SET_LAYER_COLOR_TRANSFORM has this pseudo prototype
+ *
+ * setLayerColorTransform(float[16] matrix);
+ *
+ * This command has the following binary layout in bytes:
+ *
+ * 0 - 16 * 4: matrix
+ *
+ * Sets a matrix for color transform which will be applied on this layer
+ * before composition.
+ *
+ * If the device is not capable of apply the matrix on this layer, it must force
+ * this layer to client composition during VALIDATE_DISPLAY.
+ *
+ * The matrix provided is an affine color transformation of the following
+ * form:
+ *
+ * |r.r r.g r.b 0|
+ * |g.r g.g g.b 0|
+ * |b.r b.g b.b 0|
+ * |Tr Tg Tb 1|
+ *
+ * This matrix must be provided in row-major form:
+ *
+ * {r.r, r.g, r.b, 0, g.r, ...}.
+ *
+ * Given a matrix of this form and an input color [R_in, G_in, B_in],
+ * the input color must first be converted to linear space
+ * [R_linear, G_linear, B_linear], then the output linear color
+ * [R_out_linear, G_out_linear, B_out_linear] will be:
+ *
+ * R_out_linear = R_linear * r.r + G_linear * g.r + B_linear * b.r + Tr
+ * G_out_linear = R_linear * r.g + G_linear * g.g + B_linear * b.g + Tg
+ * B_out_linear = R_linear * r.b + G_linear * g.b + B_linear * b.b + Tb
+ *
+ * [R_out_linear, G_out_linear, B_out_linear] must then be converted to
+ * gamma space: [R_out, G_out, B_out] before blending.
+ *
+ * @param matrix is a 4x4 transform matrix (16 floats) as described above.
+ */
+ SET_LAYER_COLOR_TRANSFORM = 0x40d << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+ };
+
+ /**
+ * 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);
+
+ /**
+ * Executes commands from the input command message queue. Return values
+ * generated by the input commands are written to the output command
+ * message queue in the form of value commands.
+ *
+ * @param inLength is the length of input commands.
+ * @param inHandles is an array of handles referenced by the input
+ * commands.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_PARAMETER when inLength is not equal to the length of
+ * commands in the input command message queue.
+ * NO_RESOURCES when the output command message queue was not
+ * properly drained.
+ * @param outQueueChanged indicates whether the output command message
+ * queue has changed.
+ * @param outLength is the length of output commands.
+ * @param outHandles is an array of handles referenced by the output
+ * commands.
+ */
+ executeCommands_2_3(uint32_t inLength,
+ vec<handle> inHandles)
+ generates (Error error,
+ bool outQueueChanged,
+ uint32_t outLength,
+ vec<handle> outHandles);
+};
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/command-buffer/Android.bp b/graphics/composer/2.3/utils/command-buffer/Android.bp
new file mode 100644
index 0000000..c48fe7a
--- /dev/null
+++ b/graphics/composer/2.3/utils/command-buffer/Android.bp
@@ -0,0 +1,15 @@
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.3-command-buffer",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
new file mode 100644
index 0000000..3f7b2c9
--- /dev/null
+++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+#warn "ComposerCommandBuffer.h included without LOG_TAG"
+#endif
+
+#undef LOG_NDEBUG
+#define LOG_NDEBUG 0
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+
+using android::hardware::MessageQueue;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::Layer;
+using android::hardware::graphics::composer::V2_3::IComposerClient;
+
+// This class helps build a command queue. Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandWriterBase : public V2_2::CommandWriterBase {
+ public:
+ CommandWriterBase(uint32_t initialMaxSize) : V2_2::CommandWriterBase(initialMaxSize) {}
+
+ static constexpr uint16_t kSetLayerColorTransformLength = 16;
+ void setLayerColorTransform(const float* matrix) {
+ beginCommand_2_3(IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM,
+ kSetLayerColorTransformLength);
+ for (int i = 0; i < 16; i++) {
+ writeFloat(matrix[i]);
+ }
+ endCommand();
+ }
+
+ protected:
+ void beginCommand_2_3(IComposerClient::Command command, uint16_t length) {
+ V2_2::CommandWriterBase::beginCommand_2_2(
+ static_cast<V2_2::IComposerClient::Command>(static_cast<int32_t>(command)), length);
+ }
+};
+
+// This class helps parse a command queue. Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandReaderBase : public V2_2::CommandReaderBase {
+ public:
+ CommandReaderBase() : V2_2::CommandReaderBase(){};
+};
+
+} // namespace V2_3
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
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..3ee9300
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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",
+ "android.hardware.graphics.composer@2.3-command-buffer",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.2-hal",
+ "android.hardware.graphics.composer@2.3-command-buffer",
+ ],
+ 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..c805472
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -0,0 +1,92 @@
+/*
+ * 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/ComposerCommandEngine.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();
+ }
+
+ Return<void> executeCommands_2_3(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+ IComposerClient::executeCommands_2_2_cb hidl_cb) override {
+ std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+ bool outChanged = false;
+ uint32_t outLength = 0;
+ hidl_vec<hidl_handle> outHandles;
+ Error error =
+ mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+ hidl_cb(error, outChanged, outLength, outHandles);
+
+ mCommandEngine->reset();
+
+ 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::mCommandEngine;
+ using BaseType2_1::mCommandEngineMutex;
+ 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/ComposerCommandEngine.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h
new file mode 100644
index 0000000..c3dcbcd
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h
@@ -0,0 +1,81 @@
+/*
+ * 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 "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerResources.h>
+#include <composer-hal/2.3/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_2::hal::ComposerCommandEngine {
+ public:
+ ComposerCommandEngine(ComposerHal* hal, V2_2::hal::ComposerResources* resources)
+ : BaseType2_2(hal, resources), mHal(hal) {}
+
+ protected:
+ bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+ switch (static_cast<IComposerClient::Command>(command)) {
+ case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM:
+ return executeSetLayerColorTransform(length);
+ default:
+ return BaseType2_2::executeCommand(command, length);
+ }
+ }
+
+ bool executeSetLayerColorTransform(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerColorTransformLength) {
+ return false;
+ }
+
+ float matrix[16];
+ for (int i = 0; i < 16; i++) {
+ matrix[i] = readFloat();
+ }
+ auto err = mHal->setLayerColorTransform(mCurrentDisplay, mCurrentLayer, matrix);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ private:
+ using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+ using BaseType2_1::mWriter;
+ using BaseType2_2 = V2_2::hal::ComposerCommandEngine;
+
+ ComposerHal* mHal;
+};
+
+} // 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..0f6205a
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -0,0 +1,44 @@
+/*
+ * 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;
+using V2_1::Layer;
+
+class ComposerHal : public V2_2::hal::ComposerHal {
+ public:
+ virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) = 0;
+ virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 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..ed1878b
--- /dev/null
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -0,0 +1,110 @@
+/*
+ * 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;
+ }
+
+ Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override {
+ if (!mDispatch.setLayerColorTransform) {
+ return Error::UNSUPPORTED;
+ }
+ int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix);
+ return static_cast<Error>(err);
+ }
+
+ protected:
+ bool initDispatch() override {
+ if (!BaseType2_2::initDispatch()) {
+ return false;
+ }
+
+ this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
+ &mDispatch.getDisplayIdentificationData);
+ this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
+ &mDispatch.setLayerColorTransform);
+ return true;
+ }
+
+ private:
+ struct {
+ HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
+ HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
+ } 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..19438cb
--- /dev/null
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -0,0 +1,42 @@
+//
+// 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",
+ "android.hardware.graphics.composer@2.3-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..7548cb5
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/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_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",
+ "android.hardware.graphics.composer@2.3-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..1030ddc
--- /dev/null
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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-command-buffer/2.3/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.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);
+
+ mWriter = std::make_unique<CommandWriterBase>(1024);
+ mReader = std::make_unique<V2_1::vts::TestCommandReader>();
+ }
+
+ void TearDown() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
+ }
+
+ void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+
+ // use the slot count usually set by SF
+ static constexpr uint32_t kBufferSlotCount = 64;
+
+ 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;
+ std::unique_ptr<CommandWriterBase> mWriter;
+ std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
+
+ 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";
+ }
+}
+
+/**
+ * Test IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM.
+ * TODO Add color to the layer, use matrix to keep only red component,
+ * and check.
+ */
+TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) {
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+
+ // clang-format off
+ const std::array<float, 16> matrix = {{
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f,
+ }};
+ // clang-format on
+
+ mWriter->setLayerColorTransform(matrix.data());
+ execute();
+}
+
+} // 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/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index aa9beff..5ec0af2 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -16,6 +16,10 @@
#define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest"
+#include <chrono>
+#include <thread>
+#include <vector>
+
#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <mapper-vts/2.0/MapperVts.h>
@@ -125,6 +129,36 @@
}
/**
+ * Test that IAllocator::allocate is thread-safe.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateThreaded) {
+ BufferDescriptor descriptor;
+ ASSERT_NO_FATAL_FAILURE(descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+
+ std::atomic<bool> timeUp(false);
+ std::atomic<uint64_t> allocationCount(0);
+ auto threadLoop = [&]() {
+ while (!timeUp) {
+ mGralloc->getAllocator()->allocate(
+ descriptor, 1, [&](const auto&, const auto&, const auto&) { allocationCount++; });
+ }
+ };
+
+ std::vector<std::thread> threads;
+ for (int i = 0; i < 8; i++) {
+ threads.push_back(std::thread(threadLoop));
+ }
+
+ std::this_thread::sleep_for(std::chrono::seconds(3));
+ timeUp = true;
+ LOG(VERBOSE) << "Made " << allocationCount << " threaded allocations";
+
+ for (auto& thread : threads) {
+ thread.join();
+ }
+}
+
+/**
* Test IMapper::createDescriptor with valid descriptor info.
*/
TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
new file mode 100644
index 0000000..405990e
--- /dev/null
+++ b/media/bufferpool/2.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.media.bufferpool@2.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IAccessor.hal",
+ "IClientManager.hal",
+ "IConnection.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "Buffer",
+ "BufferStatus",
+ "BufferStatusMessage",
+ "ResultStatus",
+ ],
+ gen_java: false,
+}
+
diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal
new file mode 100644
index 0000000..ab7c02d
--- /dev/null
+++ b/media/bufferpool/2.0/IAccessor.hal
@@ -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.
+ */
+
+package android.hardware.media.bufferpool@2.0;
+
+import IConnection;
+/**
+ * IAccessor creates IConnection which is used from IClientManager in order to
+ * use functionality of the specified buffer pool.
+ */
+interface IAccessor {
+
+ /**
+ * Registers a new client and creates IConnection to the buffer pool for
+ * the client. IConnection and FMQ are used by IClientManager in order to
+ * communicate with the buffer pool. Via FMQ IClientManager sends
+ * BufferStatusMesage(s) to the buffer pool.
+ *
+ * FMQ is used to send buffer ownership status changes to a buffer pool
+ * from a buffer pool client. A buffer pool synchronizes FMQ messages when
+ * there is a hidl request from the clients. Every client has its own
+ * connection and FMQ to communicate with the buffer pool. So sending an
+ * FMQ message on behalf of other clients is not possible.
+ *
+ * FMQ messages are sent when a buffer is acquired or released. Also, FMQ
+ * messages are sent when a buffer is transferred from a client to another
+ * client. FMQ has its own ID from a buffer pool. A client is specified
+ * with the ID.
+ *
+ * To transfer a buffer, a sender must send an FMQ message. The message
+ * must include a receiver's ID and a transaction ID. A receiver must send
+ * the transaction ID to fetch a buffer from a buffer pool. Since the
+ * sender already registered the receiver via an FMQ message, The buffer
+ * pool must verify the receiver with the transaction ID. In order to
+ * prevent faking a receiver, a connection to a buffer pool from client is
+ * made and kept private. Also part of transaction ID is a sender ID in
+ * order to prevent fake transactions from other clients. This must be
+ * verified with an FMQ message from a buffer pool.
+ *
+ * @return status The status of the call.
+ * OK - A connection is made successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * ALREADY_EXISTS - A connection was already made.
+ * CRITICAL_ERROR - Other errors.
+ * @return connection The IConnection have interfaces
+ * to get shared buffers from the buffer pool.
+ * @return connectionId Id of IConnection. The Id identifies
+ * sender and receiver in FMQ messages during buffer transfer.
+ * @return toFmqDesc FMQ descriptor. The descriptor is used to
+ * post buffer status messages.
+ * @return fromFmqDesc FMQ descriptor. The descriptor is used to
+ * receive buffer invalidation messages from the buffer pool.
+ */
+ connect()
+ generates (ResultStatus status, IConnection connection,
+ int64_t connectionId,
+ fmq_sync<BufferStatusMessage> toFmqDesc,
+ fmq_unsync<BufferInvalidationMessage> fromFmqDesc);
+};
diff --git a/media/bufferpool/2.0/IClientManager.hal b/media/bufferpool/2.0/IClientManager.hal
new file mode 100644
index 0000000..9253bda
--- /dev/null
+++ b/media/bufferpool/2.0/IClientManager.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.media.bufferpool@2.0;
+
+import IAccessor;
+
+/**
+ * IClientManager manages IConnection(s) inside a process. A locally
+ * created IConnection represents a communication node(receiver) with the
+ * specified buffer pool(IAccessor).
+ * IConnection(s) are not exposed to other processes(IClientManager).
+ * IClientManager instance must be unique within a process.
+ */
+interface IClientManager {
+
+ /**
+ * Sets up a buffer receiving communication node for the specified
+ * buffer pool. A manager must create a IConnection to the buffer
+ * pool if it does not already have a connection.
+ *
+ * @param bufferPool a buffer pool which is specified with the IAccessor.
+ * The specified buffer pool is the owner of received buffers.
+ * @return status The status of the call.
+ * OK - A sender was set successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * ALREADY_EXISTS - A sender was registered already.
+ * CRITICAL_ERROR - Other errors.
+ * @return connectionId the Id of the communication node to the buffer pool.
+ * This id is used in FMQ to notify IAccessor that a buffer has been
+ * sent to that connection during transfers.
+ */
+ registerSender(IAccessor bufferPool) generates
+ (ResultStatus status, int64_t connectionId);
+};
diff --git a/media/bufferpool/2.0/IConnection.hal b/media/bufferpool/2.0/IConnection.hal
new file mode 100644
index 0000000..629f83c
--- /dev/null
+++ b/media/bufferpool/2.0/IConnection.hal
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool@2.0;
+
+/**
+ * A connection to a buffer pool which handles requests from a buffer pool
+ * client. The connection must be made in order to receive buffers from
+ * other buffer pool clients.
+ */
+interface IConnection {
+
+ /**
+ * Retrieves a buffer using bufferId. The method must be called from
+ * receiving side of buffer during transferring only when the specified
+ * buffer is neither cached nor used. This fails if the specified
+ * transaction is not valid.
+ *
+ * @param transactionId Unique transaction id for buffer transferring.
+ * @param bufferId Id of the buffer to be fetched.
+ * @return status The status of the call.
+ * OK - A buffer was fetched successfully.
+ * NO_MEMORY - Memory allocation failure occurred.
+ * NOT_FOUND - A buffer was not found due to invalidation.
+ * CRITICAL_ERROR - Other errors.
+ * @return buffer The actual buffer which is specified with bufferId.
+ */
+ fetch(uint64_t transactionId, uint32_t bufferId) generates
+ (ResultStatus status, Buffer buffer);
+};
diff --git a/media/bufferpool/2.0/README.md b/media/bufferpool/2.0/README.md
new file mode 100644
index 0000000..ed985d8
--- /dev/null
+++ b/media/bufferpool/2.0/README.md
@@ -0,0 +1,54 @@
+1. Overview
+
+A buffer pool enables processes to transfer buffers asynchronously.
+Without a buffer pool, a process calls a synchronous method of the other
+process and waits until the call finishes transferring a buffer. This adds
+unwanted latency due to context switching. With help from a buffer pool, a
+process can pass buffers asynchronously and reduce context switching latency.
+
+Passing an interface and a handle adds extra latency also. To mitigate the
+latency, passing IDs with local cache is used. For security concerns about
+rogue clients, FMQ is used to communicate between a buffer pool and a client
+process. FMQ is used to send buffer ownership change status from a client
+process to a buffer pool. Except FMQ, a buffer pool does not use any shared
+memory.
+
+2. FMQ
+
+FMQ is used to send buffer ownership status changes to a buffer pool from a
+buffer pool client. A buffer pool synchronizes FMQ messages when there is a
+hidl request from the clients. Every client has its own connection and FMQ
+to communicate with the buffer pool. So sending an FMQ message on behalf of
+other clients is not possible.
+
+FMQ messages are sent when a buffer is acquired or released. Also, FMQ messages
+are sent when a buffer is transferred from a client to another client. FMQ has
+its own ID from a buffer pool. A client is specified with the ID.
+
+To transfer a buffer, a sender must send an FMQ message. The message must
+include a receiver's ID and a transaction ID. A receiver must send the
+transaction ID to fetch a buffer from a buffer pool. Since the sender already
+registered the receiver via an FMQ message, The buffer pool must verify the
+receiver with the transaction ID. In order to prevent faking a receiver, a
+connection to a buffer pool from client is made and kept privately. Also part of
+transaction ID is a sender ID in order to prevent fake transactions from other
+clients. This must be verified with an FMQ message from a buffer pool.
+
+FMQ messages are defined in BufferStatus and BufferStatusMessage of 'types.hal'.
+
+3. Interfaces
+
+IConnection
+A connection to a buffer pool from a buffer pool client. The connection
+provides the functionalities to share buffers between buffer pool clients.
+The connection must be unique for each client.
+
+IAccessor
+An accessor to a buffer pool which makes a connection to the buffer pool.
+IAccesssor#connect creates an IConnection.
+
+IClientManager
+A manager of buffer pool clients and clients' connections to buffer pools. It
+sets up a process to be a receiver of buffers from a buffer pool. The manager
+is unique in a process.
+
diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal
new file mode 100644
index 0000000..456e4aa
--- /dev/null
+++ b/media/bufferpool/2.0/types.hal
@@ -0,0 +1,109 @@
+/*
+ * 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.media.bufferpool@2.0;
+
+enum ResultStatus : int32_t {
+ OK = 0,
+
+ NO_MEMORY = 1,
+ ALREADY_EXISTS = 2,
+ NOT_FOUND = 3,
+ CRITICAL_ERROR = 4,
+};
+
+/**
+ * Generic buffer for fast recycling for media/stagefright.
+ *
+ * During media pipeline buffer references are created, shared and
+ * destroyed frequently. The underlying buffers are allocated on demand
+ * by a buffer pool, and are recycled to the buffer pool when they are
+ * no longer referenced by the clients.
+ *
+ * E.g. ion or gralloc buffer
+ */
+struct Buffer {
+ uint32_t id;
+ handle buffer;
+};
+
+/**
+ * Buffer ownership status for the specified client.
+ * Buffer transfer status for the specified buffer transafer transaction.
+ * BufferStatus is posted along with BufferStatusMessage from a client to
+ * the buffer pool for synchronization after status change.
+ */
+enum BufferStatus : int32_t {
+ /** No longer used by the specified client. */
+ NOT_USED = 0,
+ /** Buffer is acquired by the specified client. */
+ USED = 1,
+ /** Buffer is sent by the specified client. */
+ TRANSFER_TO = 2,
+ /** Buffer transfer is acked by the receiver client. */
+ TRANSFER_FROM = 3,
+ /** Buffer transfer is timed out by receiver client. */
+ TRANSFER_TIMEOUT = 4,
+ /** Buffer transfer is not acked by the receiver. */
+ TRANSFER_LOST = 5,
+ /** Buffer fetch request from the client. */
+ TRANSFER_FETCH = 6,
+ /** Buffer transaction succeeded. */
+ TRANSFER_OK = 7,
+ /** Buffer transaction failure. */
+ TRANSFER_ERROR = 8,
+};
+
+/**
+ * Buffer ownership status change message. This message is
+ * sent via fmq to the buffer pool from client processes.
+ */
+struct BufferStatusMessage {
+ /**
+ * Transaction Id = (SenderId : sender local transaction Id)
+ * Transaction Id is created from sender and posted via fmq within
+ * TRANSFER_TO message.
+ */
+ uint64_t transactionId;
+ uint32_t bufferId;
+ BufferStatus newStatus;
+ /** Used by the buffer pool. not by client. */
+ int64_t connectionId;
+ /** Valid only when TRANSFER_TO is posted. */
+ int64_t targetConnectionId;
+ /**
+ * Used by the buffer pool, not by client.
+ * Monotonic timestamp in Us since fixed point in time as decided
+ * by the sender of the message
+ */
+ int64_t timestampUs;
+};
+
+/*
+ * Buffer pool sends a buffer invalidation message to clients in order to
+ * ensure fast reclamation of the buffers. Clients must free the invalidated
+ * buffers as soon as possible upon receiving the message.
+ */
+struct BufferInvalidationMessage {
+ /**
+ * Buffers from fromBufferId to toBufferId must be invalidated.
+ * fromBufferId is inclusive, but toBufferId is not inclusive.
+ * If fromBufferId > toBufferID, wrap happens. In that case
+ * the wrap is based on UINT32_MAX.
+ */
+ uint32_t fromBufferId;
+ uint32_t toBufferId;
+};
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/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 61970f0..4377131 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -26,7 +26,56 @@
* The type of an operation in a model.
*/
enum OperationType : @1.1::OperationType {
-
+ // TODO(b/116445845): Sync docs when all ops are implemented.
+ ARGMAX = 38,
+ ARGMIN = 39,
+ PAD_V2 = 40,
+ BBOX_TRANSFORM = 41,
+ BIDIRECTIONAL_SEQUENCE_LSTM = 42,
+ BIDIRECTIONAL_SEQUENCE_RNN = 43,
+ BOX_WITH_NMS_LIMIT = 44,
+ CAST = 45,
+ CHANNEL_SHUFFLE = 46,
+ DETECTION_OUTPUT = 47,
+ EMBEDDING_LOOKUP_SPARSE = 48,
+ EXP = 49,
+ EXPAND_DIMS = 50,
+ GATHER = 51,
+ GENERATE_PROPOSALS = 52,
+ GREATER = 53,
+ GREATER_EQUAL = 54,
+ GROUPED_CONV_2D = 55,
+ HEATMAP_MAX_KEYPOINT = 56,
+ LESS = 57,
+ LESS_EQUAL = 58,
+ LOG = 59,
+ LOGICAL_AND = 60,
+ LOGICAL_NOT = 61,
+ LOGICAL_OR = 62,
+ LOG_SOFTMAX = 63,
+ MAXIMUM = 64,
+ MINIMUM = 65,
+ NEG = 66,
+ POW = 67,
+ PRELU = 68,
+ PRIOR_BOX = 69,
+ QUANTIZE = 70,
+ QUANTIZED_16BIT_LSTM = 71,
+ RANDOM_MULTINOMIAL = 72,
+ REDUCE = 73,
+ ROI_ALIGN = 74,
+ RSQRT = 75,
+ SELECT = 76,
+ SIN = 77,
+ SLICE = 78,
+ SPARSE_TO_DENSE = 79,
+ SPLIT = 80,
+ SQRT = 81,
+ TILE = 82,
+ TOPK_V2 = 83,
+ TRANSPOSE_CONV_2D = 84,
+ UNIDIRECTIONAL_SEQUENCE_LSTM = 85,
+ UNIDIRECTIONAL_SEQUENCE_RNN = 86,
};
/**
diff --git a/sensors/1.0/default/OWNERS b/sensors/1.0/default/OWNERS
index 6a38a1f..2031d84 100644
--- a/sensors/1.0/default/OWNERS
+++ b/sensors/1.0/default/OWNERS
@@ -1,2 +1,2 @@
-ashutoshj@google.com
-pengxu@google.com
+bduddie@google.com
+bstack@google.com
diff --git a/sensors/1.0/vts/functional/OWNERS b/sensors/1.0/vts/functional/OWNERS
index 8715e5d..759d87b 100644
--- a/sensors/1.0/vts/functional/OWNERS
+++ b/sensors/1.0/vts/functional/OWNERS
@@ -1,6 +1,6 @@
# Sensors team
-ashutoshj@google.com
-pengxu@google.com
+bduddie@google.com
+bstack@google.com
# VTS team
trong@google.com
diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp
new file mode 100644
index 0000000..3b948a9
--- /dev/null
+++ b/sensors/2.0/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.sensors@2.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "ISensors.hal",
+ "ISensorsCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.sensors@1.0",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "EventQueueFlagBits",
+ "SensorTimeout",
+ ],
+ gen_java: false,
+}
+
diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal
new file mode 100644
index 0000000..939bf73
--- /dev/null
+++ b/sensors/2.0/ISensors.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.sensors@2.0;
+
+import @1.0::Event;
+import @1.0::OperationMode;
+import @1.0::RateLevel;
+import @1.0::Result;
+import @1.0::SensorInfo;
+import @1.0::SharedMemInfo;
+import @2.0::ISensorsCallback;
+
+interface ISensors {
+ /**
+ * Enumerate all available (static) sensors.
+ *
+ * The SensorInfo for each sensor returned by getSensorsList must be stable
+ * from the initial call to getSensorsList after a device boot until the
+ * entire system restarts. The SensorInfo for each sensor must not change
+ * between subsequent calls to getSensorsList, even across restarts of the
+ * HAL and its dependencies (for example, the sensor handle for a given
+ * sensor must not change across HAL restarts).
+ */
+ getSensorsList() generates (vec<SensorInfo> list);
+
+ /**
+ * Place the module in a specific mode. The following modes are defined
+ *
+ * SENSOR_HAL_NORMAL_MODE - Normal operation. Default state of the module.
+ *
+ * SENSOR_HAL_DATA_INJECTION_MODE - Loopback mode.
+ * Data is injected for the supported sensors by the sensor service in
+ * this mode.
+ *
+ * @return OK on success
+ * BAD_VALUE if requested mode is not supported
+ * PERMISSION_DENIED if operation is not allowed
+ */
+ setOperationMode(OperationMode mode) generates (Result result);
+
+ /**
+ * Activate/de-activate one sensor.
+ *
+ * After sensor de-activation, existing sensor events that have not
+ * been written to the event queue must be abandoned immediately so that
+ * subsequent activations do not get stale sensor events (events
+ * that are generated prior to the latter activation).
+ *
+ * @param sensorHandle is the handle of the sensor to change.
+ * @param enabled set to true to enable, or false to disable the sensor.
+ * @return result OK on success, BAD_VALUE if sensorHandle is invalid.
+ */
+ activate(int32_t sensorHandle, bool enabled) generates (Result result);
+
+ /**
+ * Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback.
+ *
+ * The Fast Message Queues (FMQ) that are used to send data between the
+ * framework and the HAL. The callback is used by the HAL to notify the
+ * framework of asynchronous events, such as a dynamic sensor connection.
+ *
+ * The Event FMQ is used to transport sensor events from the HAL to the
+ * framework. The Event FMQ is created using the eventQueueDescriptor.
+ * Data may only be written to the Event FMQ. Data must not be read from
+ * the Event FMQ since the framework is the only reader. Upon receiving
+ * sensor events, the HAL should write the sensor events to the Event FMQ.
+ * Once the HAL is finished writing sensor events to the Event FMQ, the HAL
+ * must call the Event FMQ's EventFlag wake() function with the
+ * EventQueueFlagBits::READ_AND_PROCESS mask which notifies the framework
+ * that sensor events are available to be read and processed.
+ *
+ * The Wake Lock FMQ is used by the framework to notify the HAL when it is
+ * safe to release its wake_lock. When the framework receives WAKE_UP events
+ * from the Event FMQ and the framework has acquired a wake_lock, the
+ * framework must write a WakeLockEvent to the Wake Lock FMQ with the number
+ * of WAKE_UP events processed. When the HAL reads the WakeLockEvent from
+ * the Wake Lock FMQ, the HAL should decrement its current count of
+ * unprocessed WAKE_UP events and release its wake_lock if the current
+ * count of unprocessed WAKE_UP events is zero.
+ *
+ * The ISensorsCallback is used by the HAL to notify the framework of
+ * asynchronous events, such as a dynamic sensor connection.
+ *
+ * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events
+ * must begin with "SensorsHAL_WAKEUP".
+ *
+ * If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP
+ * event was written to the Event FMQ without receiving a message on the
+ * Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be
+ * released.
+ *
+ * If either the Event FMQ or the Wake Lock FMQ is already initialized when
+ * initialize is invoked, then both existing FMQs must be discarded and the
+ * new descriptors must be used to create new FMQs within the HAL. The
+ * number of outstanding WAKE_UP events should also be reset to zero, and
+ * any outstanding wake_locks held as a result of WAKE_UP events should be
+ * released.
+ *
+ * initialize must be thread safe and prevent concurrent calls
+ * to initialize from simultaneously modifying state.
+ *
+ * @param eventQueueDescriptor Fast Message Queue descriptor that is used to
+ * create the Event FMQ which is where sensor events are written. The
+ * descriptor is obtained from the framework's FMQ that is used to read
+ * sensor events.
+ * @param wakeLockDescriptor Fast Message Queue descriptor that is used to
+ * create the Wake Lock FMQ which is where wake_lock events are read
+ * from. The descriptor is obtained from the framework's FMQ that is
+ * used to write wake_lock events.
+ * @param sensorsCallback sensors callback that receives asynchronous data
+ * from the Sensors HAL.
+ * @return result OK on success; BAD_VALUE if descriptor is invalid (such
+ * as null)
+ */
+ @entry
+ @callflow(next = {"getSensorsList"})
+ initialize(fmq_sync<Event> eventQueueDescriptor,
+ fmq_sync<uint32_t> wakeLockDescriptor,
+ ISensorsCallback sensorsCallback)
+ generates
+ (Result result);
+
+ /**
+ * Sets a sensor’s parameters, including sampling frequency and maximum
+ * report latency. This function can be called while the sensor is
+ * activated, in which case it must not cause any sensor measurements to
+ * be lost: transitioning from one sampling rate to the other cannot cause
+ * lost events, nor can transitioning from a high maximum report latency to
+ * a low maximum report latency.
+ *
+ * @param sensorHandle handle of sensor to be changed.
+ * @param samplingPeriodNs specifies sensor sample period in nanoseconds.
+ * @param maxReportLatencyNs allowed delay time before an event is sampled
+ * to time of report.
+ * @return result OK on success, BAD_VALUE if any parameters are invalid.
+ */
+ batch(int32_t sensorHandle,
+ int64_t samplingPeriodNs,
+ int64_t maxReportLatencyNs)
+ generates (
+ Result result);
+
+ /**
+ * Trigger a flush of internal FIFO.
+ *
+ * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode"
+ * FIFO for the specified sensor and flushes the FIFO. If the FIFO is empty
+ * or if the sensor doesn't support batching (FIFO size zero), return
+ * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream.
+ * This applies to all sensors other than one-shot sensors. If the sensor
+ * is a one-shot sensor, flush must return BAD_VALUE and not generate any
+ * flush complete metadata. If the sensor is not active at the time flush()
+ * is called, flush() return BAD_VALUE.
+ *
+ * @param sensorHandle handle of sensor to be flushed.
+ * @return result OK on success and BAD_VALUE if sensorHandle is invalid.
+ */
+ flush(int32_t sensorHandle) generates (Result result);
+
+ /**
+ * Inject a single sensor event or push operation environment parameters to
+ * device.
+ *
+ * When device is in NORMAL mode, this function is called to push operation
+ * environment data to device. In this operation, Event is always of
+ * SensorType::AdditionalInfo type. See operation evironment parameters
+ * section in AdditionalInfoType.
+ *
+ * When device is in DATA_INJECTION mode, this function is also used for
+ * injecting sensor events.
+ *
+ * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO
+ * type events should not be routed back to the sensor event queue.
+ *
+ * @see AdditionalInfoType
+ * @see OperationMode
+ * @param event sensor event to be injected
+ * @return result OK on success; PERMISSION_DENIED if operation is not
+ * allowed; INVALID_OPERATION, if this functionality is unsupported;
+ * BAD_VALUE if sensor event cannot be injected.
+ */
+ injectSensorData(Event event) generates (Result result);
+
+ /**
+ * Register direct report channel.
+ *
+ * Register a direct channel with supplied shared memory information. Upon
+ * return, the sensor hardware is responsible for resetting the memory
+ * content to initial value (depending on memory format settings).
+ *
+ * @param mem shared memory info data structure.
+ * @return result OK on success; BAD_VALUE if shared memory information is
+ * not consistent; NO_MEMORY if shared memory cannot be used by sensor
+ * system; INVALID_OPERATION if functionality is not supported.
+ * @return channelHandle a positive integer used for referencing registered
+ * direct channel (>0) in configureDirectReport and
+ * unregisterDirectChannel if result is OK, -1 otherwise.
+ */
+ registerDirectChannel(SharedMemInfo mem)
+ generates (Result result,
+ int32_t channelHandle);
+
+ /**
+ * Unregister direct report channel.
+ *
+ * Unregister a direct channel previously registered using
+ * registerDirectChannel, and remove all active sensor report configured in
+ * still active sensor report configured in the direct channel.
+ *
+ * @param channelHandle handle of direct channel to be unregistered.
+ * @return result OK if direct report is supported; INVALID_OPERATION
+ * otherwise.
+ */
+ unregisterDirectChannel(int32_t channelHandle) generates (Result result);
+
+ /**
+ * Configure direct sensor event report in direct channel.
+ *
+ * This function start, modify rate or stop direct report of a sensor in a
+ * certain direct channel.
+ *
+ * @param sensorHandle handle of sensor to be configured. When combined
+ * with STOP rate, sensorHandle can be -1 to denote all active sensors
+ * in the direct channel specified by channel Handle.
+ * @param channelHandle handle of direct channel to be configured.
+ * @param rate rate level, see RateLevel enum.
+ * @return result OK on success; BAD_VALUE if parameter is invalid (such as
+ * rate level is not supported by sensor, channelHandle does not exist,
+ * etc); INVALID_OPERATION if functionality is not supported.
+ * @return reportToken positive integer to identify multiple sensors of
+ * the same type in a single direct channel. Ignored if rate is STOP.
+ * See SharedMemFormat.
+ */
+ configDirectReport(
+ int32_t sensorHandle,
+ int32_t channelHandle,
+ RateLevel rate
+ ) generates (
+ Result result,
+ int32_t reportToken);
+};
diff --git a/sensors/2.0/ISensorsCallback.hal b/sensors/2.0/ISensorsCallback.hal
new file mode 100644
index 0000000..e0bd98f
--- /dev/null
+++ b/sensors/2.0/ISensorsCallback.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.sensors@2.0;
+
+import @1.0::SensorInfo;
+
+interface ISensorsCallback {
+ /**
+ * Notify the framework that new dynamic sensors have been connected.
+ *
+ * If a dynamic sensor was previously connected and has not been
+ * disconnected, then that sensor must not be included in sensorInfos.
+ *
+ * @param sensorInfos vector of SensorInfo for each dynamic sensor that
+ * was connected.
+ */
+ oneway onDynamicSensorsConnected(vec<SensorInfo> sensorInfos);
+
+ /**
+ * Notify the framework that previously connected dynamic sensors have been
+ * disconnected.
+ *
+ * If a dynamic sensor was previously disconnected and has not been
+ * reconnected, then that sensor must not be included in sensorHandles.
+ *
+ * The HAL must ensure that all sensor events from departing dynamic
+ * sensors have been written to the Event FMQ before calling
+ * onDynamicSensorsDisconnected.
+ *
+ * @param sensorHandles vector of sensor handles for each dynamic sensors
+ * that was disconnected.
+ */
+ oneway onDynamicSensorsDisconnected(vec<int32_t> sensorHandles);
+};
diff --git a/sensors/2.0/types.hal b/sensors/2.0/types.hal
new file mode 100644
index 0000000..e1a029a
--- /dev/null
+++ b/sensors/2.0/types.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.sensors@2.0;
+
+enum SensorTimeout : int32_t {
+ /**
+ * The maximum number of seconds to wait for a message on the Wake Lock FMQ
+ * before automatically releasing any wake_lock held for a WAKE_UP event.
+ */
+ WAKE_LOCK_SECONDS = 1,
+};
+
+enum EventQueueFlagBits : uint32_t {
+ /**
+ * Used to notify the Event FMQ that events should be read and processed.
+ */
+ READ_AND_PROCESS = 1 << 0,
+};
diff --git a/wifi/1.2/default/OWNERS b/wifi/1.0/vts/OWNERS
similarity index 100%
copy from wifi/1.2/default/OWNERS
copy to wifi/1.0/vts/OWNERS
diff --git a/wifi/1.2/default/OWNERS b/wifi/1.1/vts/OWNERS
similarity index 100%
copy from wifi/1.2/default/OWNERS
copy to wifi/1.1/vts/OWNERS
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/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp
deleted file mode 100644
index 1d6e9e4..0000000
--- a/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp
+++ /dev/null
@@ -1,129 +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.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN
-#include "hidl_struct_util.h"
-
-using testing::Test;
-
-namespace {
-constexpr uint32_t kMacId1 = 1;
-constexpr uint32_t kMacId2 = 2;
-constexpr uint32_t kIfaceChannel1 = 3;
-constexpr uint32_t kIfaceChannel2 = 5;
-constexpr char kIfaceName1[] = "wlan0";
-constexpr char kIfaceName2[] = "wlan1";
-} // namespace
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_2 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-class HidlStructUtilTest : public Test {};
-
-TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) {
- std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
- legacy_hal::WifiMacInfo legacy_mac_info1 = {
- .wlan_mac_id = kMacId1,
- .mac_band =
- legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
- .channel = kIfaceChannel1};
- legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
- .channel = kIfaceChannel2};
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
- legacy_mac_infos.push_back(legacy_mac_info1);
-
- std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
- ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
- legacy_mac_infos, &hidl_radio_mode_infos));
-
- ASSERT_EQ(1u, hidl_radio_mode_infos.size());
- auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
- EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId);
- EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
- ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
- auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
- hidl_iface_info1.channel);
- auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1];
- EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
- hidl_iface_info2.channel);
-}
-
-TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) {
- std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
- legacy_hal::WifiMacInfo legacy_mac_info1 = {
- .wlan_mac_id = kMacId1, .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
- .channel = kIfaceChannel1};
- legacy_hal::WifiMacInfo legacy_mac_info2 = {
- .wlan_mac_id = kMacId2, .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
- .channel = kIfaceChannel2};
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
- legacy_mac_infos.push_back(legacy_mac_info1);
- legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
- legacy_mac_infos.push_back(legacy_mac_info2);
-
- std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
- ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
- legacy_mac_infos, &hidl_radio_mode_infos));
-
- ASSERT_EQ(2u, hidl_radio_mode_infos.size());
-
- // Find mac info 1.
- const auto hidl_radio_mode_info1 = std::find_if(
- hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
- [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) {
- return x.radioId == legacy_mac_info1.wlan_mac_id;
- });
- ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
- EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
- ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
- auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
- hidl_iface_info1.channel);
-
- // Find mac info 2.
- const auto hidl_radio_mode_info2 = std::find_if(
- hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
- [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) {
- return x.radioId == legacy_mac_info2.wlan_mac_id;
- });
- ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
- EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
- ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
- auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
- hidl_iface_info2.channel);
-}
-} // namespace implementation
-} // namespace V1_2
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh
deleted file mode 100755
index 966a6a7..0000000
--- a/wifi/1.2/default/tests/runtests.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-if [ -z $ANDROID_BUILD_TOP ]; then
- echo "You need to source and lunch before you can use this script"
- exit 1
-fi
-
-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
-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 shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
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
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
new file mode 100644
index 0000000..5e87c1c
--- /dev/null
+++ b/wifi/1.3/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.wifi@1.3",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IWifi.hal",
+ "IWifiStaIface.hal",
+ ],
+ interfaces: [
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hidl.base@1.0",
+ ],
+ types: [
+ "StaLinkLayerRadioStats",
+ "StaLinkLayerStats",
+ ],
+ gen_java: true,
+}
+
diff --git a/wifi/1.3/IWifi.hal b/wifi/1.3/IWifi.hal
new file mode 100644
index 0000000..298e722
--- /dev/null
+++ b/wifi/1.3/IWifi.hal
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi@1.3;
+
+import @1.2::IWifi;
+
+/**
+ * This is the root of the HAL module and is the interface returned when
+ * loading an implementation of the Wi-Fi HAL. There must be at most one
+ * module loaded in the system.
+ * IWifi.getChip() must return @1.2::IWifiChip
+ */
+interface IWifi extends @1.2::IWifi {
+};
diff --git a/wifi/1.3/IWifiStaIface.hal b/wifi/1.3/IWifiStaIface.hal
new file mode 100644
index 0000000..0dc6128
--- /dev/null
+++ b/wifi/1.3/IWifiStaIface.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi@1.3;
+
+import @1.0::WifiStatus;
+import @1.2::IWifiStaIface;
+
+/**
+ * Interface used to represent a single STA iface.
+ *
+ * IWifiChip.createStaIface() may return a @1.3::IWifiStaIface when supported.
+ */
+interface IWifiStaIface extends @1.2::IWifiStaIface {
+ /**
+ * Retrieve the latest link layer stats.
+ * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if
+ * link layer stats collection hasn't been explicitly enabled.
+ *
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+ * |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+ * |WifiStatusCode.ERROR_NOT_STARTED|,
+ * |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+ * |WifiStatusCode.ERROR_UNKNOWN|
+ * @return stats Instance of |LinkLayerStats|.
+ */
+ getLinkLayerStats_1_3() generates (WifiStatus status, StaLinkLayerStats stats);
+};
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.3/default/Android.mk
similarity index 94%
rename from wifi/1.2/default/Android.mk
rename to wifi/1.3/default/Android.mk
index 3919690..541e5f0 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -58,7 +58,8 @@
libwifi-system-iface \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
- android.hardware.wifi@1.2
+ android.hardware.wifi@1.2 \
+ android.hardware.wifi@1.3
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)
@@ -84,7 +85,8 @@
libwifi-system-iface \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
- android.hardware.wifi@1.2
+ android.hardware.wifi@1.2 \
+ android.hardware.wifi@1.3
LOCAL_STATIC_LIBRARIES := \
android.hardware.wifi@1.0-service-lib
LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
@@ -107,11 +109,11 @@
LOCAL_STATIC_LIBRARIES := \
libgmock \
libgtest \
+ libhidlbase \
android.hardware.wifi@1.0-service-lib
LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
- libhidlbase \
libhidltransport \
liblog \
libnl \
@@ -120,5 +122,6 @@
libwifi-system-iface \
android.hardware.wifi@1.0 \
android.hardware.wifi@1.1 \
- android.hardware.wifi@1.2
+ android.hardware.wifi@1.2 \
+ android.hardware.wifi@1.3
include $(BUILD_NATIVE_TEST)
diff --git a/wifi/1.2/default/OWNERS b/wifi/1.3/default/OWNERS
similarity index 100%
rename from wifi/1.2/default/OWNERS
rename to wifi/1.3/default/OWNERS
diff --git a/wifi/1.2/default/THREADING.README b/wifi/1.3/default/THREADING.README
similarity index 100%
rename from wifi/1.2/default/THREADING.README
rename to wifi/1.3/default/THREADING.README
diff --git a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc b/wifi/1.3/default/android.hardware.wifi@1.0-service.rc
similarity index 100%
rename from wifi/1.2/default/android.hardware.wifi@1.0-service.rc
rename to wifi/1.3/default/android.hardware.wifi@1.0-service.rc
diff --git a/wifi/1.2/default/hidl_callback_util.h b/wifi/1.3/default/hidl_callback_util.h
similarity index 98%
rename from wifi/1.2/default/hidl_callback_util.h
rename to wifi/1.3/default/hidl_callback_util.h
index 97f312a..a44af79 100644
--- a/wifi/1.2/default/hidl_callback_util.h
+++ b/wifi/1.3/default/hidl_callback_util.h
@@ -52,7 +52,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_callback_util {
template <typename CallbackType>
@@ -117,7 +117,7 @@
} // namespace hidl_callback_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/hidl_return_util.h b/wifi/1.3/default/hidl_return_util.h
similarity index 98%
rename from wifi/1.2/default/hidl_return_util.h
rename to wifi/1.3/default/hidl_return_util.h
index 914c1b4..9707444 100644
--- a/wifi/1.2/default/hidl_return_util.h
+++ b/wifi/1.3/default/hidl_return_util.h
@@ -23,7 +23,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_return_util {
using namespace android::hardware::wifi::V1_0;
@@ -113,7 +113,7 @@
} // namespace hidl_return_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp
similarity index 97%
rename from wifi/1.2/default/hidl_struct_util.cpp
rename to wifi/1.3/default/hidl_struct_util.cpp
index 39ac544..c88ddaa 100644
--- a/wifi/1.2/default/hidl_struct_util.cpp
+++ b/wifi/1.3/default/hidl_struct_util.cpp
@@ -22,7 +22,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_struct_util {
@@ -69,9 +69,9 @@
return {};
}
-IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
+V1_2::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
uint32_t feature) {
- using HidlChipCaps = IWifiChip::ChipCapabilityMask;
+ using HidlChipCaps = V1_2::IWifiChip::ChipCapabilityMask;
switch (feature) {
case WIFI_FEATURE_SET_TX_POWER_LIMIT:
return HidlChipCaps::SET_TX_POWER_LIMIT;
@@ -139,9 +139,9 @@
convertLegacyLoggerFeatureToHidlChipCapability(feature);
}
}
- for (const auto feature : {WIFI_FEATURE_SET_TX_POWER_LIMIT,
- WIFI_FEATURE_USE_BODY_HEAD_SAR,
- WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) {
+ for (const auto feature :
+ {WIFI_FEATURE_SET_TX_POWER_LIMIT, WIFI_FEATURE_USE_BODY_HEAD_SAR,
+ WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) {
if (feature & legacy_feature_set) {
*hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature);
}
@@ -267,26 +267,26 @@
V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
switch (hidl_scenario) {
// This is the only supported scenario for V1_1
- case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
+ case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
};
CHECK(false);
}
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
- IWifiChip::TxPowerScenario hidl_scenario) {
+ V1_2::IWifiChip::TxPowerScenario hidl_scenario) {
switch (hidl_scenario) {
// This is the only supported scenario for V1_1
- case IWifiChip::TxPowerScenario::VOICE_CALL:
+ case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL:
return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
// Those are the supported scenarios for V1_2
- case IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF:
+ case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF:
return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
- case IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON:
+ case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON:
return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
- case IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF:
+ case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF:
return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
- case IWifiChip::TxPowerScenario::ON_BODY_CELL_ON:
+ case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON:
return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
};
CHECK(false);
@@ -294,7 +294,7 @@
bool convertLegacyWifiMacInfoToHidl(
const legacy_hal::WifiMacInfo& legacy_mac_info,
- IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
+ V1_2::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
if (!hidl_radio_mode_info) {
return false;
}
@@ -313,9 +313,9 @@
} else {
hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED;
}
- std::vector<IWifiChipEventCallback::IfaceInfo> iface_info_vec;
+ std::vector<V1_2::IWifiChipEventCallback::IfaceInfo> iface_info_vec;
for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) {
- IWifiChipEventCallback::IfaceInfo iface_info;
+ V1_2::IWifiChipEventCallback::IfaceInfo iface_info;
iface_info.name = legacy_iface_info.name;
iface_info.channel = legacy_iface_info.channel;
iface_info_vec.push_back(iface_info);
@@ -326,14 +326,15 @@
bool convertLegacyWifiMacInfosToHidl(
const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
- std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
+ std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>*
+ hidl_radio_mode_infos) {
if (!hidl_radio_mode_infos) {
return false;
}
*hidl_radio_mode_infos = {};
for (const auto& legacy_mac_info : legacy_mac_infos) {
- IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
+ V1_2::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info,
&hidl_radio_mode_info)) {
return false;
@@ -784,7 +785,7 @@
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
- StaLinkLayerStats* hidl_stats) {
+ V1_3::StaLinkLayerStats* hidl_stats) {
if (!hidl_stats) {
return false;
}
@@ -825,16 +826,26 @@
hidl_stats->iface.wmeVoPktStats.retries =
legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
// radio legacy_stats conversion.
- std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
+ std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
for (const auto& legacy_radio_stats : legacy_stats.radios) {
- StaLinkLayerRadioStats hidl_radio_stats;
- hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
- hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
- hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
- hidl_radio_stats.onTimeInMsForScan =
+ V1_3::StaLinkLayerRadioStats hidl_radio_stats;
+ hidl_radio_stats.V1_0.onTimeInMs = legacy_radio_stats.stats.on_time;
+ hidl_radio_stats.V1_0.txTimeInMs = legacy_radio_stats.stats.tx_time;
+ hidl_radio_stats.V1_0.rxTimeInMs = legacy_radio_stats.stats.rx_time;
+ hidl_radio_stats.V1_0.onTimeInMsForScan =
legacy_radio_stats.stats.on_time_scan;
- hidl_radio_stats.txTimeInMsPerLevel =
+ hidl_radio_stats.V1_0.txTimeInMsPerLevel =
legacy_radio_stats.tx_time_per_levels;
+ hidl_radio_stats.onTimeInMsForNanScan =
+ legacy_radio_stats.stats.on_time_nbd;
+ hidl_radio_stats.onTimeInMsForBgScan =
+ legacy_radio_stats.stats.on_time_gscan;
+ hidl_radio_stats.onTimeInMsForRoamScan =
+ legacy_radio_stats.stats.on_time_roam_scan;
+ hidl_radio_stats.onTimeInMsForPnoScan =
+ legacy_radio_stats.stats.on_time_pno_scan;
+ hidl_radio_stats.onTimeInMsForHs20Scan =
+ legacy_radio_stats.stats.on_time_hs20;
hidl_radios_stats.push_back(hidl_radio_stats);
}
hidl_stats->radios = hidl_radios_stats;
@@ -1197,7 +1208,7 @@
bool convertHidlNanEnableRequest_1_2ToLegacy(
const NanEnableRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
+ const V1_2::NanConfigRequestSupplemental& hidl_request2,
legacy_hal::NanEnableRequest* legacy_request) {
if (!legacy_request) {
LOG(ERROR)
@@ -1708,7 +1719,7 @@
bool convertHidlNanConfigRequest_1_2ToLegacy(
const NanConfigRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
+ const V1_2::NanConfigRequestSupplemental& hidl_request2,
legacy_hal::NanConfigRequest* legacy_request) {
if (!legacy_request) {
LOG(ERROR) << "convertHidlNanConfigRequest_1_2ToLegacy: legacy_request "
@@ -2039,7 +2050,7 @@
bool convertLegacyNdpChannelInfoToHidl(
const legacy_hal::NanChannelInfo& legacy_struct,
- NanDataPathChannelInfo* hidl_struct) {
+ V1_2::NanDataPathChannelInfo* hidl_struct) {
if (!hidl_struct) {
LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null";
return false;
@@ -2056,7 +2067,7 @@
bool convertLegacyNanDataPathConfirmIndToHidl(
const legacy_hal::NanDataPathConfirmInd& legacy_ind,
- NanDataPathConfirmInd* hidl_ind) {
+ V1_2::NanDataPathConfirmInd* hidl_ind) {
if (!hidl_ind) {
LOG(ERROR)
<< "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
@@ -2077,9 +2088,9 @@
convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
hidl_ind->V1_0.status.description = ""; // TODO: b/34059183
- std::vector<NanDataPathChannelInfo> channelInfo;
+ std::vector<V1_2::NanDataPathChannelInfo> channelInfo;
for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
- NanDataPathChannelInfo hidl_struct;
+ V1_2::NanDataPathChannelInfo hidl_struct;
if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
&hidl_struct)) {
return false;
@@ -2093,7 +2104,7 @@
bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
- NanDataPathScheduleUpdateInd* hidl_ind) {
+ V1_2::NanDataPathScheduleUpdateInd* hidl_ind) {
if (!hidl_ind) {
LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: "
"hidl_ind is null";
@@ -2103,9 +2114,9 @@
hidl_ind->peerDiscoveryAddress =
hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr);
- std::vector<NanDataPathChannelInfo> channelInfo;
+ std::vector<V1_2::NanDataPathChannelInfo> channelInfo;
for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
- NanDataPathChannelInfo hidl_struct;
+ V1_2::NanDataPathChannelInfo hidl_struct;
if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i],
&hidl_struct)) {
return false;
@@ -2616,7 +2627,7 @@
}
} // namespace hidl_struct_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h
similarity index 94%
rename from wifi/1.2/default/hidl_struct_util.h
rename to wifi/1.3/default/hidl_struct_util.h
index 3c789c0..8df484d 100644
--- a/wifi/1.2/default/hidl_struct_util.h
+++ b/wifi/1.3/default/hidl_struct_util.h
@@ -24,6 +24,7 @@
#include <android/hardware/wifi/1.2/IWifiChip.h>
#include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
#include <android/hardware/wifi/1.2/types.h>
+#include <android/hardware/wifi/1.3/types.h>
#include "wifi_legacy_hal.h"
@@ -36,7 +37,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_struct_util {
using namespace android::hardware::wifi::V1_0;
@@ -57,10 +58,11 @@
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
V1_1::IWifiChip::TxPowerScenario hidl_scenario);
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
- IWifiChip::TxPowerScenario hidl_scenario);
+ V1_2::IWifiChip::TxPowerScenario hidl_scenario);
bool convertLegacyWifiMacInfosToHidl(
const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
- std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
+ std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>*
+ hidl_radio_mode_infos);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(
@@ -88,7 +90,7 @@
std::vector<StaScanData>* hidl_scan_datas);
bool convertLegacyLinkLayerStatsToHidl(
const legacy_hal::LinkLayerStats& legacy_stats,
- StaLinkLayerStats* hidl_stats);
+ V1_3::StaLinkLayerStats* hidl_stats);
bool convertLegacyRoamingCapabilitiesToHidl(
const legacy_hal::wifi_roaming_capabilities& legacy_caps,
StaRoamingCapabilities* hidl_caps);
@@ -115,11 +117,11 @@
legacy_hal::NanConfigRequest* legacy_request);
bool convertHidlNanEnableRequest_1_2ToLegacy(
const NanEnableRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
+ const V1_2::NanConfigRequestSupplemental& hidl_request2,
legacy_hal::NanEnableRequest* legacy_request);
bool convertHidlNanConfigRequest_1_2ToLegacy(
const NanConfigRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
+ const V1_2::NanConfigRequestSupplemental& hidl_request2,
legacy_hal::NanConfigRequest* legacy_request);
bool convertHidlNanPublishRequestToLegacy(
const NanPublishRequest& hidl_request,
@@ -152,10 +154,10 @@
NanDataPathRequestInd* hidl_ind);
bool convertLegacyNanDataPathConfirmIndToHidl(
const legacy_hal::NanDataPathConfirmInd& legacy_ind,
- NanDataPathConfirmInd* hidl_ind);
+ V1_2::NanDataPathConfirmInd* hidl_ind);
bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
- NanDataPathScheduleUpdateInd* hidl_ind);
+ V1_2::NanDataPathScheduleUpdateInd* hidl_ind);
// RTT controller conversion methods.
bool convertHidlVectorOfRttConfigToLegacy(
@@ -184,7 +186,7 @@
std::vector<RttResult>* hidl_results);
} // namespace hidl_struct_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/hidl_sync_util.cpp b/wifi/1.3/default/hidl_sync_util.cpp
similarity index 96%
rename from wifi/1.2/default/hidl_sync_util.cpp
rename to wifi/1.3/default/hidl_sync_util.cpp
index ad8448a..160727f 100644
--- a/wifi/1.2/default/hidl_sync_util.cpp
+++ b/wifi/1.3/default/hidl_sync_util.cpp
@@ -23,7 +23,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_sync_util {
@@ -33,7 +33,7 @@
} // namespace hidl_sync_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/hidl_sync_util.h b/wifi/1.3/default/hidl_sync_util.h
similarity index 96%
rename from wifi/1.2/default/hidl_sync_util.h
rename to wifi/1.3/default/hidl_sync_util.h
index 8381862..ebfb051 100644
--- a/wifi/1.2/default/hidl_sync_util.h
+++ b/wifi/1.3/default/hidl_sync_util.h
@@ -24,13 +24,13 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace hidl_sync_util {
std::unique_lock<std::recursive_mutex> acquireGlobalLock();
} // namespace hidl_sync_util
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/ringbuffer.cpp b/wifi/1.3/default/ringbuffer.cpp
similarity index 97%
rename from wifi/1.2/default/ringbuffer.cpp
rename to wifi/1.3/default/ringbuffer.cpp
index c126b36..1294c52 100644
--- a/wifi/1.2/default/ringbuffer.cpp
+++ b/wifi/1.3/default/ringbuffer.cpp
@@ -21,7 +21,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
@@ -48,7 +48,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/ringbuffer.h b/wifi/1.3/default/ringbuffer.h
similarity index 97%
rename from wifi/1.2/default/ringbuffer.h
rename to wifi/1.3/default/ringbuffer.h
index 4808e40..d9f8df6 100644
--- a/wifi/1.2/default/ringbuffer.h
+++ b/wifi/1.3/default/ringbuffer.h
@@ -23,7 +23,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
/**
@@ -45,7 +45,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/service.cpp b/wifi/1.3/default/service.cpp
similarity index 83%
rename from wifi/1.2/default/service.cpp
rename to wifi/1.3/default/service.cpp
index 01d22bd..5fd83c1 100644
--- a/wifi/1.2/default/service.cpp
+++ b/wifi/1.3/default/service.cpp
@@ -26,10 +26,10 @@
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
-using android::hardware::wifi::V1_2::implementation::feature_flags::
+using android::hardware::wifi::V1_3::implementation::feature_flags::
WifiFeatureFlags;
-using android::hardware::wifi::V1_2::implementation::legacy_hal::WifiLegacyHal;
-using android::hardware::wifi::V1_2::implementation::mode_controller::
+using android::hardware::wifi::V1_3::implementation::legacy_hal::WifiLegacyHal;
+using android::hardware::wifi::V1_3::implementation::mode_controller::
WifiModeController;
int main(int /*argc*/, char** argv) {
@@ -40,8 +40,8 @@
configureRpcThreadpool(1, true /* callerWillJoin */);
// Setup hwbinder service
- android::sp<android::hardware::wifi::V1_2::IWifi> service =
- new android::hardware::wifi::V1_2::implementation::Wifi(
+ android::sp<android::hardware::wifi::V1_3::IWifi> service =
+ new android::hardware::wifi::V1_3::implementation::Wifi(
std::make_shared<WifiLegacyHal>(),
std::make_shared<WifiModeController>(),
std::make_shared<WifiFeatureFlags>());
diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
new file mode 100644
index 0000000..d600a2b
--- /dev/null
+++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN
+#include "hidl_struct_util.h"
+
+using testing::Test;
+
+namespace {
+constexpr uint32_t kMacId1 = 1;
+constexpr uint32_t kMacId2 = 2;
+constexpr uint32_t kIfaceChannel1 = 3;
+constexpr uint32_t kIfaceChannel2 = 5;
+constexpr char kIfaceName1[] = "wlan0";
+constexpr char kIfaceName2[] = "wlan1";
+} // namespace
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_3 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+class HidlStructUtilTest : public Test {};
+
+TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {
+ .wlan_mac_id = kMacId1,
+ .mac_band =
+ legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
+ .channel = kIfaceChannel1};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
+ .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+
+ std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
+ hidl_radio_mode_infos;
+ ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
+ legacy_mac_infos, &hidl_radio_mode_infos));
+
+ ASSERT_EQ(1u, hidl_radio_mode_infos.size());
+ auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
+ EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId);
+ EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
+ ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
+ auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
+ hidl_iface_info1.channel);
+ auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1];
+ EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
+ hidl_iface_info2.channel);
+}
+
+TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {
+ .wlan_mac_id = kMacId1, .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
+ .channel = kIfaceChannel1};
+ legacy_hal::WifiMacInfo legacy_mac_info2 = {
+ .wlan_mac_id = kMacId2, .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
+ .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+ legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info2);
+
+ std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
+ hidl_radio_mode_infos;
+ ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
+ legacy_mac_infos, &hidl_radio_mode_infos));
+
+ ASSERT_EQ(2u, hidl_radio_mode_infos.size());
+
+ // Find mac info 1.
+ const auto hidl_radio_mode_info1 =
+ std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+ [&legacy_mac_info1](
+ const V1_2::IWifiChipEventCallback::RadioModeInfo& x) {
+ return x.radioId == legacy_mac_info1.wlan_mac_id;
+ });
+ ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
+ EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
+ ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
+ auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
+ hidl_iface_info1.channel);
+
+ // Find mac info 2.
+ const auto hidl_radio_mode_info2 =
+ std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+ [&legacy_mac_info2](
+ const V1_2::IWifiChipEventCallback::RadioModeInfo& x) {
+ return x.radioId == legacy_mac_info2.wlan_mac_id;
+ });
+ ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
+ EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
+ ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
+ auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
+ hidl_iface_info2.channel);
+}
+
+TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
+ legacy_hal::LinkLayerStats legacy_stats{};
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.iface.beacon_rx = rand();
+ legacy_stats.iface.rssi_mgmt = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
+
+ for (auto& radio : legacy_stats.radios) {
+ radio.stats.on_time = rand();
+ radio.stats.tx_time = rand();
+ radio.stats.rx_time = rand();
+ radio.stats.on_time_scan = rand();
+ radio.stats.on_time_nbd = rand();
+ radio.stats.on_time_gscan = rand();
+ radio.stats.on_time_roam_scan = rand();
+ radio.stats.on_time_pno_scan = rand();
+ radio.stats.on_time_hs20 = rand();
+ for (int i = 0; i < 4; i++) {
+ radio.tx_time_per_levels.push_back(rand());
+ }
+ }
+
+ V1_3::StaLinkLayerStats converted{};
+ hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
+ &converted);
+ EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx);
+ EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
+ converted.iface.wmeBePktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
+ converted.iface.wmeBePktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
+ converted.iface.wmeBePktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
+ converted.iface.wmeBePktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
+ converted.iface.wmeBkPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
+ converted.iface.wmeBkPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
+ converted.iface.wmeBkPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
+ converted.iface.wmeBkPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
+ converted.iface.wmeViPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
+ converted.iface.wmeViPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
+ converted.iface.wmeViPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
+ converted.iface.wmeViPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
+ converted.iface.wmeVoPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
+ converted.iface.wmeVoPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
+ converted.iface.wmeVoPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
+ converted.iface.wmeVoPktStats.retries);
+
+ EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
+ for (int i = 0; i < legacy_stats.radios.size(); i++) {
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
+ converted.radios[i].V1_0.onTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
+ converted.radios[i].V1_0.txTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
+ converted.radios[i].V1_0.rxTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
+ converted.radios[i].V1_0.onTimeInMsForScan);
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
+ converted.radios[i].V1_0.txTimeInMsPerLevel.size());
+ for (int j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
+ j++) {
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
+ converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
+ }
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
+ converted.radios[i].onTimeInMsForNanScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
+ converted.radios[i].onTimeInMsForBgScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
+ converted.radios[i].onTimeInMsForRoamScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
+ converted.radios[i].onTimeInMsForPnoScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
+ converted.radios[i].onTimeInMsForHs20Scan);
+ }
+}
+} // namespace implementation
+} // namespace V1_3
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.2/default/tests/main.cpp b/wifi/1.3/default/tests/main.cpp
similarity index 100%
rename from wifi/1.2/default/tests/main.cpp
rename to wifi/1.3/default/tests/main.cpp
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp
similarity index 96%
rename from wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
rename to wifi/1.3/default/tests/mock_wifi_feature_flags.cpp
index 8d0b192..a393fdc 100644
--- a/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.cpp
@@ -21,7 +21,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace feature_flags {
@@ -29,7 +29,7 @@
} // namespace feature_flags
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.h b/wifi/1.3/default/tests/mock_wifi_feature_flags.h
similarity index 96%
rename from wifi/1.2/default/tests/mock_wifi_feature_flags.h
rename to wifi/1.3/default/tests/mock_wifi_feature_flags.h
index 2a36dd5..86c50a7 100644
--- a/wifi/1.2/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.3/default/tests/mock_wifi_feature_flags.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace feature_flags {
@@ -39,7 +39,7 @@
} // namespace feature_flags
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
similarity index 96%
rename from wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
rename to wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
index 8381dde..4cd279d 100644
--- a/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.cpp
@@ -24,14 +24,14 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace legacy_hal {
MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {}
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
similarity index 97%
rename from wifi/1.2/default/tests/mock_wifi_legacy_hal.h
rename to wifi/1.3/default/tests/mock_wifi_legacy_hal.h
index 43370b4..deb3a5a 100644
--- a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.3/default/tests/mock_wifi_legacy_hal.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace legacy_hal {
@@ -49,7 +49,7 @@
};
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp
similarity index 96%
rename from wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
rename to wifi/1.3/default/tests/mock_wifi_mode_controller.cpp
index 461a581..2b0ea36 100644
--- a/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
+++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.cpp
@@ -24,14 +24,14 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace mode_controller {
MockWifiModeController::MockWifiModeController() : WifiModeController() {}
} // namespace mode_controller
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.h b/wifi/1.3/default/tests/mock_wifi_mode_controller.h
similarity index 97%
rename from wifi/1.2/default/tests/mock_wifi_mode_controller.h
rename to wifi/1.3/default/tests/mock_wifi_mode_controller.h
index 50c3e35..c204059 100644
--- a/wifi/1.2/default/tests/mock_wifi_mode_controller.h
+++ b/wifi/1.3/default/tests/mock_wifi_mode_controller.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace mode_controller {
@@ -38,7 +38,7 @@
};
} // namespace mode_controller
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp
similarity index 98%
rename from wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
rename to wifi/1.3/default/tests/ringbuffer_unit_tests.cpp
index ad5289b..0cf1e4f 100644
--- a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
+++ b/wifi/1.3/default/tests/ringbuffer_unit_tests.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
class RingbufferTest : public Test {
@@ -91,7 +91,7 @@
EXPECT_EQ(input, buffer_.getData().front());
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.3/default/tests/runtests.sh b/wifi/1.3/default/tests/runtests.sh
new file mode 100755
index 0000000..6bce3ef
--- /dev/null
+++ b/wifi/1.3/default/tests/runtests.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+# 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+set -e
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests
+adb root
+adb sync data
+adb shell /data/nativetest64/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
similarity index 96%
rename from wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
rename to wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 8722d0a..2d9050d 100644
--- a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -38,7 +38,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
class WifiChipTest : public Test {
@@ -542,38 +542,38 @@
////////// V1 Iface Combinations when AP creation is disabled //////////
class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV1_AwareDisabledApIfaceCombination();
- WifiChipTest::SetUp();
- }
+ public:
+ void SetUp() override {
+ setupV1_AwareDisabledApIfaceCombination();
+ WifiChipTest::SetUp();
+ }
};
TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest,
StaMode_CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
}
////////// V2 Iface Combinations when AP creation is disabled //////////
-class WifiChipV2_AwareDisabledApIfaceCombinationTest: public WifiChipTest {
- public:
- void SetUp() override {
- setupV2_AwareDisabledApIfaceCombination();
- WifiChipTest::SetUp();
- }
+class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV2_AwareDisabledApIfaceCombination();
+ WifiChipTest::SetUp();
+ }
};
TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest,
CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
+ findModeAndConfigureForIfaceType(IfaceType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.3/default/wifi.cpp
similarity index 99%
rename from wifi/1.2/default/wifi.cpp
rename to wifi/1.3/default/wifi.cpp
index 79f921f..e3af1ea 100644
--- a/wifi/1.2/default/wifi.cpp
+++ b/wifi/1.3/default/wifi.cpp
@@ -28,7 +28,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
using hidl_return_util::validateAndCallWithLock;
@@ -206,7 +206,7 @@
return createWifiStatus(WifiStatusCode::SUCCESS);
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi.h b/wifi/1.3/default/wifi.h
similarity index 96%
rename from wifi/1.2/default/wifi.h
rename to wifi/1.3/default/wifi.h
index 86919b1..e921424 100644
--- a/wifi/1.2/default/wifi.h
+++ b/wifi/1.3/default/wifi.h
@@ -20,7 +20,7 @@
#include <functional>
#include <android-base/macros.h>
-#include <android/hardware/wifi/1.2/IWifi.h>
+#include <android/hardware/wifi/1.3/IWifi.h>
#include <utils/Looper.h>
#include "hidl_callback_util.h"
@@ -32,13 +32,13 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
/**
* Root HIDL interface object used to control the Wifi HAL.
*/
-class Wifi : public V1_2::IWifi {
+class Wifi : public V1_3::IWifi {
public:
Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
const std::shared_ptr<mode_controller::WifiModeController>
@@ -88,7 +88,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_ap_iface.cpp b/wifi/1.3/default/wifi_ap_iface.cpp
similarity index 98%
rename from wifi/1.2/default/wifi_ap_iface.cpp
rename to wifi/1.3/default/wifi_ap_iface.cpp
index 92b7b48..c203e47 100644
--- a/wifi/1.2/default/wifi_ap_iface.cpp
+++ b/wifi/1.3/default/wifi_ap_iface.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
@@ -93,7 +93,7 @@
return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_ap_iface.h b/wifi/1.3/default/wifi_ap_iface.h
similarity index 98%
rename from wifi/1.2/default/wifi_ap_iface.h
rename to wifi/1.3/default/wifi_ap_iface.h
index 5363ec2..9f3d870 100644
--- a/wifi/1.2/default/wifi_ap_iface.h
+++ b/wifi/1.3/default/wifi_ap_iface.h
@@ -25,7 +25,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
@@ -65,7 +65,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
similarity index 97%
rename from wifi/1.2/default/wifi_chip.cpp
rename to wifi/1.3/default/wifi_chip.cpp
index 3bd0557..cf64e51 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -28,13 +28,13 @@
#include "wifi_status_util.h"
namespace {
+using android::sp;
using android::base::unique_fd;
using android::hardware::hidl_string;
using android::hardware::hidl_vec;
using android::hardware::wifi::V1_0::ChipModeId;
using android::hardware::wifi::V1_0::IfaceType;
using android::hardware::wifi::V1_0::IWifiChip;
-using android::sp;
constexpr ChipModeId kInvalidModeId = UINT32_MAX;
// These mode ID's should be unique (even across combo versions). Refer to
@@ -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;
}
@@ -304,7 +304,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
using hidl_return_util::validateAndCallWithLock;
@@ -335,7 +335,7 @@
bool WifiChip::isValid() { return is_valid_; }
-std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
+std::set<sp<V1_2::IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
return event_cb_handler_.getCallbacks();
}
@@ -344,6 +344,7 @@
&WifiChip::getIdInternal, hidl_status_cb);
}
+// Deprecated support for this callback
Return<void> WifiChip::registerEventCallback(
const sp<V1_0::IWifiChipEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) {
@@ -546,7 +547,8 @@
}
Return<void> WifiChip::selectTxPowerScenario(
- V1_1::IWifiChip::TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
+ V1_1::IWifiChip::TxPowerScenario scenario,
+ selectTxPowerScenario_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::selectTxPowerScenarioInternal,
hidl_status_cb, scenario);
@@ -560,7 +562,7 @@
}
Return<void> WifiChip::registerEventCallback_1_2(
- const sp<IWifiChipEventCallback>& event_callback,
+ const sp<V1_2::IWifiChipEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::registerEventCallbackInternal_1_2,
@@ -568,9 +570,10 @@
}
Return<void> WifiChip::selectTxPowerScenario_1_2(
- TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
+ TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario);
+ &WifiChip::selectTxPowerScenarioInternal_1_2,
+ hidl_status_cb, scenario);
}
Return<void> WifiChip::debug(const hidl_handle& handle,
@@ -1036,7 +1039,7 @@
}
WifiStatus WifiChip::selectTxPowerScenarioInternal(
- V1_1::IWifiChip::TxPowerScenario scenario) {
+ V1_1::IWifiChip::TxPowerScenario scenario) {
auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
getWlan0IfaceName(),
hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
@@ -1050,14 +1053,15 @@
}
WifiStatus WifiChip::registerEventCallbackInternal_1_2(
- const sp<IWifiChipEventCallback>& event_callback) {
+ const sp<V1_2::IWifiChipEventCallback>& event_callback) {
if (!event_cb_handler_.addCallback(event_callback)) {
return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
}
return createWifiStatus(WifiStatusCode::SUCCESS);
}
-WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) {
+WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(
+ TxPowerScenario scenario) {
auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
getWlan0IfaceName(),
hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
@@ -1156,7 +1160,7 @@
LOG(ERROR) << "Callback invoked on an invalid object";
return;
}
- std::vector<IWifiChipEventCallback::RadioModeInfo>
+ std::vector<V1_2::IWifiChipEventCallback::RadioModeInfo>
hidl_radio_mode_infos;
if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
mac_infos, &hidl_radio_mode_infos)) {
@@ -1212,15 +1216,14 @@
const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
{chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
if (feature_flags_.lock()->isApDisabled()) {
- const IWifiChip::ChipMode chip_mode = {
- kV2ChipModeId,
- {chip_iface_combination_2}};
- modes_ = {chip_mode};
+ const IWifiChip::ChipMode chip_mode = {kV2ChipModeId,
+ {chip_iface_combination_2}};
+ modes_ = {chip_mode};
} else {
- const IWifiChip::ChipMode chip_mode = {
- kV2ChipModeId,
- {chip_iface_combination_1, chip_iface_combination_2}};
- modes_ = {chip_mode};
+ const IWifiChip::ChipMode chip_mode = {
+ kV2ChipModeId,
+ {chip_iface_combination_1, chip_iface_combination_2}};
+ modes_ = {chip_mode};
}
} else {
// V1 Iface combinations for Mode Id = 0. (STA Mode)
@@ -1246,9 +1249,9 @@
const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
{ap_chip_iface_combination}};
if (feature_flags_.lock()->isApDisabled()) {
- modes_ = {sta_chip_mode};
+ modes_ = {sta_chip_mode};
} else {
- modes_ = {sta_chip_mode, ap_chip_mode};
+ modes_ = {sta_chip_mode, ap_chip_mode};
}
}
}
@@ -1415,7 +1418,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
similarity index 95%
rename from wifi/1.2/default/wifi_chip.h
rename to wifi/1.3/default/wifi_chip.h
index ada9458..ba60a8e 100644
--- a/wifi/1.2/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -37,7 +37,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
@@ -69,10 +69,11 @@
// marked valid before processing them.
void invalidate();
bool isValid();
- std::set<sp<IWifiChipEventCallback>> getEventCallbacks();
+ std::set<sp<V1_2::IWifiChipEventCallback>> getEventCallbacks();
// HIDL methods exposed.
Return<void> getId(getId_cb hidl_status_cb) override;
+ // Deprecated support for this callback
Return<void> registerEventCallback(
const sp<V1_0::IWifiChipEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) override;
@@ -137,18 +138,20 @@
Return<void> resetTxPowerScenario(
resetTxPowerScenario_cb hidl_status_cb) override;
Return<void> registerEventCallback_1_2(
- const sp<IWifiChipEventCallback>& event_callback,
+ const sp<V1_2::IWifiChipEventCallback>& event_callback,
registerEventCallback_1_2_cb hidl_status_cb) override;
Return<void> selectTxPowerScenario_1_2(
TxPowerScenario scenario,
selectTxPowerScenario_cb hidl_status_cb) override;
Return<void> debug(const hidl_handle& handle,
const hidl_vec<hidl_string>& options) override;
+
private:
void invalidateAndRemoveAllIfaces();
// Corresponding worker functions for the HIDL methods.
std::pair<WifiStatus, ChipId> getIdInternal();
+ // Deprecated support for this callback
WifiStatus registerEventCallbackInternal(
const sp<V1_0::IWifiChipEventCallback>& event_callback);
std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
@@ -195,10 +198,11 @@
std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
getDebugHostWakeReasonStatsInternal();
WifiStatus enableDebugErrorAlertsInternal(bool enable);
- WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario);
+ WifiStatus selectTxPowerScenarioInternal(
+ V1_1::IWifiChip::TxPowerScenario scenario);
WifiStatus resetTxPowerScenarioInternal();
WifiStatus registerEventCallbackInternal_1_2(
- const sp<IWifiChipEventCallback>& event_callback);
+ const sp<V1_2::IWifiChipEventCallback>& event_callback);
WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
WifiStatus handleChipConfiguration(
std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
@@ -236,14 +240,14 @@
// registration mechanism. Use this to check if we have already
// registered a callback.
bool debug_ring_buffer_cb_registered_;
- hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
+ hidl_callback_util::HidlCallbackHandler<V1_2::IWifiChipEventCallback>
event_cb_handler_;
DISALLOW_COPY_AND_ASSIGN(WifiChip);
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_feature_flags.cpp b/wifi/1.3/default/wifi_feature_flags.cpp
similarity index 93%
rename from wifi/1.2/default/wifi_feature_flags.cpp
rename to wifi/1.3/default/wifi_feature_flags.cpp
index 778944d..8d48c36 100644
--- a/wifi/1.2/default/wifi_feature_flags.cpp
+++ b/wifi/1.3/default/wifi_feature_flags.cpp
@@ -38,7 +38,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace feature_flags {
@@ -47,13 +47,11 @@
bool WifiFeatureFlags::isDualInterfaceSupported() {
return wifiHidlFeatureDualInterface;
}
-bool WifiFeatureFlags::isApDisabled() {
- return wifiHidlFeatureDisableAp;
-}
+bool WifiFeatureFlags::isApDisabled() { return wifiHidlFeatureDisableAp; }
} // namespace feature_flags
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_feature_flags.h b/wifi/1.3/default/wifi_feature_flags.h
similarity index 96%
rename from wifi/1.2/default/wifi_feature_flags.h
rename to wifi/1.3/default/wifi_feature_flags.h
index 4a7b2d2..ce74e23 100644
--- a/wifi/1.2/default/wifi_feature_flags.h
+++ b/wifi/1.3/default/wifi_feature_flags.h
@@ -20,7 +20,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace feature_flags {
@@ -36,7 +36,7 @@
} // namespace feature_flags
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp
similarity index 99%
rename from wifi/1.2/default/wifi_legacy_hal.cpp
rename to wifi/1.3/default/wifi_legacy_hal.cpp
index 375204c..817c860 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal.cpp
@@ -18,6 +18,7 @@
#include <chrono>
#include <android-base/logging.h>
+#include <cutils/properties.h>
#include "hidl_sync_util.h"
#include "wifi_legacy_hal.h"
@@ -35,6 +36,7 @@
static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
static constexpr uint32_t kMaxRingBuffers = 10;
static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
+static constexpr char kDriverPropName[] = "wlan.driver.status";
// Helper function to create a non-const char* for legacy Hal API's.
std::vector<char> makeCharVec(const std::string& str) {
@@ -48,7 +50,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace legacy_hal {
// Legacy HAL functions accept "C" style function pointers, so use global
@@ -366,6 +368,8 @@
LOG(ERROR) << "Timed out awaiting driver ready";
return status;
}
+ property_set(kDriverPropName, "ok");
+
LOG(DEBUG) << "Starting legacy HAL";
if (!iface_tool_.SetWifiUpState(true)) {
LOG(ERROR) << "Failed to set WiFi interface up";
@@ -1417,7 +1421,7 @@
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
similarity index 98%
rename from wifi/1.2/default/wifi_legacy_hal.h
rename to wifi/1.3/default/wifi_legacy_hal.h
index 00dfeef..af654fa 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -27,14 +27,15 @@
// HACK: The include inside the namespace below also transitively includes a
// bunch of libc headers into the namespace, which leads to functions like
-// socketpair being defined in android::hardware::wifi::V1_1::implementation::legacy_hal.
-// Include this one particular header as a hacky workaround until that's fixed.
+// socketpair being defined in
+// android::hardware::wifi::V1_1::implementation::legacy_hal. Include this one
+// particular header as a hacky workaround until that's fixed.
#include <sys/socket.h>
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
// This is in a separate namespace to prevent typename conflicts between
// the legacy HAL types and the HIDL interface types.
@@ -106,7 +107,8 @@
on_event_transmit_follow_up;
std::function<void(const NanRangeRequestInd&)> on_event_range_request;
std::function<void(const NanRangeReportInd&)> on_event_range_report;
- std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
+ std::function<void(const NanDataPathScheduleUpdateInd&)>
+ on_event_schedule_update;
};
// Full scan results contain IE info and are hence passed by reference, to
@@ -389,7 +391,7 @@
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp
similarity index 99%
rename from wifi/1.2/default/wifi_legacy_hal_stubs.cpp
rename to wifi/1.3/default/wifi_legacy_hal_stubs.cpp
index fc28bb5..942df2a 100644
--- a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp
@@ -20,7 +20,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace legacy_hal {
template <typename>
@@ -141,7 +141,7 @@
}
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.h b/wifi/1.3/default/wifi_legacy_hal_stubs.h
similarity index 96%
rename from wifi/1.2/default/wifi_legacy_hal_stubs.h
rename to wifi/1.3/default/wifi_legacy_hal_stubs.h
index d560dd4..64854e0 100644
--- a/wifi/1.2/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.3/default/wifi_legacy_hal_stubs.h
@@ -20,7 +20,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace legacy_hal {
#include <hardware_legacy/wifi_hal.h>
@@ -28,7 +28,7 @@
bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
} // namespace legacy_hal
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_mode_controller.cpp b/wifi/1.3/default/wifi_mode_controller.cpp
similarity index 98%
rename from wifi/1.2/default/wifi_mode_controller.cpp
rename to wifi/1.3/default/wifi_mode_controller.cpp
index c286d24..c392486 100644
--- a/wifi/1.2/default/wifi_mode_controller.cpp
+++ b/wifi/1.3/default/wifi_mode_controller.cpp
@@ -48,7 +48,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace mode_controller {
@@ -85,7 +85,7 @@
}
} // namespace mode_controller
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_mode_controller.h b/wifi/1.3/default/wifi_mode_controller.h
similarity index 97%
rename from wifi/1.2/default/wifi_mode_controller.h
rename to wifi/1.3/default/wifi_mode_controller.h
index 395aa5d..ace5a52 100644
--- a/wifi/1.2/default/wifi_mode_controller.h
+++ b/wifi/1.3/default/wifi_mode_controller.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
namespace mode_controller {
using namespace android::hardware::wifi::V1_0;
@@ -55,7 +55,7 @@
} // namespace mode_controller
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.3/default/wifi_nan_iface.cpp
similarity index 98%
rename from wifi/1.2/default/wifi_nan_iface.cpp
rename to wifi/1.3/default/wifi_nan_iface.cpp
index 566d36e..4325f44 100644
--- a/wifi/1.2/default/wifi_nan_iface.cpp
+++ b/wifi/1.3/default/wifi_nan_iface.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
@@ -420,7 +420,7 @@
LOG(ERROR) << "Callback invoked on an invalid object";
return;
}
- NanDataPathConfirmInd hidl_struct;
+ V1_2::NanDataPathConfirmInd hidl_struct;
if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(
msg, &hidl_struct)) {
LOG(ERROR) << "Failed to convert nan capabilities response";
@@ -477,7 +477,7 @@
LOG(ERROR) << "Callback invoked on an invalid object";
return;
}
- NanDataPathScheduleUpdateInd hidl_struct;
+ V1_2::NanDataPathScheduleUpdateInd hidl_struct;
if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl(
msg, &hidl_struct)) {
LOG(ERROR) << "Failed to convert nan capabilities response";
@@ -655,7 +655,7 @@
}
Return<void> WifiNanIface::registerEventCallback_1_2(
- const sp<IWifiNanIfaceEventCallback>& callback,
+ const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
registerEventCallback_1_2_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
&WifiNanIface::registerEventCallback_1_2Internal,
@@ -664,7 +664,7 @@
Return<void> WifiNanIface::enableRequest_1_2(
uint16_t cmd_id, const NanEnableRequest& msg1,
- const NanConfigRequestSupplemental& msg2,
+ const V1_2::NanConfigRequestSupplemental& msg2,
enableRequest_1_2_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
&WifiNanIface::enableRequest_1_2Internal,
@@ -673,7 +673,7 @@
Return<void> WifiNanIface::configRequest_1_2(
uint16_t cmd_id, const NanConfigRequest& msg1,
- const NanConfigRequestSupplemental& msg2,
+ const V1_2::NanConfigRequestSupplemental& msg2,
configRequest_1_2_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
&WifiNanIface::configRequest_1_2Internal,
@@ -832,7 +832,7 @@
WifiStatus WifiNanIface::enableRequest_1_2Internal(
uint16_t cmd_id, const NanEnableRequest& msg1,
- const NanConfigRequestSupplemental& msg2) {
+ const V1_2::NanConfigRequestSupplemental& msg2) {
legacy_hal::NanEnableRequest legacy_msg;
if (!hidl_struct_util::convertHidlNanEnableRequest_1_2ToLegacy(
msg1, msg2, &legacy_msg)) {
@@ -845,7 +845,7 @@
WifiStatus WifiNanIface::configRequest_1_2Internal(
uint16_t cmd_id, const NanConfigRequest& msg1,
- const NanConfigRequestSupplemental& msg2) {
+ const V1_2::NanConfigRequestSupplemental& msg2) {
legacy_hal::NanConfigRequest legacy_msg;
if (!hidl_struct_util::convertHidlNanConfigRequest_1_2ToLegacy(
msg1, msg2, &legacy_msg)) {
@@ -857,7 +857,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.3/default/wifi_nan_iface.h
similarity index 95%
rename from wifi/1.2/default/wifi_nan_iface.h
rename to wifi/1.3/default/wifi_nan_iface.h
index dba527b..f735d61 100644
--- a/wifi/1.2/default/wifi_nan_iface.h
+++ b/wifi/1.3/default/wifi_nan_iface.h
@@ -27,7 +27,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
@@ -89,15 +89,15 @@
terminateDataPathRequest_cb hidl_status_cb) override;
Return<void> registerEventCallback_1_2(
- const sp<IWifiNanIfaceEventCallback>& callback,
+ const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
registerEventCallback_1_2_cb hidl_status_cb) override;
Return<void> enableRequest_1_2(
uint16_t cmd_id, const NanEnableRequest& msg1,
- const NanConfigRequestSupplemental& msg2,
+ const V1_2::NanConfigRequestSupplemental& msg2,
enableRequest_1_2_cb hidl_status_cb) override;
Return<void> configRequest_1_2(
uint16_t cmd_id, const NanConfigRequest& msg1,
- const NanConfigRequestSupplemental& msg2,
+ const V1_2::NanConfigRequestSupplemental& msg2,
configRequest_1_2_cb hidl_status_cb) override;
private:
@@ -135,10 +135,10 @@
const sp<V1_2::IWifiNanIfaceEventCallback>& callback);
WifiStatus enableRequest_1_2Internal(
uint16_t cmd_id, const NanEnableRequest& msg1,
- const NanConfigRequestSupplemental& msg2);
+ const V1_2::NanConfigRequestSupplemental& msg2);
WifiStatus configRequest_1_2Internal(
uint16_t cmd_id, const NanConfigRequest& msg,
- const NanConfigRequestSupplemental& msg2);
+ const V1_2::NanConfigRequestSupplemental& msg2);
// all 1_0 and descendant callbacks
std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks();
@@ -157,7 +157,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_p2p_iface.cpp b/wifi/1.3/default/wifi_p2p_iface.cpp
similarity index 97%
rename from wifi/1.2/default/wifi_p2p_iface.cpp
rename to wifi/1.3/default/wifi_p2p_iface.cpp
index 92bbaee..b5d5886 100644
--- a/wifi/1.2/default/wifi_p2p_iface.cpp
+++ b/wifi/1.3/default/wifi_p2p_iface.cpp
@@ -23,7 +23,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
@@ -60,7 +60,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_p2p_iface.h b/wifi/1.3/default/wifi_p2p_iface.h
similarity index 97%
rename from wifi/1.2/default/wifi_p2p_iface.h
rename to wifi/1.3/default/wifi_p2p_iface.h
index 76120b1..8a7207a 100644
--- a/wifi/1.2/default/wifi_p2p_iface.h
+++ b/wifi/1.3/default/wifi_p2p_iface.h
@@ -25,7 +25,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
@@ -58,7 +58,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_rtt_controller.cpp b/wifi/1.3/default/wifi_rtt_controller.cpp
similarity index 99%
rename from wifi/1.2/default/wifi_rtt_controller.cpp
rename to wifi/1.3/default/wifi_rtt_controller.cpp
index b68445b..fa317e3 100644
--- a/wifi/1.2/default/wifi_rtt_controller.cpp
+++ b/wifi/1.3/default/wifi_rtt_controller.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
@@ -269,7 +269,7 @@
return createWifiStatusFromLegacyError(legacy_status);
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_rtt_controller.h b/wifi/1.3/default/wifi_rtt_controller.h
similarity index 98%
rename from wifi/1.2/default/wifi_rtt_controller.h
rename to wifi/1.3/default/wifi_rtt_controller.h
index 1ab01e1..9798b79 100644
--- a/wifi/1.2/default/wifi_rtt_controller.h
+++ b/wifi/1.3/default/wifi_rtt_controller.h
@@ -27,7 +27,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
/**
@@ -97,7 +97,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp
similarity index 97%
rename from wifi/1.2/default/wifi_sta_iface.cpp
rename to wifi/1.3/default/wifi_sta_iface.cpp
index daa5610..b0fa1ae 100644
--- a/wifi/1.2/default/wifi_sta_iface.cpp
+++ b/wifi/1.3/default/wifi_sta_iface.cpp
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using hidl_return_util::validateAndCall;
@@ -152,6 +152,13 @@
hidl_status_cb);
}
+Return<void> WifiStaIface::getLinkLayerStats_1_3(
+ getLinkLayerStats_1_3_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getLinkLayerStatsInternal_1_3,
+ hidl_status_cb);
+}
+
Return<void> WifiStaIface::startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) {
@@ -445,8 +452,13 @@
return createWifiStatusFromLegacyError(legacy_status);
}
-std::pair<WifiStatus, StaLinkLayerStats>
+std::pair<WifiStatus, V1_0::StaLinkLayerStats>
WifiStaIface::getLinkLayerStatsInternal() {
+ return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+WifiStaIface::getLinkLayerStatsInternal_1_3() {
legacy_hal::wifi_error legacy_status;
legacy_hal::LinkLayerStats legacy_stats;
std::tie(legacy_status, legacy_stats) =
@@ -454,7 +466,7 @@
if (legacy_status != legacy_hal::WIFI_SUCCESS) {
return {createWifiStatusFromLegacyError(legacy_status), {}};
}
- StaLinkLayerStats hidl_stats;
+ V1_3::StaLinkLayerStats hidl_stats;
if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
&hidl_stats)) {
return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
@@ -622,7 +634,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h
similarity index 94%
rename from wifi/1.2/default/wifi_sta_iface.h
rename to wifi/1.3/default/wifi_sta_iface.h
index 71cd17d..bc3090f 100644
--- a/wifi/1.2/default/wifi_sta_iface.h
+++ b/wifi/1.3/default/wifi_sta_iface.h
@@ -19,7 +19,7 @@
#include <android-base/macros.h>
#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.2/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
#include <wifi_system/interface_tool.h>
@@ -29,14 +29,14 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
/**
* HIDL interface object used to control a STA Iface instance.
*/
-class WifiStaIface : public V1_2::IWifiStaIface {
+class WifiStaIface : public V1_3::IWifiStaIface {
public:
WifiStaIface(const std::string& ifname,
const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -75,6 +75,8 @@
disableLinkLayerStatsCollection_cb hidl_status_cb) override;
Return<void> getLinkLayerStats(
getLinkLayerStats_cb hidl_status_cb) override;
+ Return<void> getLinkLayerStats_1_3(
+ getLinkLayerStats_1_3_cb hidl_status_cb) override;
Return<void> startRssiMonitoring(
uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
startRssiMonitoring_cb hidl_status_cb) override;
@@ -130,7 +132,9 @@
WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
WifiStatus disableLinkLayerStatsCollectionInternal();
- std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+ std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
+ std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+ getLinkLayerStatsInternal_1_3();
WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
int32_t min_rssi);
WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
@@ -163,7 +167,7 @@
};
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_status_util.cpp b/wifi/1.3/default/wifi_status_util.cpp
similarity index 98%
rename from wifi/1.2/default/wifi_status_util.cpp
rename to wifi/1.3/default/wifi_status_util.cpp
index dd37b6b..0a5bb13 100644
--- a/wifi/1.2/default/wifi_status_util.cpp
+++ b/wifi/1.3/default/wifi_status_util.cpp
@@ -19,7 +19,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
std::string legacyErrorToString(legacy_hal::wifi_error error) {
@@ -100,7 +100,7 @@
}
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.2/default/wifi_status_util.h b/wifi/1.3/default/wifi_status_util.h
similarity index 97%
rename from wifi/1.2/default/wifi_status_util.h
rename to wifi/1.3/default/wifi_status_util.h
index e9136b3..bc8baa9 100644
--- a/wifi/1.2/default/wifi_status_util.h
+++ b/wifi/1.3/default/wifi_status_util.h
@@ -24,7 +24,7 @@
namespace android {
namespace hardware {
namespace wifi {
-namespace V1_2 {
+namespace V1_3 {
namespace implementation {
using namespace android::hardware::wifi::V1_0;
@@ -37,7 +37,7 @@
WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
} // namespace implementation
-} // namespace V1_2
+} // namespace V1_3
} // namespace wifi
} // namespace hardware
} // namespace android
diff --git a/wifi/1.3/types.hal b/wifi/1.3/types.hal
new file mode 100644
index 0000000..4585ff3
--- /dev/null
+++ b/wifi/1.3/types.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi@1.3;
+
+import @1.0::StaLinkLayerRadioStats;
+import @1.0::StaLinkLayerIfaceStats;
+import @1.0::TimeStampInMs;
+
+struct StaLinkLayerRadioStats {
+ /**
+ * Baseline information as defined in HAL 1.0.
+ */
+ @1.0::StaLinkLayerRadioStats V1_0;
+
+ /**
+ * Total time for which the radio is awake due to NAN scan since boot or crash.
+ */
+ uint32_t onTimeInMsForNanScan;
+
+ /**
+ * Total time for which the radio is awake due to background scan since boot or crash.
+ */
+ uint32_t onTimeInMsForBgScan;
+
+ /**
+ * Total time for which the radio is awake due to roam scan since boot or crash.
+ */
+ uint32_t onTimeInMsForRoamScan;
+
+ /**
+ * Total time for which the radio is awake due to PNO scan since boot or crash.
+ */
+ uint32_t onTimeInMsForPnoScan;
+
+ /**
+ * Total time for which the radio is awake due to Hotspot 2.0 scans and GAS exchange since boot
+ * or crash.
+ */
+ uint32_t onTimeInMsForHs20Scan;
+};
+
+/**
+ * Link layer stats retrieved via |getLinkLayerStats|.
+ */
+struct StaLinkLayerStats {
+ StaLinkLayerIfaceStats iface;
+ vec<StaLinkLayerRadioStats> radios;
+ /**
+ * TimeStamp for each stats sample.
+ * This is the absolute milliseconds from boot when these stats were
+ * sampled.
+ */
+ TimeStampInMs timeStampInMs;
+};
\ No newline at end of file
diff --git a/wifi/1.2/default/OWNERS b/wifi/1.3/vts/OWNERS
similarity index 100%
copy from wifi/1.2/default/OWNERS
copy to wifi/1.3/vts/OWNERS
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..dbe77bd
--- /dev/null
+++ b/wifi/1.3/vts/functional/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_test {
+ name: "VtsHalWifiV1_3TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "VtsHalWifiV1_3TargetTest.cpp",
+ ],
+ static_libs: [
+ "VtsHalWifiV1_0TargetTestUtil",
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ ],
+}
diff --git a/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
new file mode 100644
index 0000000..b410a48
--- /dev/null
+++ b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 <android-base/logging.h>
+#include <android/hardware/wifi/1.3/IWifi.h>
+
+#include "wifi_hidl_test_utils.h"
+
+// Test environment for Wifi HIDL HAL.
+class WifiHidlEnvironment_1_3 : public WifiHidlEnvironment {
+ public:
+ // get the test environment singleton
+ static WifiHidlEnvironment_1_3* Instance() {
+ static WifiHidlEnvironment_1_3* instance = new WifiHidlEnvironment_1_3;
+ return instance;
+ }
+
+ virtual void registerTestServices() override {
+ registerTestService<android::hardware::wifi::V1_3::IWifi>();
+ }
+
+ private:
+ WifiHidlEnvironment_1_3() {}
+};
+
+WifiHidlEnvironment_1_3* gEnv = WifiHidlEnvironment_1_3::Instance();
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(gEnv);
+ ::testing::InitGoogleTest(&argc, argv);
+ gEnv->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp
new file mode 100644
index 0000000..d4170b6
--- /dev/null
+++ b/wifi/hostapd/1.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.wifi.hostapd@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IHostapd.hal",
+ "IHostapdCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.wifi.hostapd@1.0",
+ "android.hardware.wifi.supplicant@1.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
+
diff --git a/wifi/hostapd/1.1/IHostapd.hal b/wifi/hostapd/1.1/IHostapd.hal
new file mode 100644
index 0000000..4e59ffc
--- /dev/null
+++ b/wifi/hostapd/1.1/IHostapd.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi.hostapd@1.1;
+
+import @1.0::IHostapd;
+import @1.0::HostapdStatus;
+
+import IHostapdCallback;
+
+/**
+ * Top-level object for managing SoftAPs.
+ */
+interface IHostapd extends @1.0::IHostapd {
+ /**
+ * Register for callbacks from the hostapd service.
+ *
+ * These callbacks are invoked for global events that are not specific
+ * to any interface or network. Registration of multiple callback
+ * objects is supported. These objects must be deleted when the corresponding
+ * client process is dead.
+ *
+ * @param callback An instance of the |IHostapdCallback| HIDL interface
+ * object.
+ * @return status Status of the operation.
+ * Possible status codes:
+ * |HostapdStatusCode.SUCCESS|,
+ * |HostapdStatusCode.FAILURE_UNKNOWN|
+ */
+ registerCallback(IHostapdCallback callback)
+ generates (HostapdStatus status);
+};
diff --git a/wifi/hostapd/1.1/IHostapdCallback.hal b/wifi/hostapd/1.1/IHostapdCallback.hal
new file mode 100644
index 0000000..1d314fe
--- /dev/null
+++ b/wifi/hostapd/1.1/IHostapdCallback.hal
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi.hostapd@1.1;
+
+/**
+ * Top-level object for managing SoftAPs.
+ */
+interface IHostapdCallback {
+ /**
+ * Invoked when an asynchronous failure is encountered in one of the access
+ * points added via |IHostapd.addAccessPoint|.
+ *
+ * @param ifaceName Name of the interface.
+ */
+ oneway onFailure(string ifaceName);
+};