Merge "Added protections for RenderScript VTS tests." into oc-dev
diff --git a/audio/common/2.0/default/HidlUtils.cpp b/audio/common/2.0/default/HidlUtils.cpp
index 241ca90..79cb37c 100644
--- a/audio/common/2.0/default/HidlUtils.cpp
+++ b/audio/common/2.0/default/HidlUtils.cpp
@@ -28,6 +28,7 @@
using ::android::hardware::audio::common::V2_0::AudioPortType;
using ::android::hardware::audio::common::V2_0::AudioSource;
using ::android::hardware::audio::common::V2_0::AudioStreamType;
+using ::android::hardware::audio::common::V2_0::AudioUsage;
namespace android {
@@ -103,6 +104,9 @@
offload->durationMicroseconds = halOffload.duration_us;
offload->hasVideo = halOffload.has_video;
offload->isStreaming = halOffload.is_streaming;
+ offload->bitWidth = halOffload.bit_width;
+ offload->bufferSize = halOffload.offload_buffer_size;
+ offload->usage = static_cast<AudioUsage>(halOffload.usage);
}
void HidlUtils::audioOffloadInfoToHal(
diff --git a/automotive/evs/1.0/default/EvsEnumerator.cpp b/automotive/evs/1.0/default/EvsEnumerator.cpp
index 731e21b..b25d418 100644
--- a/automotive/evs/1.0/default/EvsEnumerator.cpp
+++ b/automotive/evs/1.0/default/EvsEnumerator.cpp
@@ -99,7 +99,7 @@
}
// Construct a camera instance for the caller
- pActiveCamera = new EvsCamera(cameraId);
+ pActiveCamera = new EvsCamera(cameraId.c_str());
pRecord->activeInstance = pActiveCamera;
if (pActiveCamera == nullptr) {
ALOGE("Failed to allocate new EvsCamera object for %s\n", cameraId.c_str());
diff --git a/automotive/evs/1.0/default/service.cpp b/automotive/evs/1.0/default/service.cpp
index 1b64e44..d4181b9 100644
--- a/automotive/evs/1.0/default/service.cpp
+++ b/automotive/evs/1.0/default/service.cpp
@@ -19,9 +19,9 @@
#include <unistd.h>
#include <hidl/HidlTransportSupport.h>
+#include <log/log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include <utils/Log.h>
#include "ServiceNames.h"
#include "EvsEnumerator.h"
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.cpp b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
index 01d9a0e..58c2f26 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.cpp
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.cpp
@@ -23,7 +23,6 @@
#include <android/log.h>
#include <cutils/native_handle.h>
-#include <ui/GraphicBufferMapper.h>
#include <ui/GraphicBuffer.h>
#include <algorithm> // std::min
@@ -135,11 +134,7 @@
// Local flag we use to keep track of when the stream is stopping
bool timeToStop = false;
- // TODO: Why do we get a gralloc crash if we don't clone the buffer here?
- BufferDesc buffer(bufferArg);
- ALOGD("Clone the received frame as %p", buffer.memHandle.getNativeHandle());
-
- if (buffer.memHandle.getNativeHandle() == nullptr) {
+ if (bufferArg.memHandle.getNativeHandle() == nullptr) {
// Signal that the last frame has been received and the stream is stopped
timeToStop = true;
} else {
@@ -157,13 +152,8 @@
printf("Didn't get target buffer - frame lost\n");
ALOGE("Didn't get requested output buffer -- skipping this frame.");
} else {
- // In order for the handles passed through HIDL and stored in the BufferDesc to
- // be lockable, we must register them with GraphicBufferMapper
- registerBufferHelper(tgtBuffer);
- registerBufferHelper(buffer);
-
// Copy the contents of the of buffer.memHandle into tgtBuffer
- copyBufferContents(tgtBuffer, buffer);
+ copyBufferContents(tgtBuffer, bufferArg);
// Send the target buffer back for display
Return <EvsResult> result = mDisplay->returnTargetBufferForDisplay(tgtBuffer);
@@ -183,10 +173,6 @@
mFramesDisplayed++;
mLock.unlock();
}
-
- // Now tell GraphicBufferMapper we won't be using these handles anymore
- unregisterBufferHelper(tgtBuffer);
- unregisterBufferHelper(buffer);
}
}
@@ -233,24 +219,22 @@
const unsigned height = std::min(tgtBuffer.height,
srcBuffer.height);
- android::GraphicBufferMapper &mapper = android::GraphicBufferMapper::get();
-
+ sp<android::GraphicBuffer> tgt = new android::GraphicBuffer(
+ tgtBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+ tgtBuffer.width, tgtBuffer.height, tgtBuffer.format, 1, tgtBuffer.usage,
+ tgtBuffer.stride);
+ sp<android::GraphicBuffer> src = new android::GraphicBuffer(
+ srcBuffer.memHandle, android::GraphicBuffer::CLONE_HANDLE,
+ srcBuffer.width, srcBuffer.height, srcBuffer.format, 1, srcBuffer.usage,
+ srcBuffer.stride);
// Lock our source buffer for reading
unsigned char* srcPixels = nullptr;
- mapper.registerBuffer(srcBuffer.memHandle);
- mapper.lock(srcBuffer.memHandle,
- GRALLOC_USAGE_SW_READ_OFTEN,
- android::Rect(width, height),
- (void **) &srcPixels);
+ src->lock(GRALLOC_USAGE_SW_READ_OFTEN, (void**)&srcPixels);
// Lock our target buffer for writing
unsigned char* tgtPixels = nullptr;
- mapper.registerBuffer(tgtBuffer.memHandle);
- mapper.lock(tgtBuffer.memHandle,
- GRALLOC_USAGE_SW_WRITE_OFTEN,
- android::Rect(width, height),
- (void **) &tgtPixels);
+ tgt->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)&tgtPixels);
if (srcPixels && tgtPixels) {
for (unsigned row = 0; row < height; row++) {
@@ -267,45 +251,11 @@
}
if (srcPixels) {
- mapper.unlock(srcBuffer.memHandle);
+ src->unlock();
}
if (tgtPixels) {
- mapper.unlock(tgtBuffer.memHandle);
+ tgt->unlock();
}
- mapper.unregisterBuffer(srcBuffer.memHandle);
- mapper.unregisterBuffer(tgtBuffer.memHandle);
return success;
}
-
-
-void FrameHandler::registerBufferHelper(const BufferDesc& buffer)
-{
- // In order for the handles passed through HIDL and stored in the BufferDesc to
- // be lockable, we must register them with GraphicBufferMapper.
- // If the device upon which we're running supports gralloc1, we could just call
- // registerBuffer directly with the handle. But that call is broken for gralloc0 devices
- // (which we care about, at least for now). As a result, we have to synthesize a GraphicBuffer
- // object around the buffer handle in order to make a call to the overloaded alternate
- // version of the registerBuffer call that does happen to work on gralloc0 devices.
-#if REGISTER_BUFFER_ALWAYS_WORKS
- android::GraphicBufferMapper::get().registerBuffer(buffer.memHandle);
-#else
- android::sp<android::GraphicBuffer> pGfxBuff = new android::GraphicBuffer(
- buffer.width, buffer.height, buffer.format,
- 1, /* we always use exactly one layer */
- buffer.usage, buffer.stride,
- const_cast<native_handle_t*>(buffer.memHandle.getNativeHandle()),
- false /* GraphicBuffer should not try to free the handle */
- );
-
- android::GraphicBufferMapper::get().registerBuffer(pGfxBuff.get());
-#endif
-}
-
-
-void FrameHandler::unregisterBufferHelper(const BufferDesc& buffer)
-{
- // Now tell GraphicBufferMapper we won't be using these handles anymore
- android::GraphicBufferMapper::get().unregisterBuffer(buffer.memHandle);
-}
diff --git a/automotive/evs/1.0/vts/functional/FrameHandler.h b/automotive/evs/1.0/vts/functional/FrameHandler.h
index d5c3f6b..17a3980 100644
--- a/automotive/evs/1.0/vts/functional/FrameHandler.h
+++ b/automotive/evs/1.0/vts/functional/FrameHandler.h
@@ -68,8 +68,6 @@
// Local implementation details
bool copyBufferContents(const BufferDesc& tgtBuffer, const BufferDesc& srcBuffer);
- void registerBufferHelper(const BufferDesc& buffer);
- void unregisterBufferHelper(const BufferDesc& buffer);
// Values initialized as startup
android::sp <IEvsCamera> mCamera;
diff --git a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
index 6a0ae48..50b6581 100644
--- a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
@@ -37,10 +37,10 @@
#include <string.h>
#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/ProcessState.h>
+#include <log/log.h>
#include <utils/Errors.h>
#include <utils/StrongPointer.h>
-#include <utils/Log.h>
-#include <hwbinder/ProcessState.h>
#include <android/log.h>
#include <android/hardware/automotive/evs/1.0/IEvsCamera.h>
diff --git a/automotive/vehicle/2.0/default/Android.mk b/automotive/vehicle/2.0/default/Android.mk
index b8535bd..3c56159 100644
--- a/automotive/vehicle/2.0/default/Android.mk
+++ b/automotive/vehicle/2.0/default/Android.mk
@@ -25,6 +25,7 @@
common/src/SubscriptionManager.cpp \
common/src/VehicleHalManager.cpp \
common/src/VehicleObjectPool.cpp \
+ common/src/VehiclePropertyStore.cpp \
common/src/VehicleUtils.cpp \
LOCAL_C_INCLUDES := \
@@ -72,9 +73,10 @@
LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
LOCAL_SRC_FILES:= \
- impl/vhal_v2_0/DefaultVehicleHal.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/SocketComm.cpp \
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/impl/vhal_v2_0
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 95057cc..e6d292e 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -21,14 +21,16 @@
#include <iostream>
#include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/EmulatedVehicleHal.h>
using namespace android;
using namespace android::hardware;
using namespace android::hardware::automotive::vehicle::V2_0;
int main(int /* argc */, char* /* argv */ []) {
- auto hal = std::make_unique<impl::DefaultVehicleHal>();
+ auto store = std::make_unique<VehiclePropertyStore>();
+ auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
+ auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
auto service = std::make_unique<VehicleHalManager>(hal.get());
configureRpcThreadpool(1, true /* callerWillJoin */);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
new file mode 100644
index 0000000..eda94b7
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehiclePropertyStore.h
@@ -0,0 +1,104 @@
+/*
+ * 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_PropertyDb_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
+
+#include <cstdint>
+#include <unordered_map>
+#include <memory>
+#include <mutex>
+
+#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+/**
+ * Encapsulates work related to storing and accessing configuration, storing and modifying
+ * vehicle property values.
+ *
+ * VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
+ * to get value for all areas for particular property.
+ *
+ * This class is thread-safe, however it uses blocking synchronization across all methods.
+ */
+class VehiclePropertyStore {
+public:
+ /* Function that used to calculate unique token for given VehiclePropValue */
+ using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;
+
+private:
+ struct RecordConfig {
+ VehiclePropConfig propConfig;
+ TokenFunction tokenFunction;
+ };
+
+ struct RecordId {
+ int32_t prop;
+ int32_t area;
+ int64_t token;
+
+ bool operator==(const RecordId& other) const;
+ bool operator<(const RecordId& other) const;
+ };
+
+ using PropertyMap = std::map<RecordId, VehiclePropValue>;
+ using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>;
+
+public:
+ void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr);
+
+ /* Stores provided value. Returns true if value was written returns false if config for
+ * example wasn't registered. */
+ bool writeValue(const VehiclePropValue& propValue);
+
+ void removeValue(const VehiclePropValue& propValue);
+ void removeValuesForProperty(int32_t propId);
+
+ std::vector<VehiclePropValue> readAllValues() const;
+ std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const;
+ std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const;
+ std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0,
+ int64_t token = 0) const;
+
+ std::vector<VehiclePropConfig> getAllConfigs() const;
+ const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
+ const VehiclePropConfig* getConfigOrDie(int32_t propId) const;
+
+private:
+ RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const;
+ const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const;
+ PropertyMapRange findRangeLocked(int32_t propId) const;
+
+private:
+ using MuxGuard = std::lock_guard<std::mutex>;
+ mutable std::mutex mLock;
+ std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;
+
+ PropertyMap mPropertyValues; // Sorted map of RecordId : VehiclePropValue.
+};
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif //android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
diff --git a/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
new file mode 100644
index 0000000..2c3ebfc
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/VehiclePropertyStore.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "VehiclePropertyStore"
+#include <log/log.h>
+
+#include <common/include/vhal_v2_0/VehicleUtils.h>
+#include "VehiclePropertyStore.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
+ return prop == other.prop && area == other.area && token == other.token;
+}
+
+bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const {
+ return prop < other.prop
+ || (prop == other.prop && area < other.area)
+ || (prop == other.prop && area == other.area && token < other.token);
+}
+
+void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
+ VehiclePropertyStore::TokenFunction tokenFunc) {
+ MuxGuard g(mLock);
+ mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
+}
+
+bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+ MuxGuard g(mLock);
+ if (!mConfigs.count(propValue.prop)) return false;
+
+ RecordId recId = getRecordIdLocked(propValue);
+ VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
+ if (valueToUpdate == nullptr) {
+ mPropertyValues.insert({ recId, propValue });
+ } else {
+ valueToUpdate->timestamp = propValue.timestamp;
+ valueToUpdate->value = propValue.value;
+ }
+ return true;
+}
+
+void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
+ MuxGuard g(mLock);
+ RecordId recId = getRecordIdLocked(propValue);
+ auto it = mPropertyValues.find(recId);
+ if (it != mPropertyValues.end()) {
+ mPropertyValues.erase(it);
+ }
+}
+
+void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
+ MuxGuard g(mLock);
+ auto range = findRangeLocked(propId);
+ mPropertyValues.erase(range.first, range.second);
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
+ MuxGuard g(mLock);
+ std::vector<VehiclePropValue> allValues;
+ allValues.reserve(mPropertyValues.size());
+ for (auto&& it : mPropertyValues) {
+ allValues.push_back(it.second);
+ }
+ return allValues;
+}
+
+std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
+ std::vector<VehiclePropValue> values;
+ MuxGuard g(mLock);
+ auto range = findRangeLocked(propId);
+ for (auto it = range.first; it != range.second; ++it) {
+ values.push_back(it->second);
+ }
+
+ return values;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+ const VehiclePropValue& request) const {
+ MuxGuard g(mLock);
+ RecordId recId = getRecordIdLocked(request);
+ const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+ return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
+ int32_t prop, int32_t area, int64_t token) const {
+ RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
+ MuxGuard g(mLock);
+ const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
+ return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
+}
+
+
+std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
+ MuxGuard g(mLock);
+ std::vector<VehiclePropConfig> configs;
+ configs.reserve(mConfigs.size());
+ for (auto&& recordConfigIt: mConfigs) {
+ configs.push_back(recordConfigIt.second.propConfig);
+ }
+ return configs;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
+ MuxGuard g(mLock);
+ auto recordConfigIt = mConfigs.find(propId);
+ return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
+}
+
+const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
+ auto cfg = getConfigOrNull(propId);
+ if (!cfg) {
+ ALOGW("%s: config not found for property: 0x%x", __func__, propId);
+ abort();
+ }
+ return cfg;
+}
+
+VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
+ const VehiclePropValue& valuePrototype) const {
+ RecordId recId = {
+ .prop = valuePrototype.prop,
+ .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
+ .token = 0
+ };
+
+ auto it = mConfigs.find(recId.prop);
+ if (it == mConfigs.end()) return {};
+
+ if (it->second.tokenFunction != nullptr) {
+ recId.token = it->second.tokenFunction(valuePrototype);
+ }
+ return recId;
+}
+
+const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
+ const VehiclePropertyStore::RecordId& recId) const {
+ auto it = mPropertyValues.find(recId);
+ return it == mPropertyValues.end() ? nullptr : &it->second;
+}
+
+VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
+ // Based on the fact that mPropertyValues is a sorted map by RecordId.
+ auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
+ auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });
+
+ return PropertyMapRange { beginIt, endIt };
+}
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
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 545de39..bf16a9b 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
@@ -33,176 +33,257 @@
toInt(VehicleProperty::HVAC_FAN_DIRECTION),
};
-const VehiclePropConfig kVehicleProperties[] = {
+struct ConfigDeclaration {
+ VehiclePropConfig config;
+
+ /* This value will be used as an initial value for the property. If this field is specified for
+ * property that supports multiple areas then it will be used for all areas unless particular
+ * area is overridden in initialAreaValue field. */
+ VehiclePropValue::RawValue initialValue;
+ /* Use initialAreaValues if it is necessary to specify different values per each area. */
+ std::map<int32_t, VehiclePropValue::RawValue> initialAreaValues;
+};
+
+const ConfigDeclaration kVehicleProperties[] {
{
- .prop = toInt(VehicleProperty::INFO_MAKE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
+ .config = {
+ .prop = toInt(VehicleProperty::INFO_MAKE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ },
+ .initialValue = { .stringValue = "Toy Vehicle" }
+ },
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .floatValues = {0.0f} }
},
{
- .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .config = {
+ .prop = toInt(VehicleProperty::CURRENT_GEAR),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
},
{
- .prop = toInt(VehicleProperty::CURRENT_GEAR),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .config = {
+ .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = {1} }
},
{
- .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .config = {
+ .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = {0} }
},
{
- .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_POWER_ON),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+ // TODO(bryaneyler): Ideally, this is generated dynamically from
+ // kHvacPowerProperties.
+ .configString = "0x12400500,0x12400501" // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
+ },
+ .initialValue = { .int32Values = {1} }
},
{
- .prop = toInt(VehicleProperty::HVAC_POWER_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
- // TODO(bryaneyler): Ideally, this is generated dynamically from
- // kHvacPowerProperties.
- .configString = "0x12400500,0x12400501" // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_DEFROSTER),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas =
+ VehicleAreaWindow::FRONT_WINDSHIELD
+ | VehicleAreaWindow::REAR_WINDSHIELD
+ },
+ .initialValue = { .int32Values = {0} } // Will be used for all areas.
},
{
- .prop = toInt(VehicleProperty::HVAC_DEFROSTER),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas =
- VehicleAreaWindow::FRONT_WINDSHIELD
- | VehicleAreaWindow::REAR_WINDSHIELD
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ },
+ .initialValue = { .int32Values = {1} }
},
{
- .prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_AC_ON),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ },
+ .initialValue = { .int32Values = {1} }
},
{
- .prop = toInt(VehicleProperty::HVAC_AC_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_AUTO_ON),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ },
+ .initialValue = { .int32Values = {1} }
},
{
- .prop = toInt(VehicleProperty::HVAC_AUTO_ON),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+ .areaConfigs = {
+ VehicleAreaConfig {
+ .areaId = toInt(VehicleAreaZone::ROW_1),
+ .minInt32Value = 1,
+ .maxInt32Value = 7
+ }
+ }
+ },
+ .initialValue = { .int32Values = {3} }
},
{
- .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
- .areaConfigs = {
- VehicleAreaConfig {
- .areaId = toInt(VehicleAreaZone::ROW_1),
- .minInt32Value = 1,
- .maxInt32Value = 7
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+ },
+ .initialValue = { .int32Values = { toInt(VehicleHvacFanDirection::FACE) } }
+ },
+
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .supportedAreas =
+ VehicleAreaZone::ROW_1_LEFT
+ | VehicleAreaZone::ROW_1_RIGHT,
+ .areaConfigs = {
+ VehicleAreaConfig {
+ .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+ .minFloatValue = 16,
+ .maxFloatValue = 32,
+ },
+ VehicleAreaConfig {
+ .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+ .minFloatValue = 16,
+ .maxFloatValue = 32,
+ }
+ }
+ },
+ .initialAreaValues = {
+ {
+ toInt(VehicleAreaZone::ROW_1_LEFT),
+ { .floatValues = {16} }
+ }, {
+ toInt(VehicleAreaZone::ROW_1_RIGHT),
+ { .floatValues = {20} }
}
}
},
{
- .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+ .config = {
+ .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
+ .access = VehiclePropertyAccess::READ,
+ // TODO(bryaneyler): Support ON_CHANGE as well.
+ .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+ .minSampleRate = 1.0f,
+ .maxSampleRate = 2.0f,
+ },
+ .initialValue = { .floatValues = {25.0f} }
},
{
- .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas =
- VehicleAreaZone::ROW_1_LEFT
- | VehicleAreaZone::ROW_1_RIGHT,
- .areaConfigs = {
- VehicleAreaConfig {
- .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
- .minFloatValue = 16,
- .maxFloatValue = 32,
- },
- VehicleAreaConfig {
- .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
- .minFloatValue = 16,
- .maxFloatValue = 32,
+ .config = {
+ .prop = toInt(VehicleProperty::NIGHT_MODE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = {0} }
+ },
+
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::DRIVING_STATUS),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = { toInt(VehicleDrivingStatus::UNRESTRICTED) } }
+ },
+
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::GEAR_SELECTION),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
+ },
+
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::STATIC,
+ },
+ .initialValue = { .floatValues = { 123000.0f } } // In Milliliters
+ },
+
+ {
+ .config = {
+ .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {
+ VehicleAreaConfig {
+ .minInt32Value = 0,
+ .maxInt32Value = 10
+ }
}
- }
+ },
+ .initialValue = { .int32Values = {7} }
},
{
- .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
- .access = VehiclePropertyAccess::READ,
- // TODO(bryaneyler): Support ON_CHANGE as well.
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 1.0f,
- .maxSampleRate = 2.0f,
+ .config = {
+ .prop = toInt(VehicleProperty::IGNITION_STATE),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ },
+ .initialValue = { .int32Values = { toInt(VehicleIgnitionState::ON) } }
},
{
- .prop = toInt(VehicleProperty::NIGHT_MODE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
-
- {
- .prop = toInt(VehicleProperty::DRIVING_STATUS),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
-
- {
- .prop = toInt(VehicleProperty::GEAR_SELECTION),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
-
- {
- .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::STATIC,
- },
-
- {
- .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .areaConfigs = {
- VehicleAreaConfig {
- .minInt32Value = 0,
- .maxInt32Value = 10
- }
- }
- },
-
- {
- .prop = toInt(VehicleProperty::IGNITION_STATE),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- },
-
- {
- .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
- .access = VehiclePropertyAccess::READ,
- .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
- .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
- .maxSampleRate = 10, // 10 Hz, every 100 ms
+ .config = {
+ .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
+ .access = VehiclePropertyAccess::READ,
+ .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+ .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
+ .maxSampleRate = 10, // 10 Hz, every 100 ms
+ },
+ .initialValue = { .floatValues = {101.0f} }
}
};
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
deleted file mode 100644
index 03a65f3..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * Copyright (C) 2016 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 "DefaultVehicleHal_v2_0"
-#include <android/log.h>
-
-#include <algorithm>
-#include <android-base/properties.h>
-#include <cstdio>
-
-#include "DefaultVehicleHal.h"
-#include "PipeComm.h"
-#include "SocketComm.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-void DefaultVehicleHal::doGetConfig(emulator::EmulatorMessage& rxMsg,
- emulator::EmulatorMessage& respMsg) {
- std::vector<VehiclePropConfig> configs = listProperties();
- emulator::VehiclePropGet getProp = rxMsg.prop(0);
-
- respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
- respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
-
- for (auto& config : configs) {
- // Find the config we are looking for
- if (config.prop == getProp.prop()) {
- emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
- populateProtoVehicleConfig(protoCfg, config);
- respMsg.set_status(emulator::RESULT_OK);
- break;
- }
- }
-}
-
-void DefaultVehicleHal::doGetConfigAll(emulator::EmulatorMessage& /* rxMsg */,
- emulator::EmulatorMessage& respMsg) {
- std::vector<VehiclePropConfig> configs = listProperties();
-
- respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
- respMsg.set_status(emulator::RESULT_OK);
-
- for (auto& config : configs) {
- emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
- populateProtoVehicleConfig(protoCfg, config);
- }
-}
-
-void DefaultVehicleHal::doGetProperty(emulator::EmulatorMessage& rxMsg,
- emulator::EmulatorMessage& respMsg) {
- int32_t areaId = 0;
- emulator::VehiclePropGet getProp = rxMsg.prop(0);
- int32_t propId = getProp.prop();
- emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
- VehiclePropValue* val;
-
- respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
-
- if (getProp.has_area_id()) {
- areaId = getProp.area_id();
- }
-
- {
- std::lock_guard<std::mutex> lock(mPropsMutex);
-
- val = getVehiclePropValueLocked(propId, areaId);
- if (val != nullptr) {
- emulator::VehiclePropValue* protoVal = respMsg.add_value();
- populateProtoVehiclePropValue(protoVal, val);
- status = emulator::RESULT_OK;
- }
- }
-
- respMsg.set_status(status);
-}
-
-void DefaultVehicleHal::doGetPropertyAll(emulator::EmulatorMessage& /* rxMsg */,
- emulator::EmulatorMessage& respMsg) {
- respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
- respMsg.set_status(emulator::RESULT_OK);
-
- {
- std::lock_guard<std::mutex> lock(mPropsMutex);
-
- for (auto& prop : mProps) {
- emulator::VehiclePropValue* protoVal = respMsg.add_value();
- populateProtoVehiclePropValue(protoVal, prop.second->get());
- }
- }
-}
-
-void DefaultVehicleHal::doSetProperty(emulator::EmulatorMessage& rxMsg,
- emulator::EmulatorMessage& respMsg) {
- emulator::VehiclePropValue protoVal = rxMsg.value(0);
- VehiclePropValue val;
-
- respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
-
- val.prop = protoVal.prop();
- val.areaId = protoVal.area_id();
- val.timestamp = elapsedRealtimeNano();
-
- // Copy value data if it is set. This automatically handles complex data types if needed.
- if (protoVal.has_string_value()) {
- val.value.stringValue = protoVal.string_value().c_str();
- }
-
- if (protoVal.has_bytes_value()) {
- std::vector<uint8_t> tmp(protoVal.bytes_value().begin(), protoVal.bytes_value().end());
- val.value.bytes = tmp;
- }
-
- if (protoVal.int32_values_size() > 0) {
- std::vector<int32_t> int32Values = std::vector<int32_t>(protoVal.int32_values_size());
- for (int i=0; i<protoVal.int32_values_size(); i++) {
- int32Values[i] = protoVal.int32_values(i);
- }
- val.value.int32Values = int32Values;
- }
-
- if (protoVal.int64_values_size() > 0) {
- std::vector<int64_t> int64Values = std::vector<int64_t>(protoVal.int64_values_size());
- for (int i=0; i<protoVal.int64_values_size(); i++) {
- int64Values[i] = protoVal.int64_values(i);
- }
- val.value.int64Values = int64Values;
- }
-
- if (protoVal.float_values_size() > 0) {
- std::vector<float> floatValues = std::vector<float>(protoVal.float_values_size());
- for (int i=0; i<protoVal.float_values_size(); i++) {
- floatValues[i] = protoVal.float_values(i);
- }
- val.value.floatValues = floatValues;
- }
-
- if (updateProperty(val) == StatusCode::OK) {
- // Send property up to VehicleHalManager via callback
- auto& pool = *getValuePool();
- VehiclePropValuePtr v = pool.obtain(val);
-
- doHalEvent(std::move(v));
- respMsg.set_status(emulator::RESULT_OK);
- } else {
- respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
- }
-}
-
-// This function should only be called while mPropsMutex is locked.
-VehiclePropValue* DefaultVehicleHal::getVehiclePropValueLocked(int32_t propId, int32_t areaId) {
- if (getPropArea(propId) == VehicleArea::GLOBAL) {
- // In VehicleHal, global properties have areaId = -1. We use 0.
- areaId = 0;
- }
-
- auto prop = mProps.find(std::make_pair(propId, areaId));
- if (prop != mProps.end()) {
- return prop->second->get();
- }
- ALOGW("%s: Property not found: propId = 0x%x, areaId = 0x%x", __func__, propId, areaId);
- return nullptr;
-}
-
-void DefaultVehicleHal::parseRxProtoBuf(std::vector<uint8_t>& msg) {
- emulator::EmulatorMessage rxMsg;
- emulator::EmulatorMessage respMsg;
-
- if (rxMsg.ParseFromArray(msg.data(), 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()));
- }
-}
-
-// Copies internal VehiclePropConfig data structure to protobuf VehiclePropConfig
-void DefaultVehicleHal::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
- const VehiclePropConfig& cfg) {
- protoCfg->set_prop(cfg.prop);
- protoCfg->set_access(toInt(cfg.access));
- protoCfg->set_change_mode(toInt(cfg.changeMode));
- protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
-
- if (!isGlobalProp(cfg.prop)) {
- protoCfg->set_supported_areas(cfg.supportedAreas);
- }
-
- for (auto& configElement : cfg.configArray) {
- protoCfg->add_config_array(configElement);
- }
-
- if (cfg.configString.size() > 0) {
- protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
- }
-
- // Populate the min/max values based on property type
- switch (getPropType(cfg.prop)) {
- case VehiclePropertyType::STRING:
- case VehiclePropertyType::BOOLEAN:
- case VehiclePropertyType::INT32_VEC:
- case VehiclePropertyType::FLOAT_VEC:
- case VehiclePropertyType::BYTES:
- case VehiclePropertyType::COMPLEX:
- // Do nothing. These types don't have min/max values
- break;
- case VehiclePropertyType::INT64:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
- aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
- }
- break;
- case VehiclePropertyType::FLOAT:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
- aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
- }
- break;
- case VehiclePropertyType::INT32:
- if (cfg.areaConfigs.size() > 0) {
- emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
- aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
- aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
- }
- break;
- default:
- ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
- break;
- }
-
- protoCfg->set_min_sample_rate(cfg.minSampleRate);
- protoCfg->set_max_sample_rate(cfg.maxSampleRate);
-}
-
-// Copies internal VehiclePropValue data structure to protobuf VehiclePropValue
-void DefaultVehicleHal::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
- const VehiclePropValue* val) {
- protoVal->set_prop(val->prop);
- protoVal->set_value_type(toInt(getPropType(val->prop)));
- protoVal->set_timestamp(val->timestamp);
- protoVal->set_area_id(val->areaId);
-
- // Copy value data if it is set.
- // - for bytes and strings, this is indicated by size > 0
- // - for int32, int64, and float, copy the values if vectors have data
- if (val->value.stringValue.size() > 0) {
- protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
- }
-
- if (val->value.bytes.size() > 0) {
- protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
- }
-
- for (auto& int32Value : val->value.int32Values) {
- protoVal->add_int32_values(int32Value);
- }
-
- for (auto& int64Value : val->value.int64Values) {
- protoVal->add_int64_values(int64Value);
- }
-
- for (auto& floatValue : val->value.floatValues) {
- protoVal->add_float_values(floatValue);
- }
-}
-
-void DefaultVehicleHal::rxMsg() {
- int numBytes = 0;
-
- while (mExit == 0) {
- 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: numBytes=%d, msgSize=%d", __func__, numBytes,
- static_cast<int32_t>(msg.size()));
- break;
- }
- }
-}
-
-void DefaultVehicleHal::rxThread() {
- bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
-
- if (isEmulator) {
- // Initialize pipe to Emulator
- mComm.reset(new PipeComm);
- } else {
- // Initialize socket over ADB
- mComm.reset(new SocketComm);
- }
-
- int retVal = mComm->open();
-
- if (retVal == 0) {
- // Comms are properly opened
- while (mExit == 0) {
- retVal = mComm->connect();
-
- if (retVal >= 0) {
- rxMsg();
- }
-
- // Check every 100ms for a new connection
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
- }
-}
-
-// This function sets the default value of a property if we are interested in setting it.
-// TODO: Co-locate the default values with the configuration structure, to make it easier to
-// add new properties and their defaults.
-void DefaultVehicleHal::setDefaultValue(VehiclePropValue* prop) {
- switch (prop->prop) {
- case toInt(VehicleProperty::INFO_MAKE):
- prop->value.stringValue = "Default Car";
- break;
- case toInt(VehicleProperty::PERF_VEHICLE_SPEED):
- prop->value.floatValues[0] = 0;
- break;
- case toInt(VehicleProperty::CURRENT_GEAR):
- prop->value.int32Values[0] = toInt(VehicleGear::GEAR_PARK);
- break;
- case toInt(VehicleProperty::PARKING_BRAKE_ON):
- prop->value.int32Values[0] = 1;
- break;
- case toInt(VehicleProperty::FUEL_LEVEL_LOW):
- prop->value.int32Values[0] = 0;
- break;
- case toInt(VehicleProperty::HVAC_POWER_ON):
- prop->value.int32Values[0] = 1;
- break;
- case toInt(VehicleProperty::HVAC_DEFROSTER):
- prop->value.int32Values[0] = 0;
- break;
- case toInt(VehicleProperty::HVAC_RECIRC_ON):
- prop->value.int32Values[0] = 1;
- break;
- case toInt(VehicleProperty::HVAC_AC_ON):
- prop->value.int32Values[0] = 1;
- break;
- case toInt(VehicleProperty::HVAC_AUTO_ON):
- prop->value.int32Values[0] = 1;
- break;
- case toInt(VehicleProperty::HVAC_FAN_SPEED):
- prop->value.int32Values[0] = 3;
- break;
- case toInt(VehicleProperty::HVAC_FAN_DIRECTION):
- prop->value.int32Values[0] = toInt(VehicleHvacFanDirection::FACE);
- break;
- case toInt(VehicleProperty::HVAC_TEMPERATURE_SET):
- prop->value.floatValues[0] = 16;
- break;
- case toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE):
- prop->value.floatValues[0] = 25;
- break;
- case toInt(VehicleProperty::NIGHT_MODE):
- prop->value.int32Values[0] = 0;
- break;
- case toInt(VehicleProperty::DRIVING_STATUS):
- prop->value.int32Values[0] = toInt(VehicleDrivingStatus::UNRESTRICTED);
- break;
- case toInt(VehicleProperty::GEAR_SELECTION):
- prop->value.int32Values[0] = toInt(VehicleGear::GEAR_PARK);
- break;
- case toInt(VehicleProperty::INFO_FUEL_CAPACITY):
- prop->value.floatValues[0] = 123000.0f; // In milliliters
- break;
- case toInt(VehicleProperty::ENGINE_OIL_TEMP):
- prop->value.floatValues[0] = 101;
- break;
- case toInt(VehicleProperty::DISPLAY_BRIGHTNESS):
- prop->value.int32Values[0] = 7;
- break;
- case toInt(VehicleProperty::IGNITION_STATE):
- prop->value.int32Values[0] = toInt(VehicleIgnitionState::ON);
- break;
- default:
- ALOGW("%s: propId=0x%x not found", __func__, prop->prop);
- break;
- }
-}
-
-// Transmit a reply back to the emulator
-void DefaultVehicleHal::txMsg(emulator::EmulatorMessage& txMsg) {
- int numBytes = txMsg.ByteSize();
- std::vector<uint8_t> msg(numBytes);
-
- if (txMsg.SerializeToArray(msg.data(), msg.size())) {
- int retVal = 0;
-
- // Send the message
- if (mExit == 0) {
- mComm->write(msg);
- }
-
- if (retVal < 0) {
- ALOGE("%s: Failed to tx message: retval=%d, errno=%d", __func__, retVal, errno);
- }
- } else {
- ALOGE("%s: SerializeToString failed!", __func__);
- }
-}
-
-// Updates the property value held in the HAL
-StatusCode DefaultVehicleHal::updateProperty(const VehiclePropValue& propValue) {
- auto propId = propValue.prop;
- auto areaId = propValue.areaId;
- StatusCode status = StatusCode::INVALID_ARG;
-
- {
- std::lock_guard<std::mutex> lock(mPropsMutex);
-
- VehiclePropValue* internalPropValue = getVehiclePropValueLocked(propId, areaId);
- if (internalPropValue != nullptr) {
- internalPropValue->value = propValue.value;
- internalPropValue->timestamp = propValue.timestamp;
- status = StatusCode::OK;
- }
- }
- return status;
-}
-
-VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
- const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
- auto areaId = requestedPropValue.areaId;
- auto& pool = *getValuePool();
- auto propId = requestedPropValue.prop;
- StatusCode status;
- VehiclePropValuePtr v = nullptr;
-
- switch (propId) {
- default:
- {
- std::lock_guard<std::mutex> lock(mPropsMutex);
-
- VehiclePropValue *internalPropValue = getVehiclePropValueLocked(propId, areaId);
- if (internalPropValue != nullptr) {
- v = pool.obtain(*internalPropValue);
- }
- }
-
- if (v != nullptr) {
- status = StatusCode::OK;
- } else {
- status = StatusCode::INVALID_ARG;
- }
- break;
- }
-
- *outStatus = status;
- return v;
-}
-
-StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
- auto propId = propValue.prop;
- StatusCode status;
- switch (propId) {
- default:
- if (mHvacPowerProps.count(propId)) {
- std::lock_guard<std::mutex> lock(mPropsMutex);
- auto hvacPowerOn = getVehiclePropValueLocked(toInt(VehicleProperty::HVAC_POWER_ON),
- toInt(VehicleAreaZone::ROW_1));
-
- if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
- && hvacPowerOn->value.int32Values[0] == 0) {
- status = StatusCode::NOT_AVAILABLE;
- break;
- }
- }
- status = updateProperty(propValue);
- if (status == StatusCode::OK) {
- // Send property update to emulator
- 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);
- }
- break;
- }
-
- return status;
-}
-
-V2_0::StatusCode DefaultVehicleHal::addCustomProperty(int32_t property,
- std::unique_ptr<CustomVehiclePropertyHandler>&& handler) {
- mProps[std::make_pair(property, 0)] = std::move(handler);
- ALOGW("%s: Added custom property: propId = 0x%x", __func__, property);
- return StatusCode::OK;
-}
-
-// Parse supported properties list and generate vector of property values to hold current values.
-void DefaultVehicleHal::onCreate() {
- // Initialize member variables
- mExit = 0;
-
- for (auto& prop : kHvacPowerProperties) {
- mHvacPowerProps.insert(prop);
- }
-
- // Get the list of configurations supported by this HAL
- std::vector<VehiclePropConfig> configs = listProperties();
-
- for (auto& cfg : configs) {
- VehiclePropertyType propType = getPropType(cfg.prop);
- int32_t supportedAreas = cfg.supportedAreas;
- int32_t vecSize;
-
- // Set the vector size based on property type
- switch (propType) {
- case VehiclePropertyType::BOOLEAN:
- case VehiclePropertyType::INT32:
- case VehiclePropertyType::INT64:
- case VehiclePropertyType::FLOAT:
- vecSize = 1;
- break;
- case VehiclePropertyType::INT32_VEC:
- case VehiclePropertyType::FLOAT_VEC:
- case VehiclePropertyType::BYTES:
- // TODO: Add proper support for these types
- vecSize = 1;
- break;
- case VehiclePropertyType::STRING:
- // Require individual handling
- vecSize = 0;
- break;
- case VehiclePropertyType::COMPLEX:
- switch (cfg.prop) {
- default:
- // Need to handle each complex property separately
- break;
- }
- continue;
- default:
- ALOGE("%s: propType=0x%x not found", __func__, propType);
- vecSize = 0;
- break;
- }
-
- // A global property will have supportedAreas = 0
- if (getPropArea(cfg.prop) == VehicleArea::GLOBAL) {
- supportedAreas = 0;
- }
-
- // This loop is a do-while so it executes at least once to handle global properties
- do {
- int32_t curArea = supportedAreas;
-
- // Clear the right-most bit of supportedAreas
- supportedAreas &= supportedAreas - 1;
-
- // Set curArea to the previously cleared bit
- curArea ^= supportedAreas;
-
- // Create a separate instance for each individual zone
- std::unique_ptr<VehiclePropValue> prop = createVehiclePropValue(propType, vecSize);
- prop->areaId = curArea;
- prop->prop = cfg.prop;
- setDefaultValue(prop.get());
- std::unique_ptr<CustomVehiclePropertyHandler> handler;
- handler.reset(new StoredValueCustomVehiclePropertyHandler());
- handler->set(*prop);
- mProps[std::make_pair(prop->prop, prop->areaId)] =
- std::move(handler);
- } while (supportedAreas != 0);
- }
-
- // Start rx thread
- mThread = std::thread(&DefaultVehicleHal::rxThread, this);
-}
-
-void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
- VehiclePropValuePtr v;
-
- auto& pool = *getValuePool();
-
- for (int32_t property : properties) {
- if (isContinuousProperty(property)) {
- // In real implementation this value should be read from sensor, random
- // value used for testing purpose only.
- std::lock_guard<std::mutex> lock(mPropsMutex);
-
- VehiclePropValue *internalPropValue = getVehiclePropValueLocked(property);
- if (internalPropValue != nullptr) {
- v = pool.obtain(*internalPropValue);
- }
- if (VehiclePropertyType::FLOAT == getPropType(property)) {
- // Just get some randomness to continuous properties to see slightly differnt values
- // on the other end.
- v->value.floatValues[0] = v->value.floatValues[0] + std::rand() % 5;
- }
- } else {
- ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
- }
-
- if (v.get()) {
- v->timestamp = elapsedRealtimeNano();
- doHalEvent(std::move(v));
- }
- }
-}
-
-StatusCode DefaultVehicleHal::subscribe(int32_t property, int32_t,
- float sampleRate) {
- ALOGI("subscribe called for property: 0x%x, sampleRate: %f", property, sampleRate);
-
- if (isContinuousProperty(property)) {
- mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
- }
- return StatusCode::OK;
-}
-
-StatusCode DefaultVehicleHal::unsubscribe(int32_t property) {
- ALOGI("%s propId: 0x%x", __func__, property);
- if (isContinuousProperty(property)) {
- mRecurrentTimer.unregisterRecurrentEvent(property);
- }
- return StatusCode::OK;
-}
-
-const VehiclePropConfig* DefaultVehicleHal::getPropConfig(int32_t propId) const {
- auto it = mPropConfigMap.find(propId);
- return it == mPropConfigMap.end() ? nullptr : it->second;
-}
-
-bool DefaultVehicleHal::isContinuousProperty(int32_t propId) const {
- const VehiclePropConfig* config = getPropConfig(propId);
- if (config == nullptr) {
- ALOGW("Config not found for property: 0x%x", propId);
- return false;
- }
- return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
-}
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
deleted file mode 100644
index c8310b3..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2016 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_DefaultVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
-
-#include <map>
-#include <memory>
-#include <sys/socket.h>
-#include <thread>
-#include <unordered_set>
-
-#include <utils/SystemClock.h>
-
-#include "CommBase.h"
-#include "VehicleHalProto.pb.h"
-
-#include <vhal_v2_0/RecurrentTimer.h>
-#include <vhal_v2_0/VehicleHal.h>
-
-#include "DefaultConfig.h"
-#include "VehicleHalProto.pb.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class DefaultVehicleHal : public VehicleHal {
-public:
- class CustomVehiclePropertyHandler {
- public:
- virtual VehiclePropValue* get() = 0;
- virtual StatusCode set(const VehiclePropValue& propValue) = 0;
- virtual ~CustomVehiclePropertyHandler() = default;
- };
-
-protected:
- class StoredValueCustomVehiclePropertyHandler :
- public CustomVehiclePropertyHandler {
- public:
- VehiclePropValue* get() override {
- return mPropValue.get();
- }
-
- StatusCode set(const VehiclePropValue& propValue) {
- *mPropValue = propValue;
- return StatusCode::OK;
- }
-private:
- std::unique_ptr<VehiclePropValue> mPropValue{new VehiclePropValue()};
-};
-
-public:
- DefaultVehicleHal() : mRecurrentTimer(
- std::bind(&DefaultVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)) {
- for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
- mPropConfigMap[kVehicleProperties[i].prop] = &kVehicleProperties[i];
- }
- }
-
- ~DefaultVehicleHal() override {
- // Notify thread to finish and wait for it to terminate
- mExit = 1;
-
- // Close emulator socket if it is open
- mComm->stop();
-
- mThread.join();
- }
-
- std::vector<VehiclePropConfig> listProperties() override {
- return std::vector<VehiclePropConfig>(std::begin(kVehicleProperties),
- std::end(kVehicleProperties));
- }
-
- VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
- StatusCode* outStatus) override;
-
- void onCreate() override;
-
- StatusCode set(const VehiclePropValue& propValue) override;
-
- StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
-
- StatusCode unsubscribe(int32_t property) override;
-
- /**
- * Add custom property information to this HAL instance.
- *
- * This is useful for allowing later versions of Vehicle HAL to coalesce
- * the list of properties they support with a previous version of the HAL.
- *
- * @param property The identifier of the new property
- * @param handler The object that will handle get/set requests
- * @return OK on success, an error code on failure
- */
- virtual StatusCode addCustomProperty(int32_t,
- std::unique_ptr<CustomVehiclePropertyHandler>&&);
-
- /**
- * Add custom property information to this HAL instance.
- *
- * This is useful for allowing later versions of Vehicle HAL to coalesce
- * the list of properties they support with a previous version of the HAL.
- *
- * @param initialValue The initial value for the new property. This is not
- * constant data, as later set() operations can change
- * this value at will
- * @return OK on success, an error code on failure
- */
- virtual StatusCode addCustomProperty(
- const VehiclePropValue& initialValue) {
- std::unique_ptr<CustomVehiclePropertyHandler> handler;
- handler.reset(new StoredValueCustomVehiclePropertyHandler());
- StatusCode setResponse = handler->set(initialValue);
- if (StatusCode::OK == setResponse) {
- return addCustomProperty(initialValue.prop,
- std::move(handler));
- } else {
- return setResponse;
- }
- }
-
-private:
- void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
- void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
- void doGetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
- void doGetPropertyAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
- void doSetProperty(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
- VehiclePropValue* getVehiclePropValueLocked(int32_t propId, int32_t areaId = 0);
- const VehiclePropConfig* getPropConfig(int32_t propId) const;
- bool isContinuousProperty(int32_t propId) const;
- void parseRxProtoBuf(std::vector<uint8_t>& msg);
- void populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
- const VehiclePropConfig& cfg);
- void populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
- const VehiclePropValue* val);
- void setDefaultValue(VehiclePropValue* prop);
- void rxMsg();
- void rxThread();
- void txMsg(emulator::EmulatorMessage& txMsg);
- StatusCode updateProperty(const VehiclePropValue& propValue);
-
- constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
- return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
- }
-
- void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
-
-private:
- std::map<
- std::pair<int32_t /*VehicleProperty*/, int32_t /*areaId*/>,
- std::unique_ptr<CustomVehiclePropertyHandler>> mProps;
- std::atomic<int> mExit;
- std::unordered_set<int32_t> mHvacPowerProps;
- std::mutex mPropsMutex;
- std::thread mThread;
- std::unique_ptr<CommBase> mComm{nullptr};
- RecurrentTimer mRecurrentTimer;
- std::unordered_map<int32_t, const VehiclePropConfig*> mPropConfigMap;
-};
-
-} // impl
-
-} // namespace V2_0
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
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
new file mode 100644
index 0000000..0ac6ada
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 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 "DefaultVehicleHal_v2_0"
+#include <android/log.h>
+
+#include "EmulatedVehicleHal.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore)
+ : mPropStore(propStore),
+ mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)),
+ mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer,
+ this, std::placeholders::_1)) {
+
+ for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
+ mPropStore->registerProperty(kVehicleProperties[i].config);
+ }
+}
+
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
+ const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+ VehiclePropValuePtr v = nullptr;
+
+ auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+ if (internalPropValue != nullptr) {
+ v = getValuePool()->obtain(*internalPropValue);
+ }
+
+ *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
+ return v;
+}
+
+StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
+ if (mHvacPowerProps.count(propValue.prop)) {
+ auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
+ toInt(VehicleAreaZone::ROW_1));
+
+ if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
+ && hvacPowerOn->value.int32Values[0] == 0) {
+ return StatusCode::NOT_AVAILABLE;
+ }
+ }
+
+ if (!mPropStore->writeValue(propValue)) {
+ return StatusCode::INVALID_ARG;
+ }
+
+ getEmulatorOrDie()->doSetValueFromClient(propValue);
+
+ return StatusCode::OK;
+}
+
+// Parse supported properties list and generate vector of property values to hold current values.
+void EmulatedVehicleHal::onCreate() {
+ for (auto& it : kVehicleProperties) {
+ VehiclePropConfig cfg = it.config;
+ int32_t supportedAreas = cfg.supportedAreas;
+
+ // A global property will have supportedAreas = 0
+ if (isGlobalProp(cfg.prop)) {
+ supportedAreas = 0;
+ }
+
+ // This loop is a do-while so it executes at least once to handle global properties
+ do {
+ int32_t curArea = supportedAreas;
+ supportedAreas &= supportedAreas - 1; // Clear the right-most bit of supportedAreas.
+ curArea ^= supportedAreas; // Set curArea to the previously cleared bit.
+
+ // Create a separate instance for each individual zone
+ VehiclePropValue prop = {
+ .prop = cfg.prop,
+ .areaId = curArea,
+ };
+ if (it.initialAreaValues.size() > 0) {
+ auto valueForAreaIt = it.initialAreaValues.find(curArea);
+ if (valueForAreaIt != it.initialAreaValues.end()) {
+ prop.value = valueForAreaIt->second;
+ } else {
+ ALOGW("%s failed to get default value for prop 0x%x area 0x%x",
+ __func__, cfg.prop, curArea);
+ }
+ } else {
+ prop.value = it.initialValue;
+ }
+ mPropStore->writeValue(prop);
+
+ } while (supportedAreas != 0);
+ }
+}
+
+std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties() {
+ return mPropStore->getAllConfigs();
+}
+
+void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
+ VehiclePropValuePtr v;
+
+ auto& pool = *getValuePool();
+
+ for (int32_t property : properties) {
+ if (isContinuousProperty(property)) {
+ auto internalPropValue = mPropStore->readValueOrNull(property);
+ if (internalPropValue != nullptr) {
+ v = pool.obtain(*internalPropValue);
+ }
+ } else {
+ ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
+ }
+
+ if (v.get()) {
+ v->timestamp = elapsedRealtimeNano();
+ doHalEvent(std::move(v));
+ }
+ }
+}
+
+StatusCode EmulatedVehicleHal::subscribe(int32_t property, int32_t,
+ float sampleRate) {
+ ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
+
+ if (isContinuousProperty(property)) {
+ mRecurrentTimer.registerRecurrentEvent(hertzToNanoseconds(sampleRate), property);
+ }
+ return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::unsubscribe(int32_t property) {
+ ALOGI("%s propId: 0x%x", __func__, property);
+ if (isContinuousProperty(property)) {
+ mRecurrentTimer.unregisterRecurrentEvent(property);
+ }
+ return StatusCode::OK;
+}
+
+bool EmulatedVehicleHal::isContinuousProperty(int32_t propId) const {
+ const VehiclePropConfig* config = mPropStore->getConfigOrNull(propId);
+ if (config == nullptr) {
+ ALOGW("Config not found for property: 0x%x", propId);
+ return false;
+ }
+ return config->changeMode == VehiclePropertyChangeMode::CONTINUOUS;
+}
+
+bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+ if (mPropStore->writeValue(propValue)) {
+ doHalEvent(getValuePool()->obtain(propValue));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const {
+ return mPropStore->readAllValues();
+}
+
+} // impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
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
new file mode 100644
index 0000000..e0874e2
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 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_EmulatedVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
+
+#include <map>
+#include <memory>
+#include <sys/socket.h>
+#include <thread>
+#include <unordered_set>
+
+#include <utils/SystemClock.h>
+
+#include "VehicleHalProto.pb.h"
+
+#include <vhal_v2_0/RecurrentTimer.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include "vhal_v2_0/VehiclePropertyStore.h"
+
+#include "DefaultConfig.h"
+#include "VehicleHalProto.pb.h"
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+/** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
+class EmulatedVehicleHal : public EmulatedVehicleHalIface {
+public:
+ EmulatedVehicleHal(VehiclePropertyStore* propStore);
+ ~EmulatedVehicleHal() = default;
+
+ // Methods from VehicleHal
+ void onCreate() override;
+ std::vector<VehiclePropConfig> listProperties() override;
+ VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+ StatusCode* outStatus) override;
+ StatusCode set(const VehiclePropValue& propValue) override;
+ StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
+ StatusCode unsubscribe(int32_t property) override;
+
+ // Methods from EmulatedVehicleHalIface
+ bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
+ std::vector<VehiclePropValue> getAllProperties() const override;
+
+private:
+ constexpr std::chrono::nanoseconds hertzToNanoseconds(float hz) const {
+ return std::chrono::nanoseconds(static_cast<int64_t>(1000000000L / hz));
+ }
+
+ void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
+ bool isContinuousProperty(int32_t propId) const;
+
+private:
+ VehiclePropertyStore* mPropStore;
+ std::unordered_set<int32_t> mHvacPowerProps;
+ RecurrentTimer mRecurrentTimer;
+};
+
+} // impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
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 6f219fa..2b15aa3 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
@@ -18,6 +18,7 @@
#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
#include <android/log.h>
+#include <log/log.h>
#include <system/qemu_pipe.h>
#include "PipeComm.h"
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 a3ef4b1..42c1c78 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 <log/log.h>
#include <netinet/in.h>
#include <sys/socket.h>
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
new file mode 100644
index 0000000..38cb743
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -0,0 +1,360 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "VehicleEmulator_v2_0"
+#include <android/log.h>
+
+#include <algorithm>
+#include <android-base/properties.h>
+#include <utils/SystemClock.h>
+
+#include <vhal_v2_0/VehicleUtils.h>
+
+#include "PipeComm.h"
+#include "SocketComm.h"
+
+#include "VehicleEmulator.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+std::unique_ptr<CommBase> CommFactory::create() {
+ bool isEmulator = android::base::GetBoolProperty("ro.kernel.qemu", false);
+
+ if (isEmulator) {
+ return std::make_unique<PipeComm>();
+ } else {
+ return std::make_unique<SocketComm>();
+ }
+}
+
+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();
+}
+
+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);
+}
+
+void VehicleEmulator::doGetConfig(VehicleEmulator::EmulatorMessage& rxMsg,
+ VehicleEmulator::EmulatorMessage& respMsg) {
+ std::vector<VehiclePropConfig> configs = mHal->listProperties();
+ emulator::VehiclePropGet getProp = rxMsg.prop(0);
+
+ respMsg.set_msg_type(emulator::GET_CONFIG_RESP);
+ respMsg.set_status(emulator::ERROR_INVALID_PROPERTY);
+
+ for (auto& config : configs) {
+ // Find the config we are looking for
+ if (config.prop == getProp.prop()) {
+ emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+ populateProtoVehicleConfig(protoCfg, config);
+ respMsg.set_status(emulator::RESULT_OK);
+ break;
+ }
+ }
+}
+
+void VehicleEmulator::doGetConfigAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+ VehicleEmulator::EmulatorMessage& respMsg) {
+ std::vector<VehiclePropConfig> configs = mHal->listProperties();
+
+ respMsg.set_msg_type(emulator::GET_CONFIG_ALL_RESP);
+ respMsg.set_status(emulator::RESULT_OK);
+
+ for (auto& config : configs) {
+ emulator::VehiclePropConfig* protoCfg = respMsg.add_config();
+ populateProtoVehicleConfig(protoCfg, config);
+ }
+}
+
+void VehicleEmulator::doGetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+ VehicleEmulator::EmulatorMessage& respMsg) {
+ int32_t areaId = 0;
+ emulator::VehiclePropGet getProp = rxMsg.prop(0);
+ int32_t propId = getProp.prop();
+ emulator::Status status = emulator::ERROR_INVALID_PROPERTY;
+
+ respMsg.set_msg_type(emulator::GET_PROPERTY_RESP);
+
+ if (getProp.has_area_id()) {
+ areaId = getProp.area_id();
+ }
+
+ {
+ VehiclePropValue request = { .prop = propId, .areaId = areaId };
+ StatusCode halStatus;
+ auto val = mHal->get(request, &halStatus);
+ if (val != nullptr) {
+ emulator::VehiclePropValue* protoVal = respMsg.add_value();
+ populateProtoVehiclePropValue(protoVal, val.get());
+ status = emulator::RESULT_OK;
+ }
+ }
+
+ respMsg.set_status(status);
+}
+
+void VehicleEmulator::doGetPropertyAll(VehicleEmulator::EmulatorMessage& /* rxMsg */,
+ VehicleEmulator::EmulatorMessage& respMsg) {
+ respMsg.set_msg_type(emulator::GET_PROPERTY_ALL_RESP);
+ respMsg.set_status(emulator::RESULT_OK);
+
+ {
+ for (const auto& prop : mHal->getAllProperties()) {
+ emulator::VehiclePropValue* protoVal = respMsg.add_value();
+ populateProtoVehiclePropValue(protoVal, &prop);
+ }
+ }
+}
+
+void VehicleEmulator::doSetProperty(VehicleEmulator::EmulatorMessage& rxMsg,
+ VehicleEmulator::EmulatorMessage& respMsg) {
+ emulator::VehiclePropValue protoVal = rxMsg.value(0);
+ VehiclePropValue val = {
+ .prop = protoVal.prop(),
+ .areaId = protoVal.area_id(),
+ .timestamp = elapsedRealtimeNano(),
+ };
+
+ respMsg.set_msg_type(emulator::SET_PROPERTY_RESP);
+
+ // Copy value data if it is set. This automatically handles complex data types if needed.
+ if (protoVal.has_string_value()) {
+ val.value.stringValue = protoVal.string_value().c_str();
+ }
+
+ if (protoVal.has_bytes_value()) {
+ val.value.bytes = std::vector<uint8_t> { protoVal.bytes_value().begin(),
+ protoVal.bytes_value().end() };
+ }
+
+ if (protoVal.int32_values_size() > 0) {
+ val.value.int32Values = std::vector<int32_t> { protoVal.int32_values().begin(),
+ protoVal.int32_values().end() };
+ }
+
+ if (protoVal.int64_values_size() > 0) {
+ val.value.int64Values = std::vector<int64_t> { protoVal.int64_values().begin(),
+ protoVal.int64_values().end() };
+ }
+
+ if (protoVal.float_values_size() > 0) {
+ val.value.floatValues = std::vector<float> { protoVal.float_values().begin(),
+ protoVal.float_values().end() };
+ }
+
+ bool halRes = mHal->setPropertyFromVehicle(val);
+ 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::populateProtoVehicleConfig(emulator::VehiclePropConfig* protoCfg,
+ const VehiclePropConfig& cfg) {
+ protoCfg->set_prop(cfg.prop);
+ protoCfg->set_access(toInt(cfg.access));
+ protoCfg->set_change_mode(toInt(cfg.changeMode));
+ protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
+
+ if (!isGlobalProp(cfg.prop)) {
+ protoCfg->set_supported_areas(cfg.supportedAreas);
+ }
+
+ for (auto& configElement : cfg.configArray) {
+ protoCfg->add_config_array(configElement);
+ }
+
+ if (cfg.configString.size() > 0) {
+ protoCfg->set_config_string(cfg.configString.c_str(), cfg.configString.size());
+ }
+
+ // Populate the min/max values based on property type
+ switch (getPropType(cfg.prop)) {
+ case VehiclePropertyType::STRING:
+ case VehiclePropertyType::BOOLEAN:
+ case VehiclePropertyType::INT32_VEC:
+ case VehiclePropertyType::FLOAT_VEC:
+ case VehiclePropertyType::BYTES:
+ case VehiclePropertyType::COMPLEX:
+ // Do nothing. These types don't have min/max values
+ break;
+ case VehiclePropertyType::INT64:
+ if (cfg.areaConfigs.size() > 0) {
+ emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+ aCfg->set_min_int64_value(cfg.areaConfigs[0].minInt64Value);
+ aCfg->set_max_int64_value(cfg.areaConfigs[0].maxInt64Value);
+ }
+ break;
+ case VehiclePropertyType::FLOAT:
+ if (cfg.areaConfigs.size() > 0) {
+ emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+ aCfg->set_min_float_value(cfg.areaConfigs[0].minFloatValue);
+ aCfg->set_max_float_value(cfg.areaConfigs[0].maxFloatValue);
+ }
+ break;
+ case VehiclePropertyType::INT32:
+ if (cfg.areaConfigs.size() > 0) {
+ emulator::VehicleAreaConfig* aCfg = protoCfg->add_area_configs();
+ aCfg->set_min_int32_value(cfg.areaConfigs[0].minInt32Value);
+ aCfg->set_max_int32_value(cfg.areaConfigs[0].maxInt32Value);
+ }
+ break;
+ default:
+ ALOGW("%s: Unknown property type: 0x%x", __func__, toInt(getPropType(cfg.prop)));
+ break;
+ }
+
+ protoCfg->set_min_sample_rate(cfg.minSampleRate);
+ protoCfg->set_max_sample_rate(cfg.maxSampleRate);
+}
+
+void VehicleEmulator::populateProtoVehiclePropValue(emulator::VehiclePropValue* protoVal,
+ const VehiclePropValue* val) {
+ protoVal->set_prop(val->prop);
+ protoVal->set_value_type(toInt(getPropType(val->prop)));
+ protoVal->set_timestamp(val->timestamp);
+ protoVal->set_area_id(val->areaId);
+
+ // Copy value data if it is set.
+ // - for bytes and strings, this is indicated by size > 0
+ // - for int32, int64, and float, copy the values if vectors have data
+ if (val->value.stringValue.size() > 0) {
+ protoVal->set_string_value(val->value.stringValue.c_str(), val->value.stringValue.size());
+ }
+
+ if (val->value.bytes.size() > 0) {
+ protoVal->set_bytes_value(val->value.bytes.data(), val->value.bytes.size());
+ }
+
+ for (auto& int32Value : val->value.int32Values) {
+ protoVal->add_int32_values(int32Value);
+ }
+
+ for (auto& int64Value : val->value.int64Values) {
+ protoVal->add_int64_values(int64Value);
+ }
+
+ for (auto& floatValue : val->value.floatValues) {
+ protoVal->add_float_values(floatValue);
+ }
+}
+
+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
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
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
new file mode 100644
index 0000000..c8bcd60
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.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_VehicleHalEmulator_H_
+#define android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
+
+#include <log/log.h>
+#include <memory>
+#include <thread>
+#include <vector>
+
+#include "vhal_v2_0/VehicleHal.h"
+
+#include "CommBase.h"
+#include "VehicleHalProto.pb.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class VehicleEmulator; // Forward declaration.
+
+/** Extension of VehicleHal that used by VehicleEmulator. */
+class EmulatedVehicleHalIface : public VehicleHal {
+public:
+ virtual bool setPropertyFromVehicle(const VehiclePropValue& propValue) = 0;
+ virtual std::vector<VehiclePropValue> getAllProperties() const = 0;
+
+ void registerEmulator(VehicleEmulator* emulator) {
+ ALOGI("%s, emulator: %p", __func__, emulator);
+ std::lock_guard<std::mutex> g(mEmulatorLock);
+ mEmulator = emulator;
+ }
+
+protected:
+ VehicleEmulator* getEmulatorOrDie() {
+ std::lock_guard<std::mutex> g(mEmulatorLock);
+ ALOGI("%s, emulator: %p", __func__, mEmulator);
+ assert(mEmulator != nullptr);
+ return mEmulator;
+ }
+
+private:
+ mutable std::mutex mEmulatorLock;
+ 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);
+ }
+ virtual ~VehicleEmulator();
+
+ void doSetValueFromClient(const VehiclePropValue& propValue);
+
+private:
+ 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 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;
+};
+
+} // impl
+
+} // namespace V2_0
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_VehicleHalEmulator_H_
diff --git a/automotive/vehicle/2.1/default/Android.mk b/automotive/vehicle/2.1/default/Android.mk
index 51cb146..32ec456 100644
--- a/automotive/vehicle/2.1/default/Android.mk
+++ b/automotive/vehicle/2.1/default/Android.mk
@@ -49,7 +49,7 @@
LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
LOCAL_SRC_FILES:= \
- impl/vhal_v2_1/DefaultVehicleHal.cpp \
+ impl/vhal_v2_1/EmulatedVehicleHal.cpp \
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/impl/vhal_v2_1 \
diff --git a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
index 945e3e0..6c44626 100644
--- a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
+++ b/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
@@ -55,8 +55,7 @@
const std::vector<uint8_t>& getSensorsBitmask() const;
// Given a stringValue, fill in a VehiclePropValue
- void fillPropValue(V2_0::VehiclePropValue *propValue,
- std::string dtc) const;
+ void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
private:
class BitmaskInVector {
diff --git a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
index b07717b..f4c63a9 100644
--- a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
+++ b/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
@@ -99,8 +99,8 @@
return mSensorsBitmask.getBitmask();
}
-void Obd2SensorStore::fillPropValue(V2_0::VehiclePropValue *propValue,
- std::string dtc) const {
+void Obd2SensorStore::fillPropValue(const std::string& dtc,
+ V2_0::VehiclePropValue *propValue) const {
propValue->timestamp = elapsedRealtimeNano();
propValue->value.int32Values = getIntegerSensors();
propValue->value.floatValues = getFloatSensors();
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
index 6bdec59..aa9aa3c 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
@@ -28,41 +28,50 @@
namespace impl {
+// Some handy constants to avoid conversions from enum to int.
+constexpr int OBD2_LIVE_FRAME = (int) V2_1::VehicleProperty::OBD2_LIVE_FRAME;
+constexpr int OBD2_FREEZE_FRAME = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME;
+constexpr int OBD2_FREEZE_FRAME_INFO = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO;
+constexpr int OBD2_FREEZE_FRAME_CLEAR = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
+constexpr int VEHICLE_MAP_SERVICE = (int) V2_1::VehicleProperty::VEHICLE_MAP_SERVICE;
+constexpr int WHEEL_TICK = (int) V2_1::VehicleProperty::WHEEL_TICK;
+
+
const V2_0::VehiclePropConfig kVehicleProperties[] = {
{
- .prop = V2_0::toInt(V2_1::VehicleProperty::WHEEL_TICK),
+ .prop = WHEEL_TICK,
.access = V2_0::VehiclePropertyAccess::READ,
.changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
},
{
- .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME),
+ .prop = OBD2_LIVE_FRAME,
.access = V2_0::VehiclePropertyAccess::READ,
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
.configArray = {0,0}
},
{
- .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME),
+ .prop = OBD2_FREEZE_FRAME,
.access = V2_0::VehiclePropertyAccess::READ,
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
.configArray = {0,0}
},
{
- .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO),
+ .prop = OBD2_FREEZE_FRAME_INFO,
.access = V2_0::VehiclePropertyAccess::READ,
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
},
{
- .prop = V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR),
+ .prop = OBD2_FREEZE_FRAME_CLEAR,
.access = V2_0::VehiclePropertyAccess::WRITE,
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
},
{
- .prop = V2_0::toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+ .prop = VEHICLE_MAP_SERVICE,
.access = V2_0::VehiclePropertyAccess::READ_WRITE,
.changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
}
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
deleted file mode 100644
index af21138..0000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2016 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_1_impl_DefaultVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_DefaultVehicleHal_H_
-
-#include <memory>
-
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/VehicleHal.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
-#include <vhal_v2_1/Obd2SensorStore.h>
-
-#include "DefaultConfig.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-using namespace std::placeholders;
-
-class DefaultVehicleHal : public V2_0::VehicleHal {
-public:
- DefaultVehicleHal(V2_0::impl::DefaultVehicleHal* vhal20) :
- mVehicleHal20(vhal20) {}
-
- std::vector<V2_0::VehiclePropConfig> listProperties() override {
- std::vector<V2_0::VehiclePropConfig> propConfigs(mVehicleHal20->listProperties());
-
- // Join Vehicle Hal 2.0 and 2.1 configs.
- propConfigs.insert(propConfigs.end(),
- std::begin(kVehicleProperties),
- std::end(kVehicleProperties));
-
- return propConfigs;
- }
-
- VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
- V2_0::StatusCode* outStatus) override;
-
- V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
-
- V2_0::StatusCode subscribe(int32_t property,
- int32_t areas,
- float sampleRate) override {
- return mVehicleHal20->subscribe(property, areas, sampleRate);
- }
-
- V2_0::StatusCode unsubscribe(int32_t property) override {
- return mVehicleHal20->unsubscribe(property);
- }
-
- void onCreate() override;
-
-private:
- void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
- V2_0::VehiclePropValue* liveObd2Frame);
- void initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig);
- V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
- V2_0::VehiclePropValue* v);
- V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *v);
- V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
-
-private:
- V2_0::impl::DefaultVehicleHal* mVehicleHal20;
- std::vector<std::unique_ptr<V2_0::VehiclePropValue>> mFreezeObd2Frames;
-};
-
-} // impl
-
-} // namespace V2_1
-} // namespace vehicle
-} // namespace automotive
-} // namespace hardware
-} // namespace android
-
-
-#endif // android_hardware_automotive_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
similarity index 63%
rename from automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
rename to automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
index b147ce7..4dceae0 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
@@ -17,11 +17,12 @@
#define LOG_TAG "DefaultVehicleHal_v2_1"
#include <android/log.h>
-#include <algorithm>
+#include <log/log.h>
#include <netinet/in.h>
#include <sys/socket.h>
+#include <algorithm>
-#include "DefaultVehicleHal.h"
+#include "EmulatedVehicleHal.h"
#include "VehicleHalProto.pb.h"
#define DEBUG_SOCKET (33452)
@@ -120,118 +121,103 @@
return sensorStore;
}
-void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
- V2_0::VehiclePropValue* liveObd2Frame) {
- auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
- propConfig.configArray[1]);
- sensorStore->fillPropValue(liveObd2Frame, "");
- liveObd2Frame->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
+void EmulatedVehicleHal::initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig) {
+ auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+ auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+ static_cast<size_t>(propConfig.configArray[1]));
+ sensorStore->fillPropValue("", liveObd2Frame.get());
+ liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+ mPropStore->writeValue(*liveObd2Frame);
}
-void DefaultVehicleHal::initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig) {
- auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
- propConfig.configArray[1]);
+void EmulatedVehicleHal::initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig) {
+ auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+ static_cast<size_t>(propConfig.configArray[1]));
- mFreezeObd2Frames.push_back(
- createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
- mFreezeObd2Frames.push_back(
- createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
- mFreezeObd2Frames.push_back(
- createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX,0));
-
- sensorStore->fillPropValue(mFreezeObd2Frames[0].get(), "P0070");
- sensorStore->fillPropValue(mFreezeObd2Frames[1].get(), "P0102");
- sensorStore->fillPropValue(mFreezeObd2Frames[2].get(), "P0123");
+ static std::vector<std::string> sampleDtcs = { "P0070", "P0102" "P0123" };
+ for (auto&& dtc : sampleDtcs) {
+ auto freezeFrame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+ sensorStore->fillPropValue(dtc, freezeFrame.get());
+ mPropStore->writeValue(*freezeFrame);
+ }
}
-template<typename Iterable>
-typename Iterable::const_iterator findPropValueAtTimestamp(
- const Iterable& frames,
- int64_t timestamp) {
- return std::find_if(frames.begin(),
- frames.end(),
- [timestamp] (const std::unique_ptr<V2_0::VehiclePropValue>&
- propValue) -> bool {
- return propValue->timestamp == timestamp;
- });
-}
-
-V2_0::StatusCode DefaultVehicleHal::fillObd2FreezeFrame(
+V2_0::StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(
const V2_0::VehiclePropValue& requestedPropValue,
- V2_0::VehiclePropValue* v) {
+ V2_0::VehiclePropValue* outValue) {
if (requestedPropValue.value.int64Values.size() != 1) {
ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
return V2_0::StatusCode::INVALID_ARG;
}
auto timestamp = requestedPropValue.value.int64Values[0];
- auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
- timestamp);
- if(mFreezeObd2Frames.end() == freezeFrameIter) {
+ auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+ if(freezeFrame == nullptr) {
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
return V2_0::StatusCode::INVALID_ARG;
}
- const auto& freezeFrame = *freezeFrameIter;
- v->prop = V2_0::toInt(VehicleProperty::OBD2_FREEZE_FRAME);
- v->value.int32Values = freezeFrame->value.int32Values;
- v->value.floatValues = freezeFrame->value.floatValues;
- v->value.bytes = freezeFrame->value.bytes;
- v->value.stringValue = freezeFrame->value.stringValue;
- v->timestamp = freezeFrame->timestamp;
+ outValue->prop = OBD2_FREEZE_FRAME;
+ outValue->value.int32Values = freezeFrame->value.int32Values;
+ outValue->value.floatValues = freezeFrame->value.floatValues;
+ outValue->value.bytes = freezeFrame->value.bytes;
+ outValue->value.stringValue = freezeFrame->value.stringValue;
+ outValue->timestamp = freezeFrame->timestamp;
return V2_0::StatusCode::OK;
}
-V2_0::StatusCode DefaultVehicleHal::clearObd2FreezeFrames(
- const V2_0::VehiclePropValue& propValue) {
+V2_0::StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue) {
if (propValue.value.int64Values.size() == 0) {
- mFreezeObd2Frames.clear();
+ mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
return V2_0::StatusCode::OK;
} else {
for(int64_t timestamp: propValue.value.int64Values) {
- auto freezeFrameIter = findPropValueAtTimestamp(mFreezeObd2Frames,
- timestamp);
- if(mFreezeObd2Frames.end() == freezeFrameIter) {
+ auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+ if(freezeFrame == nullptr) {
ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
return V2_0::StatusCode::INVALID_ARG;
}
- mFreezeObd2Frames.erase(freezeFrameIter);
+ mPropStore->removeValue(*freezeFrame);
}
}
return V2_0::StatusCode::OK;
}
-V2_0::StatusCode DefaultVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* v) {
+V2_0::StatusCode EmulatedVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* outValue) {
std::vector<int64_t> timestamps;
- for(const auto& freezeFrame: mFreezeObd2Frames) {
- timestamps.push_back(freezeFrame->timestamp);
+ for(const auto& freezeFrame: mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
+ timestamps.push_back(freezeFrame.timestamp);
}
- v->value.int64Values = timestamps;
+ outValue->value.int64Values = timestamps;
return V2_0::StatusCode::OK;
}
-void DefaultVehicleHal::onCreate() {
- mVehicleHal20->init(getValuePool(),
- std::bind(&DefaultVehicleHal::doHalEvent, this, _1),
- std::bind(&DefaultVehicleHal::doHalPropertySetError, this, _1, _2, _3));
+void EmulatedVehicleHal::onCreate() {
+ V2_0::impl::EmulatedVehicleHal::onCreate();
- std::vector<V2_0::VehiclePropConfig> configs = listProperties();
- for (auto& cfg : configs) {
- switch(cfg.prop) {
- case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME): {
- auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
- initObd2LiveFrame(cfg, liveObd2Frame.get());
- mVehicleHal20->addCustomProperty(*liveObd2Frame);
+ initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
+ initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
+}
+
+void EmulatedVehicleHal::initStaticConfig() {
+ for (auto&& cfg = std::begin(kVehicleProperties); cfg != std::end(kVehicleProperties); ++cfg) {
+ V2_0::VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+ switch (cfg->prop) {
+ case OBD2_FREEZE_FRAME: {
+ tokenFunction = [] (const V2_0::VehiclePropValue& propValue) {
+ return propValue.timestamp;
+ };
+ break;
}
- break;
- case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
- initObd2FreezeFrame(cfg);
- break;
default:
break;
}
+
+ mPropStore->registerProperty(*cfg, tokenFunction);
}
}
-DefaultVehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
+EmulatedVehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
const V2_0::VehiclePropValue& requestedPropValue,
V2_0::StatusCode* outStatus) {
@@ -240,34 +226,30 @@
auto& pool = *getValuePool();
switch (propId) {
- case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
+ case OBD2_FREEZE_FRAME:
v = pool.obtainComplex();
*outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
return v;
- case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO):
+ case OBD2_FREEZE_FRAME_INFO:
v = pool.obtainComplex();
*outStatus = fillObd2DtcInfo(v.get());
return v;
default:
- return mVehicleHal20->get(requestedPropValue, outStatus);
+ return V2_0::impl::EmulatedVehicleHal::get(requestedPropValue, outStatus);
}
}
-V2_0::StatusCode DefaultVehicleHal::set(
- const V2_0::VehiclePropValue& propValue) {
-
+V2_0::StatusCode EmulatedVehicleHal::set(const V2_0::VehiclePropValue& propValue) {
auto propId = propValue.prop;
switch (propId) {
- case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR):
+ case OBD2_FREEZE_FRAME_CLEAR:
return clearObd2FreezeFrames(propValue);
- break;
- case V2_0::toInt(V2_1::VehicleProperty::VEHICLE_MAP_SERVICE):
+ case VEHICLE_MAP_SERVICE:
// Placeholder for future implementation of VMS property in the default hal. For now, just
// returns OK; otherwise, hal clients crash with property not supported.
return V2_0::StatusCode::OK;
- break;
default:
- return mVehicleHal20->set(propValue);
+ return V2_0::impl::EmulatedVehicleHal::set(propValue);
}
}
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
new file mode 100644
index 0000000..7cc3b79
--- /dev/null
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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_1_impl_EmulatedVehicleHal_H_
+#define android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
+
+#include <memory>
+
+#include <utils/SystemClock.h>
+
+#include <vhal_v2_0/EmulatedVehicleHal.h>
+#include <vhal_v2_0/VehicleHal.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_1/Obd2SensorStore.h>
+
+#include "DefaultConfig.h"
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_1 {
+
+namespace impl {
+
+using namespace std::placeholders;
+
+class EmulatedVehicleHal : public V2_0::impl::EmulatedVehicleHal {
+public:
+ EmulatedVehicleHal(V2_0::VehiclePropertyStore* propStore)
+ : V2_0::impl::EmulatedVehicleHal(propStore), mPropStore(propStore) {
+ initStaticConfig();
+ }
+
+ VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
+ V2_0::StatusCode* outStatus) override;
+
+ V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
+
+ void onCreate() override;
+
+private:
+ void initStaticConfig();
+ void initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig);
+ void initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig);
+ V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
+ V2_0::VehiclePropValue* outValue);
+ V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *outValue);
+ V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
+
+private:
+ V2_0::VehiclePropertyStore* mPropStore;
+};
+
+} // impl
+
+} // namespace V2_1
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+
+#endif // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/service.cpp b/automotive/vehicle/2.1/default/service.cpp
index 0844622..4873279 100644
--- a/automotive/vehicle/2.1/default/service.cpp
+++ b/automotive/vehicle/2.1/default/service.cpp
@@ -23,9 +23,10 @@
#include <android/hardware/automotive/vehicle/2.1/IVehicle.h>
#include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/DefaultVehicleHal.h>
+#include <vhal_v2_0/VehiclePropertyStore.h>
+#include <vhal_v2_0/EmulatedVehicleHal.h>
-#include <vhal_v2_1/DefaultVehicleHal.h>
+#include <vhal_v2_1/EmulatedVehicleHal.h>
using namespace android;
using namespace android::hardware;
@@ -80,10 +81,10 @@
};
int main(int /* argc */, char* /* argv */ []) {
- auto halImpl20 = std::make_unique<V2_0::impl::DefaultVehicleHal>();
- auto halImpl21 = std::make_unique<V2_1::impl::DefaultVehicleHal>(halImpl20.get());
-
- auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(halImpl21.get());
+ auto store = std::make_unique<V2_0::VehiclePropertyStore>();
+ auto hal = std::make_unique<V2_1::impl::EmulatedVehicleHal>(store.get());
+ auto emulator = std::make_unique<V2_0::impl::VehicleEmulator>(hal.get());
+ auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(hal.get());
Vehicle_V2_1 vehicle21(vehicleManager.get());
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index 5b00675..4f5aaf9 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -79,7 +79,7 @@
case -28: return RequestStatus::SYS_ENOSPC;
case -110: return RequestStatus::SYS_ETIMEDOUT;
default:
- ALOGE("An unknown error returned from fingerprint vendor library");
+ ALOGE("An unknown error returned from fingerprint vendor library: %d", error);
return RequestStatus::SYS_UNKNOWN;
}
}
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index 8545d2f..0f76c39 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -2,3 +2,4 @@
class hal
user bluetooth
group bluetooth
+ writepid /dev/stune/foreground/tasks
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index 9789ee6..f48a95d 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -30,6 +30,8 @@
using ::android::hardware::hidl_string;
using ::android::hardware::Return;
using ::android::sp;
+using std::string;
+using std::vector;
// The main test class for the Boot HIDL HAL.
class BootHidlTest : public ::testing::VtsHalHidlTargetTestBase {
@@ -83,7 +85,7 @@
{
// Restore original flags to avoid problems on reboot
CommandResult cr;
- Return <void> result = boot->markBootSuccessful(generate_callback(&cr));
+ Return<void> result = boot->markBootSuccessful(generate_callback(&cr));
EXPECT_TRUE(result.isOk());
EXPECT_TRUE(cr.success);
}
@@ -151,22 +153,21 @@
// Sanity check Boot::getSuffix() on good and bad inputs.
TEST_F(BootHidlTest, GetSuffix) {
- const char *suffixPtr;
- auto cb = [&](hidl_string suffix) { suffixPtr = suffix.c_str(); };
- for (Slot i = 0; i < 2; i++) {
- CommandResult cr;
- Return<void> result = boot->getSuffix(i, cb);
- EXPECT_TRUE(result.isOk());
- char correctSuffix[3];
- snprintf(correctSuffix, sizeof(correctSuffix), "_%c", 'a' + i);
- ASSERT_EQ(0, strcmp(suffixPtr, correctSuffix));
- }
- {
- char emptySuffix[] = "";
- Return<void> result = boot->getSuffix(boot->getNumberSlots(), cb);
- EXPECT_TRUE(result.isOk());
- ASSERT_EQ(0, strcmp(emptySuffix, suffixPtr));
- }
+ string suffixStr;
+ vector<string> correctSuffixes = {"_a", "_b"};
+ auto cb = [&](hidl_string suffix) { suffixStr = suffix.c_str(); };
+ for (Slot i = 0; i < 2; i++) {
+ CommandResult cr;
+ Return<void> result = boot->getSuffix(i, cb);
+ EXPECT_TRUE(result.isOk());
+ ASSERT_EQ(0, suffixStr.compare(correctSuffixes[i]));
+ }
+ {
+ string emptySuffix = "";
+ Return<void> result = boot->getSuffix(boot->getNumberSlots(), cb);
+ EXPECT_TRUE(result.isOk());
+ ASSERT_EQ(0, suffixStr.compare(emptySuffix));
+ }
}
int main(int argc, char **argv) {
diff --git a/camera/common/1.0/default/CameraMetadata.cpp b/camera/common/1.0/default/CameraMetadata.cpp
index 44c2040..0e7ef6e 100644
--- a/camera/common/1.0/default/CameraMetadata.cpp
+++ b/camera/common/1.0/default/CameraMetadata.cpp
@@ -17,7 +17,7 @@
// #define LOG_NDEBUG 0
#define LOG_TAG "CamComm1.0-MD"
-#include <utils/Log.h>
+#include <log/log.h>
#include <utils/Errors.h>
#include "CameraMetadata.h"
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index dee2973..e22f26f 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -15,8 +15,8 @@
*/
#define LOG_TAG "HandleImporter"
-#include <utils/Log.h>
#include "HandleImporter.h"
+#include <log/log.h>
namespace android {
namespace hardware {
diff --git a/camera/common/1.0/default/VendorTagDescriptor.cpp b/camera/common/1.0/default/VendorTagDescriptor.cpp
index db884a8..bc18270 100644
--- a/camera/common/1.0/default/VendorTagDescriptor.cpp
+++ b/camera/common/1.0/default/VendorTagDescriptor.cpp
@@ -16,13 +16,13 @@
#define LOG_TAG "CamComm1.0-VTDesc"
-#include <utils/Errors.h>
-#include <utils/Log.h>
-#include <utils/Mutex.h>
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
+#include <log/log.h>
#include <system/camera_metadata.h>
#include <camera_metadata_hidden.h>
+#include <utils/Errors.h>
+#include <utils/Mutex.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
#include "VendorTagDescriptor.h"
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 44a108c..81e41aa 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -66,7 +66,6 @@
"libutils",
"libcutils",
"android.hardware.camera.common@1.0",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
@@ -76,7 +75,6 @@
"libhwbinder",
"libutils",
"android.hardware.camera.common@1.0",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal
index 4c9b517..5421981 100644
--- a/camera/device/1.0/ICameraDevicePreviewCallback.hal
+++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal
@@ -17,7 +17,6 @@
package android.hardware.camera.device@1.0;
import android.hardware.camera.common@1.0::types;
-import android.hardware.graphics.allocator@2.0::types;
import android.hardware.graphics.common@1.0::types;
/**
@@ -89,7 +88,7 @@
*
* @return Status The status code for this operation.
*/
- setUsage(ProducerUsage usage) generates (Status status);
+ setUsage(BufferUsage usage) generates (Status status);
/**
* Set the expected buffering mode for the preview output.
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 877c6e7..cb20fec 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -15,10 +15,10 @@
*/
#define LOG_TAG "CamDev@1.0-impl"
-#include <utils/Log.h>
#include <hardware/camera.h>
#include <hardware/gralloc1.h>
#include <hidlmemory/mapping.h>
+#include <log/log.h>
#include <utils/Trace.h>
#include "CameraDevice_1_0.h"
@@ -30,7 +30,7 @@
namespace V1_0 {
namespace implementation {
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
HandleImporter& CameraDevice::sHandleImporter = HandleImporter::getInstance();
@@ -259,7 +259,7 @@
}
object->cleanUpCirculatingBuffers();
- return getStatusT(object->mPreviewCallback->setUsage((ProducerUsage) usage));
+ return getStatusT(object->mPreviewCallback->setUsage((BufferUsage)usage));
}
int CameraDevice::sSetSwapInterval(struct preview_stream_ops *w, int interval) {
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index fd7276f..7807a85 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -66,7 +66,6 @@
"libutils",
"libcutils",
"android.hardware.camera.common@1.0",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
@@ -76,7 +75,6 @@
"libhwbinder",
"libutils",
"android.hardware.camera.common@1.0",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index a742335..637a1e6 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "CamDev@3.2-impl"
-#include <utils/Log.h>
+#include <log/log.h>
#include <utils/Vector.h>
#include <utils/Trace.h>
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 5b3024b..5bb53c7 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -650,7 +650,8 @@
mVideoStreamIds.clear();
for (const auto& stream : requestedConfiguration.streams) {
if (stream.streamType == StreamType::OUTPUT &&
- stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
+ stream.usage &
+ graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
mVideoStreamIds.push_back(stream.id);
}
}
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index 35676df..d878deb 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "android.hardware.camera.device@3.2-convert-impl"
-#include <android/log.h>
+#include <log/log.h>
#include "include/convert.h"
@@ -28,8 +28,7 @@
using ::android::hardware::graphics::common::V1_0::Dataspace;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::camera::device::V3_2::ConsumerUsageFlags;
-using ::android::hardware::camera::device::V3_2::ProducerUsageFlags;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) {
if (src.size() == 0) {
@@ -78,11 +77,11 @@
dst->overrideFormat = (PixelFormat) src->format;
dst->maxBuffers = src->max_buffers;
if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
- dst->consumerUsage = (ConsumerUsageFlags) 0;
- dst->producerUsage = (ProducerUsageFlags) src->usage;
+ dst->consumerUsage = (BufferUsageFlags)0;
+ dst->producerUsage = (BufferUsageFlags)src->usage;
} else if (src->stream_type == CAMERA3_STREAM_INPUT) {
- dst->producerUsage = (ProducerUsageFlags) 0;
- dst->consumerUsage = (ConsumerUsageFlags) src->usage;
+ dst->producerUsage = (BufferUsageFlags)0;
+ dst->consumerUsage = (BufferUsageFlags)src->usage;
} else {
//Should not reach here per current HIDL spec, but we might end up adding
// bi-directional stream to HIDL.
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 5ae7a18..1632570 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -16,12 +16,10 @@
package android.hardware.camera.device@3.2;
-import android.hardware.graphics.allocator@2.0::types;
import android.hardware.graphics.common@1.0::types;
typedef vec<uint8_t> CameraMetadata;
-typedef bitfield<ProducerUsage> ProducerUsageFlags;
-typedef bitfield<ConsumerUsage> ConsumerUsageFlags;
+typedef bitfield<BufferUsage> BufferUsageFlags;
typedef bitfield<Dataspace> DataspaceFlags;
/**
@@ -255,7 +253,7 @@
* with ILLEGAL_ARGUMENT if the combined flags cannot be supported due to
* imcompatible buffer format, dataSpace, or other hardware limitations.
*/
- ConsumerUsageFlags usage;
+ BufferUsageFlags usage;
/**
* A field that describes the contents of the buffer. The format and buffer
@@ -373,8 +371,8 @@
* consumerUsage must be set. For other types, producerUsage must be set,
* and consumerUsage must be 0.
*/
- ProducerUsageFlags producerUsage;
- ConsumerUsageFlags consumerUsage;
+ BufferUsageFlags producerUsage;
+ BufferUsageFlags consumerUsage;
/**
* The maximum number of buffers the HAL device may need to have dequeued at
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 1656325..d295f3e 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -57,7 +57,6 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
@@ -69,7 +68,6 @@
"android.hardware.camera.common@1.0",
"android.hardware.camera.device@1.0",
"android.hardware.camera.device@3.2",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/camera/provider/2.4/vts/functional/CameraParameters.cpp b/camera/provider/2.4/vts/functional/CameraParameters.cpp
index 0285154..97b263b 100644
--- a/camera/provider/2.4/vts/functional/CameraParameters.cpp
+++ b/camera/provider/2.4/vts/functional/CameraParameters.cpp
@@ -16,7 +16,7 @@
*/
#define LOG_TAG "CameraParams"
-#include <utils/Log.h>
+#include <log/log.h>
#include <string.h>
#include <stdlib.h>
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 74e6efe..e37f989 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -52,8 +52,8 @@
using ::android::BufferItemConsumer;
using ::android::Surface;
using ::android::CameraParameters;
+using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
-using ::android::hardware::graphics::allocator::V2_0::ProducerUsage;
using ::android::hardware::camera::common::V1_0::Status;
using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
using ::android::hardware::camera::common::V1_0::TorchMode;
@@ -233,7 +233,7 @@
Return<Status> setCrop(int32_t left, int32_t top,
int32_t right, int32_t bottom) override;
- Return<Status> setUsage(ProducerUsage usage) override;
+ Return<Status> setUsage(BufferUsage usage) override;
Return<Status> setSwapInterval(int32_t interval) override;
@@ -408,7 +408,7 @@
return mapToStatus(rc);
}
-Return<Status> PreviewWindowCb::setUsage(ProducerUsage usage) {
+Return<Status> PreviewWindowCb::setUsage(BufferUsage usage) {
auto rc = native_window_set_usage(mAnw.get(), static_cast<int>(usage));
if (rc == ::android::OK) {
mPreviewUsage = static_cast<int>(usage);
diff --git a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
index 765857f..5672824 100644
--- a/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
+++ b/contexthub/1.0/vts/functional/VtsHalContexthubV1_0TargetTest.cpp
@@ -16,12 +16,13 @@
#define LOG_TAG "contexthub_hidl_hal_test"
+#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/contexthub/1.0/IContexthub.h>
#include <android/hardware/contexthub/1.0/IContexthubCallback.h>
#include <android/hardware/contexthub/1.0/types.h>
#include <android/log.h>
-#include <VtsHalHidlTargetTestBase.h>
+#include <log/log.h>
#include <cinttypes>
#include <future>
diff --git a/drm/1.0/IDrmPlugin.hal b/drm/1.0/IDrmPlugin.hal
index 083b311..07b0832 100644
--- a/drm/1.0/IDrmPlugin.hal
+++ b/drm/1.0/IDrmPlugin.hal
@@ -179,10 +179,9 @@
* certificate authority (CA) is an entity which issues digital certificates
* for use by other parties. It is an example of a trusted third party.
* @return status the status of the call. The status must be OK or one of
- * the following errors: BAD_VALUE if the sessionId is invalid,
- * ERROR_DRM_CANNOT_HANDLE if the drm scheme does not require provisioning
- * or ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
- * request cannot be generated.
+ * the following errors: ERROR_DRM_CANNOT_HANDLE if the drm scheme does not
+ * require provisioning or ERROR_DRM_INVALID_STATE if the HAL is in a state
+ * where the provision request cannot be generated.
* @return request if successful the opaque certificate request blob
* is returned
* @return defaultUrl URL that the provisioning request should be
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index f2334a0..23a4506 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -38,9 +38,12 @@
LOCAL_C_INCLUDES := \
hardware/interfaces/drm
-# TODO: The legacy DRM plugins only support 32-bit. They need
-# to be migrated to 64-bit (b/18948909)
+# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
+# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
+# that device can turn on ENABLE_MEDIADRM_64 to build this service as 64-bit.
+ifneq ($(ENABLE_MEDIADRM_64), true)
LOCAL_32_BIT_ONLY := true
+endif
include $(BUILD_EXECUTABLE)
@@ -55,11 +58,13 @@
DrmPlugin.cpp \
CryptoFactory.cpp \
CryptoPlugin.cpp \
+ LegacyPluginPath.cpp \
TypeConvert.cpp \
LOCAL_SHARED_LIBRARIES := \
android.hardware.drm@1.0 \
android.hidl.memory@1.0 \
+ libcutils \
libhidlbase \
libhidlmemory \
libhidltransport \
@@ -72,8 +77,11 @@
frameworks/native/include \
frameworks/av/include
-# TODO: The legacy DRM plugins only support 32-bit. They need
-# to be migrated to 64-bit (b/18948909)
+# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
+# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
+# that device can turn on ENABLE_MEDIADRM_64 to build this impl as 64-bit.
+ifneq ($(ENABLE_MEDIADRM_64), true)
LOCAL_32_BIT_ONLY := true
+endif
include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
index e46233d..caab83b 100644
--- a/drm/1.0/default/CryptoFactory.cpp
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -16,9 +16,10 @@
#define LOG_TAG "android.hardware.drm@1.0-impl"
#include "CryptoFactory.h"
+#include <log/log.h>
#include "CryptoPlugin.h"
+#include "LegacyPluginPath.h"
#include "TypeConvert.h"
-#include <utils/Log.h>
namespace android {
namespace hardware {
@@ -27,7 +28,7 @@
namespace implementation {
CryptoFactory::CryptoFactory() :
- loader("/vendor/lib/mediadrm", "createCryptoFactory") {
+ loader(getDrmPluginPath(), "createCryptoFactory") {
}
// Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 9c51b15..591861a 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -20,8 +20,8 @@
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
+#include <log/log.h>
#include <media/stagefright/foundation/AString.h>
-#include <utils/Log.h>
using android::hardware::hidl_memory;
using android::hidl::memory::V1_0::IMemory;
@@ -35,7 +35,7 @@
// Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
const hidl_string& mime) {
- return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+ return mLegacyPlugin->requiresSecureDecoderComponent(mime.c_str());
}
Return<void> CryptoPlugin::notifyResolution(uint32_t width,
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
index 9ec0ab7..7e5d998 100644
--- a/drm/1.0/default/DrmFactory.cpp
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2016 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
@@ -16,9 +16,10 @@
#define LOG_TAG "android.hardware.drm@1.0-impl"
#include "DrmFactory.h"
+#include <log/log.h>
#include "DrmPlugin.h"
+#include "LegacyPluginPath.h"
#include "TypeConvert.h"
-#include <utils/Log.h>
namespace android {
namespace hardware {
@@ -27,7 +28,7 @@
namespace implementation {
DrmFactory::DrmFactory() :
- loader("/vendor/lib/mediadrm", "createDrmFactory") {
+ loader(getDrmPluginPath(), "createDrmFactory") {
}
// Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
index c7428a5..1695ef7 100644
--- a/drm/1.0/default/DrmPlugin.cpp
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -70,15 +70,15 @@
if (status == android::OK) {
android::KeyedVector<String8, String8> legacyOptionalParameters;
for (size_t i = 0; i < optionalParameters.size(); i++) {
- legacyOptionalParameters.add(String8(optionalParameters[i].key),
- String8(optionalParameters[i].value));
+ legacyOptionalParameters.add(String8(optionalParameters[i].key.c_str()),
+ String8(optionalParameters[i].value.c_str()));
}
android::DrmPlugin::KeyRequestType legacyRequestType =
android::DrmPlugin::kKeyRequestType_Unknown;
status = mLegacyPlugin->getKeyRequest(toVector(scope),
- toVector(initData), String8(mimeType), legacyKeyType,
+ toVector(initData), String8(mimeType.c_str()), legacyKeyType,
legacyOptionalParameters, legacyRequest, defaultUrl,
&legacyRequestType);
@@ -149,7 +149,7 @@
Vector<uint8_t> legacyRequest;
String8 legacyDefaultUrl;
status_t status = mLegacyPlugin->getProvisionRequest(
- String8(certificateType), String8(certificateAuthority),
+ String8(certificateType.c_str()), String8(certificateAuthority.c_str()),
legacyRequest, legacyDefaultUrl);
_hidl_cb(toStatus(status), toHidlVec(legacyRequest),
@@ -217,7 +217,7 @@
getPropertyString_cb _hidl_cb) {
String8 legacyValue;
status_t status = mLegacyPlugin->getPropertyString(
- String8(propertyName), legacyValue);
+ String8(propertyName.c_str()), legacyValue);
_hidl_cb(toStatus(status), legacyValue.string());
return Void();
}
@@ -226,7 +226,7 @@
getPropertyByteArray_cb _hidl_cb) {
Vector<uint8_t> legacyValue;
status_t status = mLegacyPlugin->getPropertyByteArray(
- String8(propertyName), legacyValue);
+ String8(propertyName.c_str()), legacyValue);
_hidl_cb(toStatus(status), toHidlVec(legacyValue));
return Void();
}
@@ -234,15 +234,15 @@
Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
const hidl_string& value) {
status_t legacyStatus =
- mLegacyPlugin->setPropertyString(String8(propertyName),
- String8(value));
+ mLegacyPlugin->setPropertyString(String8(propertyName.c_str()),
+ String8(value.c_str()));
return toStatus(legacyStatus);
}
Return<Status> DrmPlugin::setPropertyByteArray(
const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
status_t legacyStatus =
- mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+ mLegacyPlugin->setPropertyByteArray(String8(propertyName.c_str()),
toVector(value));
return toStatus(legacyStatus);
}
@@ -251,7 +251,7 @@
const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
status_t legacyStatus =
mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
- String8(algorithm));
+ String8(algorithm.c_str()));
return toStatus(legacyStatus);
}
@@ -259,7 +259,7 @@
const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
status_t legacyStatus =
mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
- String8(algorithm));
+ String8(algorithm.c_str()));
return toStatus(legacyStatus);
}
@@ -313,7 +313,7 @@
Vector<uint8_t> legacySignature;
status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
- String8(algorithm), toVector(message), toVector(wrappedKey),
+ String8(algorithm.c_str()), toVector(message), toVector(wrappedKey),
legacySignature);
_hidl_cb(toStatus(status), toHidlVec(legacySignature));
return Void();
@@ -327,19 +327,25 @@
Return<void> DrmPlugin::sendEvent(EventType eventType,
const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
- mListener->sendEvent(eventType, sessionId, data);
+ if (mListener != nullptr) {
+ mListener->sendEvent(eventType, sessionId, data);
+ }
return Void();
}
Return<void> DrmPlugin::sendExpirationUpdate(
const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
- mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+ if (mListener != nullptr) {
+ mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+ }
return Void();
}
Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
- mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+ if (mListener != nullptr) {
+ mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+ }
return Void();
}
diff --git a/drm/1.0/default/LegacyPluginPath.cpp b/drm/1.0/default/LegacyPluginPath.cpp
new file mode 100644
index 0000000..369059d
--- /dev/null
+++ b/drm/1.0/default/LegacyPluginPath.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 "LegacyPluginPath.h"
+
+#include <cutils/properties.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+const char* getDrmPluginPath() {
+ if (property_get_bool("drm.64bit.enabled", false)) {
+ return "/vendor/lib64/mediadrm";
+ } else {
+ return "/vendor/lib/mediadrm";
+ }
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace drm
+} // namespace hardware
+} // namespace android
diff --git a/drm/1.0/default/LegacyPluginPath.h b/drm/1.0/default/LegacyPluginPath.h
new file mode 100644
index 0000000..7145f2e
--- /dev/null
+++ b/drm/1.0/default/LegacyPluginPath.h
@@ -0,0 +1,35 @@
+/*
+ * 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 LEGACY_PLUGIN_PATH_H_
+
+#define LEGACY_PLUGIN_PATH_H_
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+const char* getDrmPluginPath();
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace drm
+} // namespace hardware
+} // namespace android
+
+#endif // LEGACY_PLUGIN_PATH_H_
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 36d7d1c..43ea372 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -34,6 +34,8 @@
"libhwbinder",
"liblog",
"libnativehelper",
+ "libssl",
+ "libcrypto",
"libutils",
],
static_libs: [
diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
index 2296d2d..e97ac10 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -26,6 +26,8 @@
#include <gtest/gtest.h>
#include <hidl/HidlSupport.h>
#include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <openssl/aes.h>
#include <memory>
#include <random>
@@ -125,6 +127,39 @@
}
/**
+ * Ensure the factory doesn't support an empty UUID
+ */
+TEST_F(DrmHalClearkeyFactoryTest, EmptyPluginUUIDNotSupported) {
+ hidl_array<uint8_t, 16> emptyUUID;
+ EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
+ EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
+}
+
+/**
+ * Ensure empty content type is not supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, EmptyContentTypeNotSupported) {
+ hidl_string empty;
+ EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
+}
+
+/**
+ * Ensure invalid content type is not supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, InvalidContentTypeNotSupported) {
+ hidl_string invalid("abcdabcd");
+ EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
+}
+
+/**
+ * Ensure valid content type is supported
+ */
+TEST_F(DrmHalClearkeyFactoryTest, ValidContentTypeSupported) {
+ hidl_string cencType("cenc");
+ EXPECT_TRUE(drmFactory->isContentTypeSupported(cencType));
+}
+
+/**
* Ensure clearkey drm plugin can be created
*/
TEST_F(DrmHalClearkeyFactoryTest, CreateClearKeyDrmPlugin) {
@@ -418,6 +453,26 @@
}
/**
+ * Test that a removeKeys on an empty sessionID returns BAD_VALUE
+ */
+TEST_F(DrmHalClearkeyPluginTest, RemoveKeysEmptySessionId) {
+ SessionId sessionId;
+ Status status = drmPlugin->removeKeys(sessionId);
+ EXPECT_TRUE(status == Status::BAD_VALUE);
+}
+
+/**
+ * Remove keys is not supported for clearkey.
+ */
+TEST_F(DrmHalClearkeyPluginTest, RemoveKeysNewSession) {
+ SessionId sessionId = openSession();
+ Status status = drmPlugin->removeKeys(sessionId);
+ // Clearkey plugin doesn't support remove keys
+ EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+ closeSession(sessionId);
+}
+
+/**
* Test that the clearkey plugin doesn't support getting
* secure stops.
*/
@@ -617,7 +672,7 @@
;
hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
- hidl_vec<uint8_t> iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
auto res = drmPlugin->encrypt(session, keyId, input, iv,
[&](Status status, const hidl_vec<uint8_t>&) {
EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
@@ -629,10 +684,9 @@
TEST_F(DrmHalClearkeyPluginTest, GenericDecryptNotSupported) {
SessionId session = openSession();
- ;
hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
- hidl_vec<uint8_t> iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
auto res = drmPlugin->decrypt(session, keyId, input, iv,
[&](Status status, const hidl_vec<uint8_t>&) {
EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE,
@@ -763,6 +817,17 @@
}
/**
+ * setMediaDrmSession with an empty session id: BAD_VALUE. An
+ * empty session clears the previously set session and should
+ * return OK.
+ */
+TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {
+ SessionId sessionId;
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+}
+
+/**
* Decrypt tests
*/
@@ -771,9 +836,15 @@
void loadKeys(const SessionId& sessionId);
void fillRandom(const sp<IMemory>& memory);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
- EXPECT_EQ(vec.size(), 16u);
+ EXPECT_EQ(16u, vec.size());
return hidl_array<uint8_t, 16>(&vec[0]);
}
+ uint32_t decrypt(Mode mode, uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const Pattern& pattern, Status status);
+ void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
+ void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
/**
@@ -847,36 +918,162 @@
}
}
-/**
- * Positive decrypt test. "Decrypt" a single clear
- * segment. Verify data matches.
- */
-TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
- const size_t kSegmentSize = 1024;
+uint32_t DrmHalClearkeyDecryptTest::decrypt(Mode mode,
+ uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const Pattern& pattern, Status expectedStatus) {
const size_t kSegmentIndex = 0;
const vector<uint8_t> keyId = {0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47,
0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
0x1e, 0xd0, 0x0d, 0x1e};
- uint8_t iv[16] = {0};
+ const vector<uint8_t> contentKey = {0x1a, 0x8a, 0x20, 0x95, 0xe4,
+ 0xde, 0xb2, 0xd2, 0x9e, 0xc8,
+ 0x16, 0xac, 0x7b, 0xae, 0x20, 0x82};
+ uint8_t localIv[AES_BLOCK_SIZE];
+ memcpy(localIv, iv, AES_BLOCK_SIZE);
+ size_t totalSize = 0;
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ totalSize += subSamples[i].numBytesOfClearData;
+ totalSize += subSamples[i].numBytesOfEncryptedData;
+ }
+
+ // The first totalSize bytes of shared memory is the encrypted
+ // input, the second totalSize bytes is the decrypted output.
sp<IMemory> sharedMemory =
- getDecryptMemory(kSegmentSize * 2, kSegmentIndex);
+ getDecryptMemory(totalSize * 2, kSegmentIndex);
- SharedBuffer sourceBuffer = {
- .bufferId = kSegmentIndex, .offset = 0, .size = kSegmentSize};
+ const SharedBuffer sourceBuffer = {
+ .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
fillRandom(sharedMemory);
- DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
- {.bufferId = kSegmentIndex,
- .offset = kSegmentSize,
- .size = kSegmentSize},
- .secureMemory = nullptr};
+ const DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
+ {.bufferId = kSegmentIndex,
+ .offset = totalSize,
+ .size = totalSize},
+ .secureMemory = nullptr};
+ const uint64_t offset = 0;
+ const bool kNotSecure = false;
+ uint32_t bytesWritten = 0;
+ auto res = cryptoPlugin->decrypt(kNotSecure, toHidlArray(keyId), localIv, mode,
+ pattern, subSamples, sourceBuffer, offset, destBuffer,
+ [&](Status status, uint32_t count, string detailedError) {
+ EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
+ detailedError;
+ bytesWritten = count;
+ });
+ EXPECT_OK(res);
- Pattern noPattern = {0, 0};
- vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
- .numBytesOfEncryptedData = 0}};
- uint64_t offset = 0;
+ if (bytesWritten != totalSize) {
+ return bytesWritten;
+ }
+ uint8_t* base = static_cast<uint8_t*>(
+ static_cast<void*>(sharedMemory->getPointer()));
+ // generate reference vector
+ vector<uint8_t> reference(totalSize);
+
+ memcpy(localIv, iv, AES_BLOCK_SIZE);
+ switch (mode) {
+ case Mode::UNENCRYPTED:
+ memcpy(&reference[0], base, totalSize);
+ break;
+ case Mode::AES_CTR:
+ aes_ctr_decrypt(&reference[0], base, localIv, subSamples, contentKey);
+ break;
+ case Mode::AES_CBC:
+ aes_cbc_decrypt(&reference[0], base, localIv, subSamples, contentKey);
+ break;
+ case Mode::AES_CBC_CTS:
+ EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
+ break;
+ }
+
+ // compare reference to decrypted data which is at base + total size
+ EXPECT_EQ(0, memcmp(static_cast<void *>(&reference[0]),
+ static_cast<void*>(base + totalSize), totalSize))
+ << "decrypt data mismatch";
+ return totalSize;
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CTR mode
+ */
+void DrmHalClearkeyDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
+ uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const vector<uint8_t>& key) {
+ AES_KEY decryptionKey;
+ AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+ size_t offset = 0;
+ unsigned int blockOffset = 0;
+ uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
+ memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
+
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ const SubSample& subSample = subSamples[i];
+
+ if (subSample.numBytesOfClearData > 0) {
+ memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+ offset += subSample.numBytesOfClearData;
+ }
+
+ if (subSample.numBytesOfEncryptedData > 0) {
+ AES_ctr128_encrypt(src + offset, dest + offset,
+ subSample.numBytesOfEncryptedData, &decryptionKey,
+ iv, previousEncryptedCounter, &blockOffset);
+ offset += subSample.numBytesOfEncryptedData;
+ }
+ }
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CBC mode
+ */
+void DrmHalClearkeyDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
+ uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const vector<uint8_t>& key) {
+ AES_KEY decryptionKey;
+ AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+ size_t offset = 0;
+ size_t num = 0;
+ size_t ecount_buf = 0;
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
+ offset += subSamples[i].numBytesOfClearData;
+
+ AES_cbc_encrypt(src + offset, dest + offset, subSamples[i].numBytesOfEncryptedData,
+ &decryptionKey, iv, 0 /* decrypt */);
+ offset += subSamples[i].numBytesOfEncryptedData;
+ }
+}
+
+/**
+ * Test query key status
+ */
+TEST_F(DrmHalClearkeyDecryptTest, TestQueryKeyStatus) {
+ auto sessionId = openSession();
+ auto res = drmPlugin->queryKeyStatus(sessionId,
+ [&](Status status, KeyedVector /* info */) {
+ // clearkey doesn't support this method
+ EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
+ });
+ EXPECT_OK(res);
+}
+
+
+/**
+ * Positive decrypt test. "Decrypt" a single clear segment
+ */
+TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const uint32_t kByteCount = 256;
+ const vector<SubSample> subSamples = {
+ {.numBytesOfClearData = kByteCount,
+ .numBytesOfEncryptedData = 0}};
auto sessionId = openSession();
loadKeys(sessionId);
@@ -884,21 +1081,57 @@
EXPECT_EQ(Status::OK, status);
const bool kNotSecure = false;
- auto res = cryptoPlugin->decrypt(
- kNotSecure, toHidlArray(keyId), iv, Mode::UNENCRYPTED, noPattern,
- subSamples, sourceBuffer, offset, destBuffer,
- [&](Status status, uint32_t bytesWritten, string detailedError) {
- EXPECT_EQ(Status::OK, status) << "Failure in decryption:"
- << detailedError;
- EXPECT_EQ(bytesWritten, kSegmentSize);
- });
- EXPECT_OK(res);
+ uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
+ noPattern, Status::OK);
+ EXPECT_EQ(kByteCount, byteCount);
- uint8_t* base = static_cast<uint8_t*>(
- static_cast<void*>(sharedMemory->getPointer()));
+ closeSession(sessionId);
+}
- EXPECT_EQ(0, memcmp(static_cast<void*>(base),
- static_cast<void*>(base + kSegmentSize), kSegmentSize))
- << "decrypt data mismatch";
+/**
+ * Positive decrypt test. Decrypt a single segment using AES_CTR.
+ * Verify data matches.
+ */
+TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) {
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const uint32_t kClearBytes = 512;
+ const uint32_t kEncryptedBytes = 512;
+ const vector<SubSample> subSamples = {
+ {.numBytesOfClearData = kClearBytes,
+ .numBytesOfEncryptedData = kEncryptedBytes
+ }};
+ auto sessionId = openSession();
+ loadKeys(sessionId);
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ const bool kNotSecure = false;
+ uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
+ noPattern, Status::OK);
+ EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
+
+ closeSession(sessionId);
+}
+/**
+ * Negative decrypt test. Decrypt without loading keys.
+ */
+TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const vector<SubSample> subSamples = {
+ {.numBytesOfClearData = 256,
+ .numBytesOfEncryptedData = 256}};
+ auto sessionId = openSession();
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ const bool kNotSecure = false;
+ uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
+ noPattern, Status::ERROR_DRM_NO_LICENSE);
+ EXPECT_EQ(0u, byteCount);
+
closeSession(sessionId);
}
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
index db19719..73e0cfe 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
+++ b/drm/1.0/vts/functional/drm_hal_vendor_module_api.h
@@ -73,21 +73,21 @@
* value with initial version 1. The API version indicates which subclass
* version DrmHalVTSVendorModule this instance is.
*/
- virtual uint32_t getAPIVersion() = 0;
+ virtual uint32_t getAPIVersion() const = 0;
/**
* Return the UUID for the DRM HAL implementation. Protection System
* Specific
* UUID (see http://dashif.org/identifiers/protection/)
*/
- virtual std::vector<uint8_t> getUUID() = 0;
+ virtual std::vector<uint8_t> getUUID() const = 0;
/**
* Return the service name for the DRM HAL implementation. If the hal is a
* legacy
* drm plugin, i.e. not running as a HIDL service, return the empty string.
*/
- virtual std::string getServiceName() = 0;
+ virtual std::string getServiceName() const = 0;
private:
DrmHalVTSVendorModule(const DrmHalVTSVendorModule&) = delete;
@@ -103,7 +103,7 @@
DrmHalVTSVendorModule_V1() {}
virtual ~DrmHalVTSVendorModule_V1() {}
- virtual uint32_t getAPIVersion() { return 1; }
+ virtual uint32_t getAPIVersion() const { return 1; }
/**
* Handle a provisioning request. This function will be called if the HAL
@@ -178,11 +178,10 @@
const std::vector<uint8_t> keyId;
/**
- * The key value is provided to generate expected values for
- * validating
- * decryption. If isSecure is false, no key value is required.
+ * The clear content key is provided to generate expected values for
+ * validating decryption.
*/
- const std::vector<uint8_t> keyValue;
+ const std::vector<uint8_t> clearContentKey;
};
std::vector<Key> keys;
};
@@ -191,7 +190,8 @@
* Return a list of content configurations that can be exercised by the
* VTS test.
*/
- virtual std::vector<ContentConfiguration> getContentConfigurations() = 0;
+ virtual std::vector<ContentConfiguration>
+ getContentConfigurations() const = 0;
/**
* Handle a key request. This function will be called if the HAL
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index bd78442c..5945c05 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -21,27 +21,35 @@
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.0/types.h>
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <gtest/gtest.h>
#include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <openssl/aes.h>
#include <memory>
#include <random>
-#include "VtsHalHidlTargetTestBase.h"
#include "drm_hal_vendor_module_api.h"
#include "vendor_modules.h"
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
using ::android::hardware::drm::V1_0::BufferType;
using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::EventType;
using ::android::hardware::drm::V1_0::ICryptoFactory;
using ::android::hardware::drm::V1_0::ICryptoPlugin;
using ::android::hardware::drm::V1_0::IDrmFactory;
using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
using ::android::hardware::drm::V1_0::KeyedVector;
-using ::android::hardware::drm::V1_0::KeyValue;
using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyStatusType;
using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
using ::android::hardware::drm::V1_0::Mode;
using ::android::hardware::drm::V1_0::Pattern;
using ::android::hardware::drm::V1_0::SecureStop;
@@ -56,6 +64,7 @@
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
+using ::android::hardware::Void;
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::sp;
@@ -67,6 +76,10 @@
using std::mt19937;
using std::vector;
+using ContentConfiguration = ::DrmHalVTSVendorModule_V1::ContentConfiguration;
+using Key = ::DrmHalVTSVendorModule_V1::ContentConfiguration::Key;
+using VtsTestBase = ::testing::VtsHalHidlTargetTestBase;
+
#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
@@ -80,10 +93,9 @@
class DrmHalVendorFactoryTest : public testing::TestWithParam<std::string> {
public:
DrmHalVendorFactoryTest()
- : vendorModule(gVendorModules ? static_cast<DrmHalVTSVendorModule_V1*>(
- gVendorModules->getVendorModule(
- GetParam()))
- : nullptr) {}
+ : vendorModule(static_cast<DrmHalVTSVendorModule_V1*>(
+ gVendorModules->getModule(GetParam()))),
+ contentConfigurations(vendorModule->getContentConfigurations()) {}
virtual ~DrmHalVendorFactoryTest() {}
@@ -95,14 +107,22 @@
GetParam().c_str());
ASSERT_NE(vendorModule, nullptr);
+
+ // First try the binderized service name provided by the vendor module.
+ // If that fails, which it can on non-binderized devices, try the default
+ // service.
string name = vendorModule->getServiceName();
- drmFactory =
- ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(
- name != "default" ? name : "drm");
+ drmFactory = VtsTestBase::getService<IDrmFactory>(name);
+ if (drmFactory == nullptr) {
+ drmFactory = VtsTestBase::getService<IDrmFactory>("drm");
+ }
ASSERT_NE(drmFactory, nullptr);
- cryptoFactory =
- ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(
- name != "default" ? name : "crypto");
+
+ // Dot the same for the crypto factory
+ cryptoFactory = VtsTestBase::getService<ICryptoFactory>(name);
+ if (cryptoFactory == nullptr) {
+ VtsTestBase::getService<ICryptoFactory>("crypto");
+ }
ASSERT_NE(cryptoFactory, nullptr);
}
@@ -117,14 +137,27 @@
sp<IDrmFactory> drmFactory;
sp<ICryptoFactory> cryptoFactory;
unique_ptr<DrmHalVTSVendorModule_V1> vendorModule;
+ const vector<ContentConfiguration> contentConfigurations;
};
-/**
- * Ensure the factory supports its scheme UUID
- */
-TEST_P(DrmHalVendorFactoryTest, VendorPluginSupported) {
- EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
- EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
+TEST_P(DrmHalVendorFactoryTest, ValidateConfigurations) {
+ const char* kVendorStr = "Vendor module ";
+ for (auto config : contentConfigurations) {
+ ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
+ ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
+ << "has no serverUrl";
+ ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
+ << "has no init data";
+ ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
+ << "has no mime type";
+ ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
+ for (auto key : config.keys) {
+ ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
+ << " has zero length keyId";
+ ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
+ << " has zero length key value";
+ }
+ }
}
/**
@@ -136,6 +169,48 @@
}
/**
+ * Ensure the factory doesn't support an empty UUID
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyPluginUUIDNotSupported) {
+ hidl_array<uint8_t, 16> emptyUUID;
+ EXPECT_FALSE(drmFactory->isCryptoSchemeSupported(emptyUUID));
+ EXPECT_FALSE(cryptoFactory->isCryptoSchemeSupported(emptyUUID));
+}
+
+/**
+ * Ensure the factory supports the scheme uuid in the config
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyPluginConfigUUIDSupported) {
+ EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(getVendorUUID()));
+ EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(getVendorUUID()));
+}
+
+/**
+ * Ensure empty content type is not supported
+ */
+TEST_P(DrmHalVendorFactoryTest, EmptyContentTypeNotSupported) {
+ hidl_string empty;
+ EXPECT_FALSE(drmFactory->isContentTypeSupported(empty));
+}
+
+/**
+ * Ensure invalid content type is not supported
+ */
+TEST_P(DrmHalVendorFactoryTest, InvalidContentTypeNotSupported) {
+ hidl_string invalid("abcdabcd");
+ EXPECT_FALSE(drmFactory->isContentTypeSupported(invalid));
+}
+
+/**
+ * Ensure valid content types in the configs are supported
+ */
+TEST_P(DrmHalVendorFactoryTest, ValidContentTypeSupported) {
+ for (auto config : contentConfigurations) {
+ EXPECT_TRUE(drmFactory->isContentTypeSupported(config.mimeType));
+ }
+}
+
+/**
* Ensure vendor drm plugin can be created
*/
TEST_P(DrmHalVendorFactoryTest, CreateVendorDrmPlugin) {
@@ -393,6 +468,26 @@
}
/**
+ * Test that a removeKeys on an empty sessionID returns BAD_VALUE
+ */
+TEST_P(DrmHalVendorPluginTest, RemoveKeysEmptySessionId) {
+ SessionId sessionId;
+ Status status = drmPlugin->removeKeys(sessionId);
+ EXPECT_TRUE(status == Status::BAD_VALUE);
+}
+
+/**
+ * Test that remove keys returns okay on an initialized session
+ * that has no keys.
+ */
+TEST_P(DrmHalVendorPluginTest, RemoveKeysNewSession) {
+ SessionId sessionId = openSession();
+ Status status = drmPlugin->removeKeys(sessionId);
+ EXPECT_TRUE(status == Status::OK);
+ closeSession(sessionId);
+}
+
+/**
* Test that the plugin either doesn't support getting
* secure stops, or has no secure stops available after
* clearing them.
@@ -722,6 +817,166 @@
}
/**
+ * Verify that requiresSecureDecoderComponent returns true for secure
+ * configurations
+ */
+TEST_P(DrmHalVendorPluginTest, RequiresSecureDecoderConfig) {
+ const char* kVendorStr = "Vendor module ";
+ for (auto config : contentConfigurations) {
+ for (auto key : config.keys) {
+ if (key.isSecure) {
+ EXPECT_TRUE(cryptoPlugin->requiresSecureDecoderComponent(config.mimeType));
+ break;
+ }
+ }
+ }
+}
+
+/**
+ * Event Handling tests
+ */
+struct ListenerEventArgs {
+ EventType eventType;
+ SessionId sessionId;
+ hidl_vec<uint8_t> data;
+ int64_t expiryTimeInMS;
+ hidl_vec<KeyStatus> keyStatusList;
+ bool hasNewUsableKey;
+};
+
+const char *kCallbackEvent = "SendEvent";
+const char *kCallbackExpirationUpdate = "SendExpirationUpdate";
+const char *kCallbackKeysChange = "SendKeysChange";
+
+class TestDrmPluginListener
+ : public ::testing::VtsHalHidlTargetCallbackBase<ListenerEventArgs>,
+ public IDrmPluginListener {
+public:
+ TestDrmPluginListener() {
+ SetWaitTimeoutDefault(std::chrono::milliseconds(500));
+ }
+ virtual ~TestDrmPluginListener() {}
+
+ virtual Return<void> sendEvent(EventType eventType, const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<uint8_t>& data) override {
+ ListenerEventArgs args;
+ args.eventType = eventType;
+ args.sessionId = sessionId;
+ args.data = data;
+ NotifyFromCallback(kCallbackEvent, args);
+ return Void();
+ }
+
+ virtual Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+ int64_t expiryTimeInMS) override {
+ ListenerEventArgs args;
+ args.sessionId = sessionId;
+ args.expiryTimeInMS = expiryTimeInMS;
+ NotifyFromCallback(kCallbackExpirationUpdate, args);
+ return Void();
+ }
+
+ virtual Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+ const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) override {
+ ListenerEventArgs args;
+ args.sessionId = sessionId;
+ args.keyStatusList = keyStatusList;
+ args.hasNewUsableKey = hasNewUsableKey;
+ NotifyFromCallback(kCallbackKeysChange, args);
+ return Void();
+ }
+};
+
+
+/**
+ * Simulate the plugin sending events. Make sure the listener
+ * gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerEvents) {
+ sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+ drmPlugin->setListener(listener);
+ auto sessionId = openSession();
+ hidl_vec<uint8_t> data = {0, 1, 2};
+ EventType eventTypes[] = {EventType::PROVISION_REQUIRED,
+ EventType::KEY_NEEDED,
+ EventType::KEY_EXPIRED,
+ EventType::VENDOR_DEFINED,
+ EventType::SESSION_RECLAIMED};
+ for (auto eventType : eventTypes) {
+ drmPlugin->sendEvent(eventType, sessionId, data);
+ auto result = listener->WaitForCallback(kCallbackEvent);
+ EXPECT_TRUE(result.no_timeout);
+ EXPECT_TRUE(result.args);
+ EXPECT_EQ(eventType, result.args->eventType);
+ EXPECT_EQ(sessionId, result.args->sessionId);
+ EXPECT_EQ(data, result.args->data);
+ }
+ closeSession(sessionId);
+}
+
+/**
+ * Simulate the plugin sending expiration updates and make sure
+ * the listener gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerExpirationUpdate) {
+ sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+ drmPlugin->setListener(listener);
+ auto sessionId = openSession();
+ drmPlugin->sendExpirationUpdate(sessionId, 100);
+ auto result = listener->WaitForCallback(kCallbackExpirationUpdate);
+ EXPECT_TRUE(result.no_timeout);
+ EXPECT_TRUE(result.args);
+ EXPECT_EQ(sessionId, result.args->sessionId);
+ EXPECT_EQ(100, result.args->expiryTimeInMS);
+ closeSession(sessionId);
+}
+
+/**
+ * Simulate the plugin sending keys change and make sure
+ * the listener gets them.
+ */
+TEST_P(DrmHalVendorPluginTest, ListenerKeysChange) {
+ sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+ drmPlugin->setListener(listener);
+ auto sessionId = openSession();
+ const hidl_vec<KeyStatus> keyStatusList = {
+ {{1}, KeyStatusType::USABLE},
+ {{2}, KeyStatusType::EXPIRED},
+ {{3}, KeyStatusType::OUTPUTNOTALLOWED},
+ {{4}, KeyStatusType::STATUSPENDING},
+ {{5}, KeyStatusType::INTERNALERROR},
+ };
+
+ drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
+ auto result = listener->WaitForCallback(kCallbackKeysChange);
+ EXPECT_TRUE(result.no_timeout);
+ EXPECT_TRUE(result.args);
+ EXPECT_EQ(sessionId, result.args->sessionId);
+ EXPECT_EQ(keyStatusList, result.args->keyStatusList);
+}
+
+/**
+ * Negative listener tests. Call send methods with no
+ * listener set.
+ */
+TEST_P(DrmHalVendorPluginTest, NotListening) {
+ sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
+ drmPlugin->setListener(listener);
+ drmPlugin->setListener(nullptr);
+
+ SessionId sessionId;
+ hidl_vec<uint8_t> data;
+ hidl_vec<KeyStatus> keyStatusList;
+ drmPlugin->sendEvent(EventType::PROVISION_REQUIRED, sessionId, data);
+ drmPlugin->sendExpirationUpdate(sessionId, 100);
+ drmPlugin->sendKeysChange(sessionId, keyStatusList, true);
+ auto result = listener->WaitForCallbackAny(
+ {kCallbackEvent, kCallbackExpirationUpdate, kCallbackKeysChange});
+ EXPECT_FALSE(result.no_timeout);
+}
+
+
+/**
* CryptoPlugin tests
*/
@@ -786,6 +1041,15 @@
}
/**
+ * setMediaDrmSession with a empty session id: BAD_VALUE
+ */
+TEST_P(DrmHalVendorPluginTest, SetMediaDrmSessionEmptySession) {
+ SessionId sessionId;
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::BAD_VALUE, status);
+}
+
+/**
* Decrypt tests
*/
@@ -796,14 +1060,23 @@
protected:
void loadKeys(const SessionId& sessionId,
- const DrmHalVTSVendorModule_V1::ContentConfiguration&
- configuration);
+ const ContentConfiguration& configuration);
void fillRandom(const sp<IMemory>& memory);
KeyedVector toHidlKeyedVector(const map<string, string>& params);
hidl_array<uint8_t, 16> toHidlArray(const vector<uint8_t>& vec) {
EXPECT_EQ(vec.size(), 16u);
return hidl_array<uint8_t, 16>(&vec[0]);
}
+ hidl_vec<KeyValue> queryKeyStatus(SessionId sessionId);
+ void removeKeys(SessionId sessionId);
+ uint32_t decrypt(Mode mode, bool isSecure,
+ const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
+ const vector<uint8_t>& key, Status expectedStatus);
+ void aes_ctr_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
+ void aes_cbc_decrypt(uint8_t* dest, uint8_t* src, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const vector<uint8_t>& key);
};
KeyedVector DrmHalVendorDecryptTest::toHidlKeyedVector(
@@ -823,9 +1096,8 @@
* These tests use predetermined key request/response to
* avoid requiring a round trip to a license server.
*/
-void DrmHalVendorDecryptTest::loadKeys(
- const SessionId& sessionId,
- const DrmHalVTSVendorModule_V1::ContentConfiguration& configuration) {
+void DrmHalVendorDecryptTest::loadKeys(const SessionId& sessionId,
+ const ContentConfiguration& configuration) {
hidl_vec<uint8_t> keyRequest;
auto res = drmPlugin->getKeyRequest(
sessionId, configuration.initData, configuration.mimeType,
@@ -874,111 +1146,326 @@
}
}
-TEST_P(DrmHalVendorDecryptTest, ValidateConfigurations) {
- vector<DrmHalVTSVendorModule_V1::ContentConfiguration> configurations =
- vendorModule->getContentConfigurations();
- const char* kVendorStr = "Vendor module ";
- for (auto config : configurations) {
- ASSERT_TRUE(config.name.size() > 0) << kVendorStr << "has no name";
- ASSERT_TRUE(config.serverUrl.size() > 0) << kVendorStr
- << "has no serverUrl";
- ASSERT_TRUE(config.initData.size() > 0) << kVendorStr
- << "has no init data";
- ASSERT_TRUE(config.mimeType.size() > 0) << kVendorStr
- << "has no mime type";
- ASSERT_TRUE(config.keys.size() >= 1) << kVendorStr << "has no keys";
- for (auto key : config.keys) {
- ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
- << " has zero length keyId";
- ASSERT_TRUE(key.keyId.size() > 0) << kVendorStr
- << " has zero length key value";
+hidl_vec<KeyValue> DrmHalVendorDecryptTest::queryKeyStatus(SessionId sessionId) {
+ hidl_vec<KeyValue> keyStatus;
+ auto res = drmPlugin->queryKeyStatus(sessionId,
+ [&](Status status, KeyedVector info) {
+ EXPECT_EQ(Status::OK, status);
+ keyStatus = info;
+ });
+ EXPECT_OK(res);
+ return keyStatus;
+}
+
+void DrmHalVendorDecryptTest::removeKeys(SessionId sessionId) {
+ auto res = drmPlugin->removeKeys(sessionId);
+ EXPECT_OK(res);
+}
+
+uint32_t DrmHalVendorDecryptTest::decrypt(Mode mode, bool isSecure,
+ const hidl_array<uint8_t, 16>& keyId, uint8_t* iv,
+ const hidl_vec<SubSample>& subSamples, const Pattern& pattern,
+ const vector<uint8_t>& key, Status expectedStatus) {
+ const size_t kSegmentIndex = 0;
+
+ uint8_t localIv[AES_BLOCK_SIZE];
+ memcpy(localIv, iv, AES_BLOCK_SIZE);
+
+ size_t totalSize = 0;
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ totalSize += subSamples[i].numBytesOfClearData;
+ totalSize += subSamples[i].numBytesOfEncryptedData;
+ }
+
+ // The first totalSize bytes of shared memory is the encrypted
+ // input, the second totalSize bytes is the decrypted output.
+ sp<IMemory> sharedMemory =
+ getDecryptMemory(totalSize * 2, kSegmentIndex);
+
+ SharedBuffer sourceBuffer = {
+ .bufferId = kSegmentIndex, .offset = 0, .size = totalSize};
+ fillRandom(sharedMemory);
+
+ DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
+ {.bufferId = kSegmentIndex,
+ .offset = totalSize,
+ .size = totalSize},
+ .secureMemory = nullptr};
+ uint64_t offset = 0;
+ uint32_t bytesWritten = 0;
+ auto res = cryptoPlugin->decrypt(isSecure, keyId, localIv, mode, pattern,
+ subSamples, sourceBuffer, offset, destBuffer,
+ [&](Status status, uint32_t count, string detailedError) {
+ EXPECT_EQ(expectedStatus, status) << "Unexpected decrypt status " <<
+ detailedError;
+ bytesWritten = count;
+ });
+ EXPECT_OK(res);
+
+ if (bytesWritten != totalSize) {
+ return bytesWritten;
+ }
+ uint8_t* base = static_cast<uint8_t*>(
+ static_cast<void*>(sharedMemory->getPointer()));
+
+ // generate reference vector
+ vector<uint8_t> reference(totalSize);
+
+ memcpy(localIv, iv, AES_BLOCK_SIZE);
+ switch (mode) {
+ case Mode::UNENCRYPTED:
+ memcpy(&reference[0], base, totalSize);
+ break;
+ case Mode::AES_CTR:
+ aes_ctr_decrypt(&reference[0], base, localIv, subSamples, key);
+ break;
+ case Mode::AES_CBC:
+ aes_cbc_decrypt(&reference[0], base, localIv, subSamples, key);
+ break;
+ case Mode::AES_CBC_CTS:
+ EXPECT_TRUE(false) << "AES_CBC_CTS mode not supported";
+ break;
+ }
+
+ // compare reference to decrypted data which is at base + total size
+ EXPECT_EQ(0, memcmp(static_cast<void*>(&reference[0]),
+ static_cast<void*>(base + totalSize), totalSize))
+ << "decrypt data mismatch";
+ return totalSize;
+}
+
+/**
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CTR mode
+ */
+void DrmHalVendorDecryptTest::aes_ctr_decrypt(uint8_t* dest, uint8_t* src,
+ uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const vector<uint8_t>& key) {
+
+ AES_KEY decryptionKey;
+ AES_set_encrypt_key(&key[0], 128, &decryptionKey);
+
+ size_t offset = 0;
+ unsigned blockOffset = 0;
+ uint8_t previousEncryptedCounter[AES_BLOCK_SIZE];
+ memset(previousEncryptedCounter, 0, AES_BLOCK_SIZE);
+
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ const SubSample& subSample = subSamples[i];
+
+ if (subSample.numBytesOfClearData > 0) {
+ memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+ offset += subSample.numBytesOfClearData;
+ }
+
+ if (subSample.numBytesOfEncryptedData > 0) {
+ AES_ctr128_encrypt(src + offset, dest + offset,
+ subSample.numBytesOfEncryptedData, &decryptionKey,
+ iv, previousEncryptedCounter, &blockOffset);
+ offset += subSample.numBytesOfEncryptedData;
}
}
}
/**
- * Positive decrypt test. "Decrypt" a single clear
- * segment. Verify data matches.
+ * Decrypt a list of clear+encrypted subsamples using the specified key
+ * in AES-CBC mode
*/
-TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
- vector<DrmHalVTSVendorModule_V1::ContentConfiguration> configurations =
- vendorModule->getContentConfigurations();
- for (auto config : configurations) {
- const size_t kSegmentSize = 1024;
- const size_t kSegmentIndex = 0;
- uint8_t iv[16] = {0};
+void DrmHalVendorDecryptTest::aes_cbc_decrypt(uint8_t* dest, uint8_t* src,
+ uint8_t* iv, const hidl_vec<SubSample>& subSamples,
+ const vector<uint8_t>& key) {
+ AES_KEY decryptionKey;
+ AES_set_encrypt_key(&key[0], 128, &decryptionKey);
- sp<IMemory> sharedMemory =
- getDecryptMemory(kSegmentSize * 2, kSegmentIndex);
+ size_t offset = 0;
+ size_t num = 0;
+ size_t ecount_buf = 0;
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ const SubSample& subSample = subSamples[i];
- SharedBuffer sourceBuffer = {
- .bufferId = kSegmentIndex, .offset = 0, .size = kSegmentSize};
- fillRandom(sharedMemory);
+ memcpy(dest + offset, src + offset, subSample.numBytesOfClearData);
+ offset += subSample.numBytesOfClearData;
- DestinationBuffer destBuffer = {.type = BufferType::SHARED_MEMORY,
- {.bufferId = kSegmentIndex,
- .offset = kSegmentSize,
- .size = kSegmentSize},
- .secureMemory = nullptr};
+ AES_cbc_encrypt(src + offset, dest + offset, subSample.numBytesOfEncryptedData,
+ &decryptionKey, iv, 0 /* decrypt */);
+ offset += subSample.numBytesOfEncryptedData;
+ }
+}
- Pattern noPattern = {0, 0};
- vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
- .numBytesOfEncryptedData = 0}};
- uint64_t offset = 0;
+/**
+ * Test key status with empty session id, should return BAD_VALUE
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusInvalidSession) {
+ SessionId sessionId;
+ auto res = drmPlugin->queryKeyStatus(sessionId,
+ [&](Status status, KeyedVector /* info */) {
+ EXPECT_EQ(Status::BAD_VALUE, status);
+ });
+ EXPECT_OK(res);
+}
+
+
+/**
+ * Test key status. There should be no key status prior to loading keys
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatusWithNoKeys) {
+ auto sessionId = openSession();
+ auto keyStatus = queryKeyStatus(sessionId);
+ EXPECT_EQ(0u, keyStatus.size());
+ closeSession(sessionId);
+}
+
+
+/**
+ * Test key status. There should be key status after loading keys.
+ */
+TEST_P(DrmHalVendorDecryptTest, QueryKeyStatus) {
+ for (auto config : contentConfigurations) {
auto sessionId = openSession();
loadKeys(sessionId, config);
-
- Status status = cryptoPlugin->setMediaDrmSession(sessionId);
- EXPECT_EQ(Status::OK, status);
-
- const bool kNotSecure = false;
- auto res = cryptoPlugin->decrypt(
- kNotSecure, toHidlArray(config.keys[0].keyId), iv,
- Mode::UNENCRYPTED, noPattern, subSamples, sourceBuffer, offset,
- destBuffer, [&](Status status, uint32_t bytesWritten,
- string detailedError) {
- EXPECT_EQ(Status::OK, status) << "Failure in decryption "
- "for configuration "
- << config.name << ": "
- << detailedError;
- EXPECT_EQ(bytesWritten, kSegmentSize);
- });
- EXPECT_OK(res);
- uint8_t* base = static_cast<uint8_t*>(
- static_cast<void*>(sharedMemory->getPointer()));
-
- EXPECT_EQ(0,
- memcmp(static_cast<void*>(base),
- static_cast<void*>(base + kSegmentSize), kSegmentSize))
- << "decrypt data mismatch";
+ auto keyStatus = queryKeyStatus(sessionId);
+ EXPECT_NE(0u, keyStatus.size());
closeSession(sessionId);
}
}
/**
+ * Positive decrypt test. "Decrypt" a single clear segment and verify.
+ */
+TEST_P(DrmHalVendorDecryptTest, ClearSegmentTest) {
+ for (auto config : contentConfigurations) {
+ for (auto key : config.keys) {
+ const size_t kSegmentSize = 1024;
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
+ .numBytesOfEncryptedData = 0}};
+ auto sessionId = openSession();
+ loadKeys(sessionId, config);
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ uint32_t byteCount = decrypt(Mode::UNENCRYPTED, key.isSecure, toHidlArray(key.keyId),
+ &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
+ EXPECT_EQ(kSegmentSize, byteCount);
+
+ closeSession(sessionId);
+ }
+ }
+}
+
+/**
+ * Positive decrypt test. Decrypt a single segment using aes_ctr.
+ * Verify data matches.
+ */
+TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTest) {
+ for (auto config : contentConfigurations) {
+ for (auto key : config.keys) {
+ const size_t kSegmentSize = 1024;
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const vector<SubSample> subSamples = {{.numBytesOfClearData = kSegmentSize,
+ .numBytesOfEncryptedData = 0}};
+ auto sessionId = openSession();
+ loadKeys(sessionId, config);
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure, toHidlArray(key.keyId),
+ &iv[0], subSamples, noPattern, key.clearContentKey, Status::OK);
+ EXPECT_EQ(kSegmentSize, byteCount);
+
+ closeSession(sessionId);
+ }
+ }
+}
+
+/**
+ * Negative decrypt test. Decrypt without loading keys.
+ */
+TEST_P(DrmHalVendorDecryptTest, EncryptedAesCtrSegmentTestNoKeys) {
+ for (auto config : contentConfigurations) {
+ for (auto key : config.keys) {
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
+ .numBytesOfEncryptedData = 256}};
+ auto sessionId = openSession();
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
+ toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
+ key.clearContentKey, Status::ERROR_DRM_NO_LICENSE);
+ EXPECT_EQ(0u, byteCount);
+
+ closeSession(sessionId);
+ }
+ }
+}
+
+/**
+ * Test key removal. Load keys then remove them and verify that
+ * decryption can't be performed.
+ */
+TEST_P(DrmHalVendorDecryptTest, AttemptDecryptWithKeysRemoved) {
+ for (auto config : contentConfigurations) {
+ for (auto key : config.keys) {
+ vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
+ const Pattern noPattern = {0, 0};
+ const vector<SubSample> subSamples = {{.numBytesOfClearData = 256,
+ .numBytesOfEncryptedData = 256}};
+ auto sessionId = openSession();
+
+ Status status = cryptoPlugin->setMediaDrmSession(sessionId);
+ EXPECT_EQ(Status::OK, status);
+
+ loadKeys(sessionId, config);
+ removeKeys(sessionId);
+
+ uint32_t byteCount = decrypt(Mode::AES_CTR, key.isSecure,
+ toHidlArray(key.keyId), &iv[0], subSamples, noPattern,
+ key.clearContentKey, Status::ERROR_DRM_DECRYPT);
+ EXPECT_EQ(0u, byteCount);
+
+ closeSession(sessionId);
+ }
+ }
+}
+
+
+/**
* Instantiate the set of test cases for each vendor module
*/
INSTANTIATE_TEST_CASE_P(
DrmHalVendorFactoryTestCases, DrmHalVendorFactoryTest,
- testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+ testing::ValuesIn(gVendorModules->getPathList()));
INSTANTIATE_TEST_CASE_P(
DrmHalVendorPluginTestCases, DrmHalVendorPluginTest,
- testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+ testing::ValuesIn(gVendorModules->getPathList()));
INSTANTIATE_TEST_CASE_P(
DrmHalVendorDecryptTestCases, DrmHalVendorDecryptTest,
- testing::ValuesIn(gVendorModules->getVendorModulePaths()));
+ testing::ValuesIn(gVendorModules->getPathList()));
int main(int argc, char** argv) {
#if defined(__LP64__)
- const char *kModulePath = "/data/local/tmp/64/lib";
+ const char* kModulePath = "/data/local/tmp/64/lib";
#else
- const char *kModulePath = "/data/local/tmp/32/lib";
+ const char* kModulePath = "/data/local/tmp/32/lib";
#endif
gVendorModules = new drm_vts::VendorModules(kModulePath);
+ if (gVendorModules->getPathList().size() == 0) {
+ std::cerr << "No vendor modules found in " << kModulePath <<
+ ", exiting" << std::endl;
+ exit(-1);
+ }
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
diff --git a/drm/1.0/vts/functional/vendor_modules.cpp b/drm/1.0/vts/functional/vendor_modules.cpp
index 34af6f8..2bf0b28 100644
--- a/drm/1.0/vts/functional/vendor_modules.cpp
+++ b/drm/1.0/vts/functional/vendor_modules.cpp
@@ -18,7 +18,7 @@
#include <dirent.h>
#include <dlfcn.h>
-#include <utils/Log.h>
+#include <log/log.h>
#include <memory>
#include "shared_library.h"
@@ -29,44 +29,37 @@
using std::unique_ptr;
namespace drm_vts {
-vector<string> VendorModules::getVendorModulePaths() {
- if (mModuleList.size() > 0) {
- return mModuleList;
- }
-
- DIR* dir = opendir(mModulesPath.c_str());
+void VendorModules::scanModules(const std::string &directory) {
+ DIR* dir = opendir(directory.c_str());
if (dir == NULL) {
- ALOGE("Unable to open drm VTS vendor directory %s",
- mModulesPath.c_str());
- return mModuleList;
- }
-
- struct dirent* entry;
- while ((entry = readdir(dir))) {
- string fullpath = mModulesPath + "/" + entry->d_name;
- if (endsWith(fullpath, ".so")) {
- mModuleList.push_back(fullpath);
+ ALOGE("Unable to open drm VTS vendor directory %s", directory.c_str());
+ } else {
+ struct dirent* entry;
+ while ((entry = readdir(dir))) {
+ ALOGD("checking file %s", entry->d_name);
+ string fullpath = directory + "/" + entry->d_name;
+ if (endsWith(fullpath, ".so")) {
+ mPathList.push_back(fullpath);
+ }
}
+ closedir(dir);
}
-
- closedir(dir);
- return mModuleList;
}
-DrmHalVTSVendorModule* VendorModules::getVendorModule(const string& path) {
- unique_ptr<SharedLibrary>& library = mOpenLibraries[path];
- if (!library) {
- library = unique_ptr<SharedLibrary>(new SharedLibrary(path));
+DrmHalVTSVendorModule* VendorModules::getModule(const string& path) {
+ if (mOpenLibraries.find(path) == mOpenLibraries.end()) {
+ auto library = std::make_unique<SharedLibrary>(path);
if (!library) {
ALOGE("failed to map shared library %s", path.c_str());
return NULL;
}
+ mOpenLibraries[path] = std::move(library);
}
+ const unique_ptr<SharedLibrary>& library = mOpenLibraries[path];
void* symbol = library->lookup("vendorModuleFactory");
if (symbol == NULL) {
ALOGE("getVendorModule failed to lookup 'vendorModuleFactory' in %s: "
- "%s",
- path.c_str(), library->lastError());
+ "%s", path.c_str(), library->lastError());
return NULL;
}
typedef DrmHalVTSVendorModule* (*ModuleFactory)();
diff --git a/drm/1.0/vts/functional/vendor_modules.h b/drm/1.0/vts/functional/vendor_modules.h
index 5371a0d..ca538f6 100644
--- a/drm/1.0/vts/functional/vendor_modules.h
+++ b/drm/1.0/vts/functional/vendor_modules.h
@@ -30,27 +30,33 @@
* Initialize with a file system path where the shared libraries
* are to be found.
*/
- explicit VendorModules(const std::string& path) : mModulesPath(path) {}
+ explicit VendorModules(const std::string& dir) {
+ scanModules(dir);
+ }
~VendorModules() {}
/**
- * Return a list of paths to available vendor modules.
- */
- std::vector<std::string> getVendorModulePaths();
-
- /**
* Retrieve a DrmHalVTSVendorModule given its full path. The
* getAPIVersion method can be used to determine the versioned
* subclass type.
*/
- DrmHalVTSVendorModule* getVendorModule(const std::string& path);
+ DrmHalVTSVendorModule* getModule(const std::string& path);
+
+ /**
+ * Return the list of paths to available vendor modules.
+ */
+ std::vector<std::string> getPathList() const {return mPathList;}
private:
- std::string mModulesPath;
- std::vector<std::string> mModuleList;
+ std::vector<std::string> mPathList;
std::map<std::string, std::unique_ptr<SharedLibrary>> mOpenLibraries;
- inline bool endsWith(const std::string& str, const std::string& suffix) {
+ /**
+ * Scan the list of paths to available vendor modules.
+ */
+ void scanModules(const std::string& dir);
+
+ inline bool endsWith(const std::string& str, const std::string& suffix) const {
if (suffix.size() > str.size()) return false;
return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
}
diff --git a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
index 391dea0..e9a44eb 100644
--- a/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
+++ b/gatekeeper/1.0/vts/functional/VtsHalGatekeeperV1_0TargetTest.cpp
@@ -30,6 +30,8 @@
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
#include <android/hardware/gatekeeper/1.0/types.h>
+#include <log/log.h>
+
#include <VtsHalHidlTargetTestBase.h>
using ::android::hardware::hidl_string;
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index bd5cc2e..fde3171 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "VtsHalGnssV1_0TargetTest"
#include <android/hardware/gnss/1.0/IGnss.h>
-#include <android/log.h>
+#include <log/log.h>
#include <VtsHalHidlTargetTestBase.h>
@@ -35,11 +35,11 @@
using android::hardware::gnss::V1_0::IGnssMeasurement;
using android::sp;
-#define TIMEOUT_SEC 3 // for basic commands/responses
+#define TIMEOUT_SEC 2 // for basic commands/responses
-// Set these false for release, true for stronger test
-#define GNSS_SIGNAL_IS_PRESENT false
-#define GNSS_ASSISTANCE_IS_PRESENT false
+// for command line argument on how strictly to run the test
+bool sAgpsIsPresent = false; // if SUPL or XTRA assistance available
+bool sSignalIsWeak = false; // if GNSS signals are weak (e.g. light indoor)
// The main test class for GNSS HAL.
class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
@@ -204,7 +204,6 @@
* CheckLocation:
* Helper function to vet Location fields
*/
-
void CheckLocation(GnssLocation& location, bool checkAccuracies) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
@@ -270,6 +269,39 @@
}
/*
+ * StartAndGetSingleLocation:
+ * Helper function to get one Location and check fields
+ *
+ * returns true if a location was successfully generated
+ */
+bool StartAndGetSingleLocation(GnssHalTest* test, bool checkAccuracies) {
+ auto result = test->gnss_hal_->start();
+
+ EXPECT_TRUE(result.isOk());
+ EXPECT_TRUE(result);
+
+ /*
+ * GPS signals initially optional for this test, so don't expect fast fix,
+ * or no timeout, unless signal is present
+ */
+ int firstGnssLocationTimeoutSeconds = sAgpsIsPresent ? 15 : 45;
+ if (sSignalIsWeak) {
+ // allow more time for weak signals
+ firstGnssLocationTimeoutSeconds += 30;
+ }
+
+ test->wait(firstGnssLocationTimeoutSeconds);
+ if (sAgpsIsPresent) {
+ EXPECT_EQ(test->location_called_count_, 1);
+ }
+ if (test->location_called_count_ > 0) {
+ CheckLocation(test->last_location_, checkAccuracies);
+ return true;
+ }
+ return false;
+}
+
+/*
* GetLocation:
* Turns on location, waits 45 second for at least 5 locations,
* and checks them for reasonable validity.
@@ -279,12 +311,6 @@
#define PREFERRED_ACCURACY 0 // Ideally perfect (matches GnssLocationProvider)
#define PREFERRED_TIME_MSEC 0 // Ideally immediate
-#if GNSS_ASSISTANCE_IS_PRESENT
-#define LOCATION_TIMEOUT_FIRST_SEC 15
-#else
-#define LOCATION_TIMEOUT_FIRST_SEC 45
-#endif
-
#define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
#define LOCATIONS_TO_CHECK 5
@@ -299,26 +325,17 @@
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
- result = gnss_hal_->start();
-
- ASSERT_TRUE(result.isOk());
- EXPECT_TRUE(result);
-
/*
* GPS signals initially optional for this test, so don't expect no timeout
* yet
*/
- wait(LOCATION_TIMEOUT_FIRST_SEC);
- if (GNSS_SIGNAL_IS_PRESENT) {
- ASSERT_GT(location_called_count_, 0);
- }
- if (location_called_count_ > 0) {
- CheckLocation(last_location_, checkMoreAccuracies);
- }
+ bool gotLocation = StartAndGetSingleLocation(this, checkMoreAccuracies);
- for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
- wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC);
- if (location_called_count_ > 0) {
+ if (gotLocation) {
+ for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
+ EXPECT_EQ(std::cv_status::no_timeout,
+ wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC));
+ EXPECT_EQ(location_called_count_, i + 1);
CheckLocation(last_location_, checkMoreAccuracies);
}
}
@@ -332,13 +349,11 @@
/*
* InjectDelete:
* Ensures that calls to inject and/or delete information state are handled.
- * Better tests await GPS signal
*/
TEST_F(GnssHalTest, InjectDelete) {
// confidently, well north of Alaska
auto result = gnss_hal_->injectLocation(80.0, -170.0, 1000.0);
- // TODO: full self-diff including TODO's :)
ASSERT_TRUE(result.isOk());
EXPECT_TRUE(result);
@@ -351,6 +366,9 @@
auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL);
ASSERT_TRUE(resultVoid.isOk());
+
+ // Ensure we can get a good location after a bad injection has been deleted
+ StartAndGetSingleLocation(this, false);
}
/*
@@ -413,6 +431,18 @@
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
+ /*
+ * These arguments not used by automated VTS testing.
+ * Only for use in manual testing, when wanting to run
+ * stronger tests that require the presence of GPS signal.
+ */
+ for (int i = 1; i < argc; i++) {
+ if (strcmp(argv[i],"-agps") == 0) {
+ sAgpsIsPresent = true;
+ } else if (strcmp(argv[i],"-weak") == 0) {
+ sSignalIsWeak = true;
+ }
+ }
int status = RUN_ALL_TESTS();
ALOGI("Test result = %d", status);
return status;
diff --git a/graphics/Android.bp b/graphics/Android.bp
index f4f7db4..9aea85f 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -2,7 +2,6 @@
subdirs = [
"allocator/2.0",
"allocator/2.0/default",
- "allocator/2.0/vts/functional",
"bufferqueue/1.0",
"common/1.0",
"composer/2.1",
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 271f2ce..f707468 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -3,9 +3,7 @@
filegroup {
name: "android.hardware.graphics.allocator@2.0_hal",
srcs: [
- "types.hal",
"IAllocator.hal",
- "IAllocatorClient.hal",
],
}
@@ -17,9 +15,7 @@
":android.hardware.graphics.allocator@2.0_hal",
],
out: [
- "android/hardware/graphics/allocator/2.0/types.cpp",
"android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
- "android/hardware/graphics/allocator/2.0/AllocatorClientAll.cpp",
],
}
@@ -31,18 +27,11 @@
":android.hardware.graphics.allocator@2.0_hal",
],
out: [
- "android/hardware/graphics/allocator/2.0/types.h",
- "android/hardware/graphics/allocator/2.0/hwtypes.h",
"android/hardware/graphics/allocator/2.0/IAllocator.h",
"android/hardware/graphics/allocator/2.0/IHwAllocator.h",
"android/hardware/graphics/allocator/2.0/BnHwAllocator.h",
"android/hardware/graphics/allocator/2.0/BpHwAllocator.h",
"android/hardware/graphics/allocator/2.0/BsAllocator.h",
- "android/hardware/graphics/allocator/2.0/IAllocatorClient.h",
- "android/hardware/graphics/allocator/2.0/IHwAllocatorClient.h",
- "android/hardware/graphics/allocator/2.0/BnHwAllocatorClient.h",
- "android/hardware/graphics/allocator/2.0/BpHwAllocatorClient.h",
- "android/hardware/graphics/allocator/2.0/BsAllocatorClient.h",
],
}
@@ -59,6 +48,7 @@
"libutils",
"libcutils",
"android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.mapper@2.0",
"android.hidl.base@1.0",
],
export_shared_lib_headers: [
@@ -67,6 +57,7 @@
"libhwbinder",
"libutils",
"android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.mapper@2.0",
"android.hidl.base@1.0",
],
}
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
index bf0e141..43a3916 100644
--- a/graphics/allocator/2.0/IAllocator.hal
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -16,38 +16,9 @@
package android.hardware.graphics.allocator@2.0;
-import IAllocatorClient;
+import android.hardware.graphics.mapper@2.0;
interface IAllocator {
- enum Capability : int32_t {
- /** reserved */
- INVALID = 0,
-
- /**
- * IAllocatorClient::testAllocate must always return UNDEFINED unless
- * this capability is supported.
- */
- TEST_ALLOCATE = 1,
-
- /**
- * IAllocatorClient::BufferDescriptorInfo::layerCount must be 1 unless
- * this capability is supported.
- */
- LAYERED_BUFFERS = 2,
- };
-
- /**
- * Provides a list of supported capabilities (as described in the
- * definition of Capability above). This list must not change after
- * initialization.
- *
- * @return capabilities is a list of supported capabilities.
- */
- @entry
- @exit
- @callflow(next="*")
- getCapabilities() generates (vec<Capability> capabilities);
-
/**
* Retrieves implementation-defined debug information, which will be
* displayed during, for example, `dumpsys SurfaceFlinger`.
@@ -60,15 +31,27 @@
dumpDebugInfo() generates (string debugInfo);
/**
- * Creates a client of the allocator. All resources created by the client
- * are owned by the client and are only visible to the client, unless they
- * are exported by exportHandle.
+ * Allocates buffers with the properties specified by the descriptor.
*
+ * @param descriptor specifies the properties of the buffers to allocate.
+ * @param count is the number of buffers to allocate.
* @return error is NONE upon success. Otherwise,
- * NO_RESOURCES when no more client can currently be created.
- * @return client is the newly created client.
+ * BAD_DESCRIPTOR when the descriptor is invalid.
+ * NO_RESOURCES when the allocation cannot be fulfilled at this
+ * time.
+ * UNSUPPORTED when any of the property encoded in the descriptor
+ * is not supported.
+ * @return stride is the number of pixels between two consecutive rows of
+ * the buffers, when the concept of consecutive rows is defined.
+ * Otherwise, it has no meaning.
+ * @return buffers is an array of raw handles to the newly allocated
+ * buffers.
*/
@entry
+ @exit
@callflow(next="*")
- createClient() generates (Error error, IAllocatorClient client);
+ allocate(BufferDescriptor descriptor, uint32_t count)
+ generates (Error error,
+ uint32_t stride,
+ vec<handle> buffers);
};
diff --git a/graphics/allocator/2.0/IAllocatorClient.hal b/graphics/allocator/2.0/IAllocatorClient.hal
deleted file mode 100644
index 8ca568f..0000000
--- a/graphics/allocator/2.0/IAllocatorClient.hal
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2016 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.allocator@2.0;
-
-import android.hardware.graphics.common@1.0::PixelFormat;
-
-interface IAllocatorClient {
- struct BufferDescriptorInfo {
- /**
- * The width specifies how many columns of pixels must be in the
- * allocated buffer, but does not necessarily represent the offset in
- * columns between the same column in adjacent rows. The rows may be
- * padded.
- */
- uint32_t width;
-
- /**
- * The height specifies how many rows of pixels must be in the
- * allocated buffer.
- */
- uint32_t height;
-
- /**
- * The number of image layers that must be in the allocated buffer.
- */
- uint32_t layerCount;
-
- /** Buffer pixel format. */
- PixelFormat format;
-
- /**
- * Buffer producer usage mask; valid flags can be found in the
- * definition of ProducerUsage.
- */
- uint64_t producerUsageMask;
-
- /**
- * Buffer consumer usage mask; valid flags can be found in the
- * definition of ConsumerUsage.
- */
- uint64_t consumerUsageMask;
- };
-
- /**
- * Creates a new, opaque buffer descriptor.
- *
- * @param descriptorInfo specifies the attributes of the buffer
- * descriptor.
- * @return error is NONE upon success. Otherwise,
- * BAD_VALUE when any attribute in descriptorInfo is invalid.
- * NO_RESOURCES when no more descriptors can currently be created.
- * @return descriptor is the newly created buffer descriptor.
- */
- @entry
- @callflow(next="*")
- createDescriptor(BufferDescriptorInfo descriptorInfo)
- generates (Error error,
- BufferDescriptor descriptor);
-
- /**
- * Destroys an existing buffer descriptor.
- *
- * @param descriptor is the descriptor to destroy.
- * @return error is either NONE or BAD_DESCRIPTOR.
- */
- @exit
- @callflow(next="*")
- destroyDescriptor(BufferDescriptor descriptor) generates (Error error);
-
- /**
- * Tests whether a buffer allocation can succeed, ignoring potential
- * resource contention which might lead to a NO_RESOURCES error.
- *
- * @param descriptors is a list of buffer descriptors.
- * @return error is NONE or NOT_SHARED upon success;
- * NONE when buffers can be created and share a backing store.
- * NOT_SHARED when buffers can be created but require more than a
- * backing store.
- * Otherwise,
- * BAD_DESCRIPTOR when any of the descriptors is invalid.
- * UNSUPPORTED when any of the descriptors can never be satisfied.
- * UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
- */
- @callflow(next="allocate")
- testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);
-
- /**
- * Attempts to allocate a list of buffers sharing a backing store.
- *
- * Each buffer must correspond to one of the descriptors passed into the
- * function and must hold a reference to its backing store. If the device
- * is unable to share the backing store between the buffers, it must
- * attempt to allocate the buffers with different backing stores and
- * return NOT_SHARED if it is successful.
- *
- * @param descriptors is the buffer descriptors to attempt to allocate.
- * @return error is NONE or NOT_SHARED upon success;
- * NONE when buffers can be created and share a backing store.
- * NOT_SHARED when buffers can be created but require more than a
- * backing store.
- * Otherwise,
- * BAD_DESCRIPTOR when any of the descriptors is invalid.
- * UNSUPPORTED when any of the descriptors can never be satisfied.
- * NO_RESOURCES when any of the buffers cannot be created at this
- * time.
- * @return buffers is the allocated buffers.
- */
- @callflow(next="exportHandle")
- allocate(vec<BufferDescriptor> descriptors)
- generates (Error error,
- vec<Buffer> buffers);
-
- /**
- * Frees a buffer.
- *
- * @param buffer is the buffer to be freed.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer is invalid.
- */
- @exit
- @callflow(next="*")
- free(Buffer buffer) generates (Error error);
-
- /**
- * Exports a buffer for use in other client libraries or for cross-process
- * sharing.
- *
- * The exported handle is a handle to the backing store of the buffer, not
- * to the buffer itself. It however may not hold any reference to the
- * backing store and may be considered invalid by client libraries. To use
- * it and, in most cases, to save it for later use, a client must make a
- * clone of the handle and have the cloned handle hold a reference to the
- * backing store. Such a cloned handle will stay valid even after the
- * original buffer is freed. Refer to native_handle_clone and IMapper for
- * how a handle is cloned and how a reference is added.
- *
- * @param descriptor is the descriptor used to allocate the buffer.
- * @param buffer is the buffer to be exported.
- * @return error is NONE upon success. Otherwise,
- * BAD_DESCRIPTOR when the descriptor is invalid.
- * BAD_BUFFER when the buffer is invalid.
- * BAD_VALUE when descriptor and buffer do not match.
- * NO_RESOURCES when the buffer cannot be exported at this time.
- * @return bufferHandle is the exported handle.
- */
- @callflow(next="free")
- exportHandle(BufferDescriptor descriptor,
- Buffer buffer)
- generates (Error error,
- handle bufferHandle);
-};
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 0baef89..6adfa71 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -3,7 +3,7 @@
defaults: ["hidl_defaults"],
proprietary: true,
relative_install_path: "hw",
- srcs: ["Gralloc.cpp"],
+ srcs: ["Gralloc.cpp", "Gralloc0Allocator.cpp", "Gralloc1Allocator.cpp"],
cppflags: ["-Wall", "-Wextra"],
shared_libs: [
"android.hardware.graphics.allocator@2.0",
@@ -15,6 +15,7 @@
"liblog",
"libutils",
],
+ static_libs: ["libgrallocmapperincludes"],
}
cc_binary {
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
index 0b9e863..273d3f5 100644
--- a/graphics/allocator/2.0/default/Gralloc.cpp
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -16,17 +16,11 @@
#define LOG_TAG "GrallocPassthrough"
-#include <mutex>
-#include <type_traits>
-#include <unordered_set>
-#include <vector>
-
-#include <string.h>
-
-#include <hardware/gralloc1.h>
-#include <log/log.h>
-
#include "Gralloc.h"
+#include "Gralloc0Allocator.h"
+#include "Gralloc1Allocator.h"
+
+#include <log/log.h>
namespace android {
namespace hardware {
@@ -35,417 +29,6 @@
namespace V2_0 {
namespace implementation {
-class GrallocHal : public IAllocator {
-public:
- GrallocHal(const hw_module_t* module);
- virtual ~GrallocHal();
-
- // IAllocator interface
- Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
- Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
- Return<void> createClient(createClient_cb hidl_cb) override;
-
- Error createDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor);
- Error destroyDescriptor(BufferDescriptor descriptor);
-
- Error testAllocate(const hidl_vec<BufferDescriptor>& descriptors);
- Error allocate(const hidl_vec<BufferDescriptor>& descriptors,
- hidl_vec<Buffer>* outBuffers);
- Error free(Buffer buffer);
-
- Error exportHandle(Buffer buffer, const native_handle_t** outHandle);
-
-private:
- void initCapabilities();
-
- template<typename T>
- void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
- void initDispatch();
-
- bool hasCapability(Capability capability) const;
-
- gralloc1_device_t* mDevice;
-
- std::unordered_set<Capability> mCapabilities;
-
- struct {
- GRALLOC1_PFN_DUMP dump;
- GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
- GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
- GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
- GRALLOC1_PFN_SET_FORMAT setFormat;
- GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
- GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
- GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
- GRALLOC1_PFN_ALLOCATE allocate;
- GRALLOC1_PFN_RELEASE release;
- } mDispatch;
-};
-
-class GrallocClient : public IAllocatorClient {
-public:
- GrallocClient(GrallocHal& hal);
- virtual ~GrallocClient();
-
- // IAllocatorClient interface
- Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
- createDescriptor_cb hidl_cb) override;
- Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
-
- Return<Error> testAllocate(
- const hidl_vec<BufferDescriptor>& descriptors) override;
- Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
- allocate_cb hidl_cb) override;
- Return<Error> free(Buffer buffer) override;
-
- Return<void> exportHandle(BufferDescriptor descriptor,
- Buffer buffer, exportHandle_cb hidl_cb) override;
-
-private:
- GrallocHal& mHal;
-
- std::mutex mMutex;
- std::unordered_set<BufferDescriptor> mDescriptors;
- std::unordered_set<Buffer> mBuffers;
-};
-
-GrallocHal::GrallocHal(const hw_module_t* module)
- : mDevice(nullptr), mDispatch()
-{
- int status = gralloc1_open(module, &mDevice);
- if (status) {
- LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
- strerror(-status));
- }
-
- initCapabilities();
- initDispatch();
-}
-
-GrallocHal::~GrallocHal()
-{
- gralloc1_close(mDevice);
-}
-
-void GrallocHal::initCapabilities()
-{
- uint32_t count = 0;
- mDevice->getCapabilities(mDevice, &count, nullptr);
-
- std::vector<Capability> caps(count);
- mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
- std::underlying_type<Capability>::type*>(caps.data()));
- caps.resize(count);
-
- mCapabilities.insert(caps.cbegin(), caps.cend());
-}
-
-template<typename T>
-void GrallocHal::initDispatch(gralloc1_function_descriptor_t desc, T* outPfn)
-{
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
- }
-
- *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void GrallocHal::initDispatch()
-{
- initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
- initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
- &mDispatch.createDescriptor);
- initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
- &mDispatch.destroyDescriptor);
- initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
- initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
- if (hasCapability(Capability::LAYERED_BUFFERS)) {
- initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
- &mDispatch.setLayerCount);
- }
- initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
- &mDispatch.setConsumerUsage);
- initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
- &mDispatch.setProducerUsage);
- initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
- initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-}
-
-bool GrallocHal::hasCapability(Capability capability) const
-{
- return (mCapabilities.count(capability) > 0);
-}
-
-Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
-{
- std::vector<Capability> caps(
- mCapabilities.cbegin(), mCapabilities.cend());
-
- hidl_vec<Capability> reply;
- reply.setToExternal(caps.data(), caps.size());
- hidl_cb(reply);
-
- return Void();
-}
-
-Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
-{
- uint32_t len = 0;
- mDispatch.dump(mDevice, &len, nullptr);
-
- std::vector<char> buf(len + 1);
- mDispatch.dump(mDevice, &len, buf.data());
- buf.resize(len + 1);
- buf[len] = '\0';
-
- hidl_string reply;
- reply.setToExternal(buf.data(), len);
- hidl_cb(reply);
-
- return Void();
-}
-
-Return<void> GrallocHal::createClient(createClient_cb hidl_cb)
-{
- sp<IAllocatorClient> client = new GrallocClient(*this);
- hidl_cb(Error::NONE, client);
-
- return Void();
-}
-
-Error GrallocHal::createDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor)
-{
- gralloc1_buffer_descriptor_t descriptor;
- int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
- if (err != GRALLOC1_ERROR_NONE) {
- return static_cast<Error>(err);
- }
-
- err = mDispatch.setDimensions(mDevice, descriptor,
- descriptorInfo.width, descriptorInfo.height);
- if (err == GRALLOC1_ERROR_NONE) {
- err = mDispatch.setFormat(mDevice, descriptor,
- static_cast<int32_t>(descriptorInfo.format));
- }
- if (err == GRALLOC1_ERROR_NONE) {
- if (hasCapability(Capability::LAYERED_BUFFERS)) {
- err = mDispatch.setLayerCount(mDevice, descriptor,
- descriptorInfo.layerCount);
- } else if (descriptorInfo.layerCount != 1) {
- err = GRALLOC1_ERROR_BAD_VALUE;
- }
- }
- if (err == GRALLOC1_ERROR_NONE) {
- uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
- if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
- producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
- }
- if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
- producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
- }
- err = mDispatch.setProducerUsage(mDevice, descriptor,
- descriptorInfo.producerUsageMask);
- }
- if (err == GRALLOC1_ERROR_NONE) {
- uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
- if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
- consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
- }
- err = mDispatch.setConsumerUsage(mDevice, descriptor,
- consumerUsageMask);
- }
-
- if (err == GRALLOC1_ERROR_NONE) {
- *outDescriptor = descriptor;
- } else {
- mDispatch.destroyDescriptor(mDevice, descriptor);
- }
-
- return static_cast<Error>(err);
-}
-
-Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor)
-{
- int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
- return static_cast<Error>(err);
-}
-
-Error GrallocHal::testAllocate(const hidl_vec<BufferDescriptor>& descriptors)
-{
- if (!hasCapability(Capability::TEST_ALLOCATE)) {
- return Error::UNDEFINED;
- }
-
- int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
- descriptors.data(), nullptr);
- return static_cast<Error>(err);
-}
-
-Error GrallocHal::allocate(const hidl_vec<BufferDescriptor>& descriptors,
- hidl_vec<Buffer>* outBuffers)
-{
- std::vector<buffer_handle_t> buffers(descriptors.size());
- int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
- descriptors.data(), buffers.data());
- if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) {
- outBuffers->resize(buffers.size());
- for (size_t i = 0; i < outBuffers->size(); i++) {
- (*outBuffers)[i] = static_cast<Buffer>(
- reinterpret_cast<uintptr_t>(buffers[i]));
- }
- }
-
- return static_cast<Error>(err);
-}
-
-Error GrallocHal::free(Buffer buffer)
-{
- buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(
- static_cast<uintptr_t>(buffer));
-
- int32_t err = mDispatch.release(mDevice, handle);
- return static_cast<Error>(err);
-}
-
-Error GrallocHal::exportHandle(Buffer buffer,
- const native_handle_t** outHandle)
-{
- // we rely on the caller to validate buffer here
- *outHandle = reinterpret_cast<buffer_handle_t>(
- static_cast<uintptr_t>(buffer));
- return Error::NONE;
-}
-
-GrallocClient::GrallocClient(GrallocHal& hal)
- : mHal(hal)
-{
-}
-
-GrallocClient::~GrallocClient()
-{
- if (!mBuffers.empty()) {
- ALOGW("client destroyed with valid buffers");
- for (auto buf : mBuffers) {
- mHal.free(buf);
- }
- }
-
- if (!mDescriptors.empty()) {
- ALOGW("client destroyed with valid buffer descriptors");
- for (auto desc : mDescriptors) {
- mHal.destroyDescriptor(desc);
- }
- }
-}
-
-Return<void> GrallocClient::createDescriptor(
- const BufferDescriptorInfo& descriptorInfo,
- createDescriptor_cb hidl_cb)
-{
- BufferDescriptor descriptor = 0;
- Error err = mHal.createDescriptor(descriptorInfo, &descriptor);
-
- if (err == Error::NONE) {
- std::lock_guard<std::mutex> lock(mMutex);
-
- auto result = mDescriptors.insert(descriptor);
- if (!result.second) {
- ALOGW("duplicated buffer descriptor id returned");
- mHal.destroyDescriptor(descriptor);
- err = Error::NO_RESOURCES;
- }
- }
-
- hidl_cb(err, descriptor);
- return Void();
-}
-
-Return<Error> GrallocClient::destroyDescriptor(BufferDescriptor descriptor)
-{
- {
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mDescriptors.erase(descriptor)) {
- return Error::BAD_DESCRIPTOR;
- }
- }
-
- return mHal.destroyDescriptor(descriptor);
-}
-
-Return<Error> GrallocClient::testAllocate(
- const hidl_vec<BufferDescriptor>& descriptors)
-{
- return mHal.testAllocate(descriptors);
-}
-
-Return<void> GrallocClient::allocate(
- const hidl_vec<BufferDescriptor>& descriptors,
- allocate_cb hidl_cb) {
- hidl_vec<Buffer> buffers;
- Error err = mHal.allocate(descriptors, &buffers);
-
- if (err == Error::NONE || err == Error::NOT_SHARED) {
- std::lock_guard<std::mutex> lock(mMutex);
-
- for (size_t i = 0; i < buffers.size(); i++) {
- auto result = mBuffers.insert(buffers[i]);
- if (!result.second) {
- ALOGW("duplicated buffer id returned");
-
- for (size_t j = 0; j < buffers.size(); j++) {
- if (j < i) {
- mBuffers.erase(buffers[i]);
- }
- mHal.free(buffers[i]);
- }
-
- buffers = hidl_vec<Buffer>();
- err = Error::NO_RESOURCES;
- break;
- }
- }
- }
-
- hidl_cb(err, buffers);
- return Void();
-}
-
-Return<Error> GrallocClient::free(Buffer buffer)
-{
- {
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mBuffers.erase(buffer)) {
- return Error::BAD_BUFFER;
- }
- }
-
- return mHal.free(buffer);
-}
-
-Return<void> GrallocClient::exportHandle(BufferDescriptor /*descriptor*/,
- Buffer buffer, exportHandle_cb hidl_cb)
-{
- const native_handle_t* handle = nullptr;
-
- {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mBuffers.count(buffer) == 0) {
- hidl_cb(Error::BAD_BUFFER, handle);
- return Void();
- }
- }
-
- Error err = mHal.exportHandle(buffer, &handle);
-
- hidl_cb(err, handle);
- return Void();
-}
-
IAllocator* HIDL_FETCH_IAllocator(const char* /* name */) {
const hw_module_t* module = nullptr;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -455,12 +38,15 @@
}
uint8_t major = (module->module_api_version >> 8) & 0xff;
- if (major != 1) {
- ALOGE("unknown gralloc module major version %d", major);
- return nullptr;
+ switch (major) {
+ case 1:
+ return new Gralloc1Allocator(module);
+ case 0:
+ return new Gralloc0Allocator(module);
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
}
-
- return new GrallocHal(module);
}
} // namespace implementation
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.cpp b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
new file mode 100644
index 0000000..3b62bb3
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2016 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 "Gralloc0Allocator"
+
+#include "Gralloc0Allocator.h"
+#include "GrallocBufferDescriptor.h"
+
+#include <vector>
+
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::implementation::
+ grallocDecodeBufferDescriptor;
+
+Gralloc0Allocator::Gralloc0Allocator(const hw_module_t* module) {
+ int result = gralloc_open(module, &mDevice);
+ if (result) {
+ LOG_ALWAYS_FATAL("failed to open gralloc0 device: %s",
+ strerror(-result));
+ }
+}
+
+Gralloc0Allocator::~Gralloc0Allocator() {
+ gralloc_close(mDevice);
+}
+
+Return<void> Gralloc0Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
+ char buf[4096] = {};
+ if (mDevice->dump) {
+ mDevice->dump(mDevice, buf, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+
+ hidl_cb(hidl_string(buf));
+
+ return Void();
+}
+
+Return<void> Gralloc0Allocator::allocate(const BufferDescriptor& descriptor,
+ uint32_t count, allocate_cb hidl_cb) {
+ IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
+ return Void();
+ }
+
+ Error error = Error::NONE;
+ uint32_t stride = 0;
+ std::vector<hidl_handle> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ buffer_handle_t tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOne(descriptorInfo, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ mDevice->free(mDevice, tmpBuffer);
+ stride = 0;
+ error = Error::UNSUPPORTED;
+ break;
+ }
+
+ buffers.emplace_back(hidl_handle(tmpBuffer));
+ }
+
+ // return the buffers
+ hidl_vec<hidl_handle> hidl_buffers;
+ if (error == Error::NONE) {
+ hidl_buffers.setToExternal(buffers.data(), buffers.size());
+ }
+ hidl_cb(error, stride, hidl_buffers);
+
+ // free the buffers
+ for (const auto& buffer : buffers) {
+ mDevice->free(mDevice, buffer.getNativeHandle());
+ }
+
+ return Void();
+}
+
+Error Gralloc0Allocator::allocateOne(const IMapper::BufferDescriptorInfo& info,
+ buffer_handle_t* outBuffer,
+ uint32_t* outStride) {
+ if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+ return Error::BAD_VALUE;
+ }
+
+ buffer_handle_t buffer = nullptr;
+ int stride = 0;
+ int result = mDevice->alloc(mDevice, info.width, info.height,
+ static_cast<int>(info.format), info.usage,
+ &buffer, &stride);
+ if (result) {
+ switch (result) {
+ case -EINVAL:
+ return Error::BAD_VALUE;
+ default:
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ *outBuffer = buffer;
+ *outStride = stride;
+
+ return Error::NONE;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc0Allocator.h b/graphics/allocator/2.0/default/Gralloc0Allocator.h
new file mode 100644
index 0000000..0e90527
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc0Allocator.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 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_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V2_0::Error;
+
+class Gralloc0Allocator : public IAllocator {
+ public:
+ Gralloc0Allocator(const hw_module_t* module);
+ virtual ~Gralloc0Allocator();
+
+ // IAllocator interface
+ Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+ Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+ allocate_cb hidl_cb) override;
+
+ private:
+ Error allocateOne(const IMapper::BufferDescriptorInfo& info,
+ buffer_handle_t* outBuffer, uint32_t* outStride);
+
+ alloc_device_t* mDevice;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC0ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.cpp b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
new file mode 100644
index 0000000..c0a5e1e
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2016 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 "Gralloc1Allocator"
+
+#include "Gralloc1Allocator.h"
+#include "GrallocBufferDescriptor.h"
+
+#include <vector>
+
+#include <string.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::mapper::V2_0::implementation::
+ grallocDecodeBufferDescriptor;
+
+Gralloc1Allocator::Gralloc1Allocator(const hw_module_t* module)
+ : mDevice(nullptr), mCapabilities(), mDispatch() {
+ int result = gralloc1_open(module, &mDevice);
+ if (result) {
+ LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+ strerror(-result));
+ }
+
+ initCapabilities();
+ initDispatch();
+}
+
+Gralloc1Allocator::~Gralloc1Allocator() {
+ gralloc1_close(mDevice);
+}
+
+void Gralloc1Allocator::initCapabilities() {
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> capabilities(count);
+ mDevice->getCapabilities(mDevice, &count, capabilities.data());
+ capabilities.resize(count);
+
+ for (auto capability : capabilities) {
+ if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+ mCapabilities.layeredBuffers = true;
+ break;
+ }
+ }
+}
+
+template <typename T>
+void Gralloc1Allocator::initDispatch(gralloc1_function_descriptor_t desc,
+ T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (!pfn) {
+ LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
+ }
+
+ *outPfn = reinterpret_cast<T>(pfn);
+}
+
+void Gralloc1Allocator::initDispatch() {
+ initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump);
+ initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR,
+ &mDispatch.createDescriptor);
+ initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR,
+ &mDispatch.destroyDescriptor);
+ initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions);
+ initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat);
+ if (mCapabilities.layeredBuffers) {
+ initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
+ &mDispatch.setLayerCount);
+ }
+ initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
+ &mDispatch.setConsumerUsage);
+ initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
+ &mDispatch.setProducerUsage);
+ initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
+ initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
+ initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+}
+
+Return<void> Gralloc1Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
+ uint32_t len = 0;
+ mDispatch.dump(mDevice, &len, nullptr);
+
+ std::vector<char> buf(len + 1);
+ mDispatch.dump(mDevice, &len, buf.data());
+ buf.resize(len + 1);
+ buf[len] = '\0';
+
+ hidl_string reply;
+ reply.setToExternal(buf.data(), len);
+ hidl_cb(reply);
+
+ return Void();
+}
+
+Return<void> Gralloc1Allocator::allocate(const BufferDescriptor& descriptor,
+ uint32_t count, allocate_cb hidl_cb) {
+ IMapper::BufferDescriptorInfo descriptorInfo;
+ if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+ hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
+ return Void();
+ }
+
+ gralloc1_buffer_descriptor_t desc;
+ Error error = createDescriptor(descriptorInfo, &desc);
+ if (error != Error::NONE) {
+ hidl_cb(error, 0, hidl_vec<hidl_handle>());
+ return Void();
+ }
+
+ uint32_t stride = 0;
+ std::vector<hidl_handle> buffers;
+ buffers.reserve(count);
+
+ // allocate the buffers
+ for (uint32_t i = 0; i < count; i++) {
+ buffer_handle_t tmpBuffer;
+ uint32_t tmpStride;
+ error = allocateOne(desc, &tmpBuffer, &tmpStride);
+ if (error != Error::NONE) {
+ break;
+ }
+
+ if (stride == 0) {
+ stride = tmpStride;
+ } else if (stride != tmpStride) {
+ // non-uniform strides
+ mDispatch.release(mDevice, tmpBuffer);
+ stride = 0;
+ error = Error::UNSUPPORTED;
+ break;
+ }
+
+ buffers.emplace_back(hidl_handle(tmpBuffer));
+ }
+
+ mDispatch.destroyDescriptor(mDevice, desc);
+
+ // return the buffers
+ hidl_vec<hidl_handle> hidl_buffers;
+ if (error == Error::NONE) {
+ hidl_buffers.setToExternal(buffers.data(), buffers.size());
+ }
+ hidl_cb(error, stride, hidl_buffers);
+
+ // free the buffers
+ for (const auto& buffer : buffers) {
+ mDispatch.release(mDevice, buffer.getNativeHandle());
+ }
+
+ return Void();
+}
+
+Error Gralloc1Allocator::toError(int32_t error) {
+ switch (error) {
+ case GRALLOC1_ERROR_NONE:
+ return Error::NONE;
+ case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+ return Error::BAD_DESCRIPTOR;
+ case GRALLOC1_ERROR_BAD_HANDLE:
+ return Error::BAD_BUFFER;
+ case GRALLOC1_ERROR_BAD_VALUE:
+ return Error::BAD_VALUE;
+ case GRALLOC1_ERROR_NOT_SHARED:
+ return Error::NONE; // this is fine
+ case GRALLOC1_ERROR_NO_RESOURCES:
+ return Error::NO_RESOURCES;
+ case GRALLOC1_ERROR_UNDEFINED:
+ case GRALLOC1_ERROR_UNSUPPORTED:
+ default:
+ return Error::UNSUPPORTED;
+ }
+}
+
+uint64_t Gralloc1Allocator::toProducerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t producerUsage =
+ usage &
+ ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+ BufferUsage::CPU_WRITE_MASK);
+
+ switch (usage & BufferUsage::CPU_WRITE_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ return producerUsage;
+}
+
+uint64_t Gralloc1Allocator::toConsumerUsage(uint64_t usage) {
+ // this is potentially broken as we have no idea which private flags
+ // should be filtered out
+ uint64_t consumerUsage =
+ usage &
+ ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+ BufferUsage::CPU_WRITE_MASK);
+
+ switch (usage & BufferUsage::CPU_READ_MASK) {
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+ break;
+ case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+ consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+ break;
+ default:
+ break;
+ }
+
+ return consumerUsage;
+}
+
+Error Gralloc1Allocator::createDescriptor(
+ const IMapper::BufferDescriptorInfo& info,
+ gralloc1_buffer_descriptor_t* outDescriptor) {
+ gralloc1_buffer_descriptor_t descriptor;
+
+ int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setDimensions(mDevice, descriptor, info.width,
+ info.height);
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setFormat(mDevice, descriptor,
+ static_cast<int32_t>(info.format));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ if (mCapabilities.layeredBuffers) {
+ error =
+ mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+ } else if (info.layerCount > 1) {
+ error = GRALLOC1_ERROR_UNSUPPORTED;
+ }
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setProducerUsage(mDevice, descriptor,
+ toProducerUsage(info.usage));
+ }
+ if (error == GRALLOC1_ERROR_NONE) {
+ error = mDispatch.setConsumerUsage(mDevice, descriptor,
+ toConsumerUsage(info.usage));
+ }
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outDescriptor = descriptor;
+ } else {
+ mDispatch.destroyDescriptor(mDevice, descriptor);
+ }
+
+ return toError(error);
+}
+
+Error Gralloc1Allocator::allocateOne(gralloc1_buffer_descriptor_t descriptor,
+ buffer_handle_t* outBuffer,
+ uint32_t* outStride) {
+ buffer_handle_t buffer = nullptr;
+ int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+ return toError(error);
+ }
+
+ uint32_t stride = 0;
+ error = mDispatch.getStride(mDevice, buffer, &stride);
+ if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+ mDispatch.release(mDevice, buffer);
+ return toError(error);
+ }
+
+ *outBuffer = buffer;
+ *outStride = stride;
+
+ return Error::NONE;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1Allocator.h b/graphics/allocator/2.0/default/Gralloc1Allocator.h
new file mode 100644
index 0000000..7b5a966
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1Allocator.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2016 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_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V2_0::Error;
+
+class Gralloc1Allocator : public IAllocator {
+ public:
+ Gralloc1Allocator(const hw_module_t* module);
+ virtual ~Gralloc1Allocator();
+
+ // IAllocator interface
+ Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+ Return<void> allocate(const BufferDescriptor& descriptor, uint32_t count,
+ allocate_cb hidl_cb) override;
+
+ private:
+ void initCapabilities();
+
+ template <typename T>
+ void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+ void initDispatch();
+
+ static Error toError(int32_t error);
+ static uint64_t toProducerUsage(uint64_t usage);
+ static uint64_t toConsumerUsage(uint64_t usage);
+
+ Error createDescriptor(const IMapper::BufferDescriptorInfo& info,
+ gralloc1_buffer_descriptor_t* outDescriptor);
+ Error allocateOne(gralloc1_buffer_descriptor_t descriptor,
+ buffer_handle_t* outBuffer, uint32_t* outStride);
+
+ gralloc1_device_t* mDevice;
+
+ struct {
+ bool layeredBuffers;
+ } mCapabilities;
+
+ struct {
+ GRALLOC1_PFN_DUMP dump;
+ GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+ GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+ GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+ GRALLOC1_PFN_SET_FORMAT setFormat;
+ GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
+ GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+ GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+ GRALLOC1_PFN_GET_STRIDE getStride;
+ GRALLOC1_PFN_ALLOCATE allocate;
+ GRALLOC1_PFN_RELEASE release;
+ } mDispatch;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC1ALLOCATOR_H
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
index f722429..be055ec 100644
--- a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
+++ b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
@@ -25,7 +25,7 @@
#include <hardware/gralloc.h>
-#include <utils/Log.h>
+#include <log/log.h>
#include <sync/sync.h>
#include <inttypes.h>
diff --git a/graphics/allocator/2.0/types.hal b/graphics/allocator/2.0/types.hal
deleted file mode 100644
index d9b184b..0000000
--- a/graphics/allocator/2.0/types.hal
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2016 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.allocator@2.0;
-
-enum Error : int32_t {
- NONE = 0, /** no error */
- BAD_DESCRIPTOR = 1, /** invalid BufferDescriptor */
- BAD_BUFFER = 2, /** invalid Buffer */
- BAD_VALUE = 3, /** invalid width, height, etc. */
- NOT_SHARED = 4, /** buffers not sharing backing store */
- NO_RESOURCES = 5, /** temporary failure due to resource contention */
- UNDEFINED = 6, /** an operation has no defined meaning */
- UNSUPPORTED = 7, /** permanent failure */
-};
-
-enum ProducerUsage : uint64_t {
- /** bit 0 is reserved */
-
- /** buffer is read by CPU occasionally */
- CPU_READ = 1ULL << 1,
- /** buffer is read by CPU frequently */
- CPU_READ_OFTEN = 1ULL << 2,
-
- /** bit 3 is reserved */
- /** bit 4 is reserved */
-
- /** buffer is written by CPU occasionally */
- CPU_WRITE = 1ULL << 5,
- /** buffer is written by CPU frequently */
- CPU_WRITE_OFTEN = 1ULL << 6,
-
- /** bit 7 is reserved */
- /** bit 8 is reserved */
-
- /** buffer is used as a GPU render target */
- GPU_RENDER_TARGET = 1ULL << 9,
-
- /** bit 10 is reserved */
- /** bit 11 is reserved */
- /** bit 12 is reserved */
- /** bit 13 is reserved */
-
- /**
- * Buffer is allocated with hardware-level protection against copying the
- * contents (or information derived from the contents) into unprotected
- * memory.
- */
- PROTECTED = 1ULL << 14,
-
- /** bit 15 is reserved */
- /** bit 16 is reserved */
-
- /** buffer is used as a camera HAL output */
- CAMERA = 1ULL << 17,
-
- /** bit 18 is reserved */
- /** bit 19 is reserved */
- /** bit 20 is reserved */
- /** bit 21 is reserved */
-
- /** buffer is used as a video decoder output */
- VIDEO_DECODER = 1ULL << 22,
-
- /** buffer is used as a sensor direct report output */
- SENSOR_DIRECT_DATA = 1ULL << 23,
-
- /** bits 24-27 are reserved for future versions */
- /** bits 28-31 are reserved for vendor extensions */
-
- /** bits 32-47 are reserved for future versions */
- /** bits 48-63 are reserved for vendor extensions */
-};
-
-enum ConsumerUsage : uint64_t {
- /** bit 0 is reserved */
-
- /** buffer is read by CPU occasionally */
- CPU_READ = 1ULL << 1,
- /** buffer is read by CPU frequently */
- CPU_READ_OFTEN = 1ULL << 2,
-
- /** bit 3 is reserved */
- /** bit 4 is reserved */
- /** bit 5 is reserved */
- /** bit 6 is reserved */
- /** bit 7 is reserved */
-
- /** buffer is used as a GPU texture */
- GPU_TEXTURE = 1ULL << 8,
-
- /** bit 9 is reserved */
- /** bit 10 is reserved */
-
- /** buffer is used by hwcomposer HAL */
- HWCOMPOSER = 1ULL << 11,
- /** buffer is a hwcomposer HAL client target */
- CLIENT_TARGET = 1ULL << 12,
-
- /** bit 13 is reserved */
- /** bit 14 is reserved */
-
- /** buffer is used as a hwcomposer HAL cursor */
- CURSOR = 1ULL << 15,
-
- /** buffer is used as a video encoder input */
- VIDEO_ENCODER = 1ULL << 16,
-
- /** bit 17 is reserved */
-
- /** buffer is used as a camera HAL input */
- CAMERA = 1ULL << 18,
-
- /** bit 19 is reserved */
-
- /** buffer is used as a renderscript allocation */
- RENDERSCRIPT = 1ULL << 20,
-
- /** bit 21 is reserved */
- /** bit 22 is reserved */
-
- /**
- * buffer is used as as an OpenGL shader storage or uniform
- buffer object */
- GPU_DATA_BUFFER = 1ULL << 23,
-
- /** bits 24-27 are reserved for future versions */
- /** bits 28-31 are reserved for vendor extensions */
-
- /** bits 32-47 are reserved for future versions */
- /** bits 48-63 are reserved for vendor extensions */
-};
-
-typedef uint64_t BufferDescriptor;
-typedef uint64_t Buffer;
diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp
deleted file mode 100644
index fb77ab3..0000000
--- a/graphics/allocator/2.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2016 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: "libVtsHalGraphicsAllocatorTestUtils",
- defaults: ["hidl_defaults"],
- srcs: ["VtsHalGraphicsAllocatorTestUtils.cpp"],
- shared_libs: [
- "android.hardware.graphics.allocator@2.0",
- ],
- static_libs: [
- "VtsHalHidlTargetTestBase",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-O0",
- "-g",
- ],
- export_include_dirs: ["."],
-}
-
-cc_test {
- name: "VtsHalGraphicsAllocatorV2_0TargetTest",
- defaults: ["hidl_defaults"],
- srcs: ["VtsHalGraphicsAllocatorV2_0TargetTest.cpp"],
- shared_libs: [
- "libbase",
- "liblog",
- "libcutils",
- "libhidlbase",
- "libhidltransport",
- "libnativehelper",
- "libutils",
- "android.hardware.graphics.allocator@2.0",
- ],
- static_libs: [
- "libVtsHalGraphicsAllocatorTestUtils",
- "VtsHalHidlTargetTestBase",
- ],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-O0",
- "-g",
- ]
-}
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
deleted file mode 100644
index 0dc43be..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.cpp
+++ /dev/null
@@ -1,183 +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 <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-Allocator::Allocator() { init(); }
-
-void Allocator::init() {
- mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
- ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
-
- std::vector<IAllocator::Capability> capabilities = getCapabilities();
- mCapabilities.insert(capabilities.begin(), capabilities.end());
-}
-
-sp<IAllocator> Allocator::getRaw() const { return mAllocator; }
-
-bool Allocator::hasCapability(IAllocator::Capability capability) const {
- return mCapabilities.count(capability) > 0;
-}
-
-std::vector<IAllocator::Capability> Allocator::getCapabilities() {
- std::vector<IAllocator::Capability> capabilities;
- mAllocator->getCapabilities(
- [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
-
- return capabilities;
-}
-
-std::string Allocator::dumpDebugInfo() {
- std::string debugInfo;
- mAllocator->dumpDebugInfo(
- [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
- return debugInfo;
-}
-
-std::unique_ptr<AllocatorClient> Allocator::createClient() {
- std::unique_ptr<AllocatorClient> client;
- mAllocator->createClient([&](const auto& tmpError, const auto& tmpClient) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
- client = std::make_unique<AllocatorClient>(tmpClient);
- });
-
- return client;
-}
-
-AllocatorClient::AllocatorClient(const sp<IAllocatorClient>& client)
- : mClient(client) {}
-
-AllocatorClient::~AllocatorClient() {
- for (auto buffer : mBuffers) {
- EXPECT_EQ(Error::NONE, mClient->free(buffer))
- << "failed to free buffer " << buffer;
- }
- mBuffers.clear();
-
- for (auto descriptor : mDescriptors) {
- EXPECT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
- << "failed to destroy descriptor " << descriptor;
- }
- mDescriptors.clear();
-}
-
-sp<IAllocatorClient> AllocatorClient::getRaw() const { return mClient; }
-
-BufferDescriptor AllocatorClient::createDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& info) {
- BufferDescriptor descriptor = 0;
- mClient->createDescriptor(
- info, [&](const auto& tmpError, const auto& tmpDescriptor) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
- descriptor = tmpDescriptor;
-
- EXPECT_TRUE(mDescriptors.insert(descriptor).second)
- << "duplicated descriptor id " << descriptor;
- });
-
- return descriptor;
-}
-
-void AllocatorClient::destroyDescriptor(BufferDescriptor descriptor) {
- ASSERT_EQ(Error::NONE, mClient->destroyDescriptor(descriptor))
- << "failed to destroy descriptor " << descriptor;
-
- mDescriptors.erase(descriptor);
-}
-
-Error AllocatorClient::testAllocate(
- const std::vector<BufferDescriptor>& descriptors) {
- return mClient->testAllocate(descriptors);
-}
-
-bool AllocatorClient::testAllocate(BufferDescriptor descriptor) {
- std::vector<BufferDescriptor> descriptors(1, descriptor);
- Error error = testAllocate(descriptors);
- return (error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-Error AllocatorClient::allocate(
- const std::vector<BufferDescriptor>& descriptors,
- std::vector<Buffer>& buffers) {
- Error error = Error::NO_RESOURCES;
- mClient->allocate(descriptors, [&](const auto& tmpError,
- const auto& tmpBuffers) {
- ASSERT_TRUE(tmpError == Error::NONE || tmpError == Error::NOT_SHARED)
- << "failed to allocate buffer";
- ASSERT_EQ(descriptors.size(), tmpBuffers.size()) << "invalid buffer count";
-
- error = tmpError;
- buffers = tmpBuffers;
-
- for (auto buffer : buffers) {
- EXPECT_TRUE(mBuffers.insert(buffer).second)
- << "duplicated buffer id " << buffer;
- }
- });
-
- return error;
-}
-
-Buffer AllocatorClient::allocate(BufferDescriptor descriptor) {
- std::vector<BufferDescriptor> descriptors(1, descriptor);
- std::vector<Buffer> buffers;
- allocate(descriptors, buffers);
- if (::testing::Test::HasFatalFailure()) {
- return 0;
- }
-
- return buffers[0];
-}
-
-void AllocatorClient::free(Buffer buffer) {
- ASSERT_EQ(Error::NONE, mClient->free(buffer))
- << "failed to free buffer " << buffer;
-
- mBuffers.erase(buffer);
-}
-
-native_handle_t* AllocatorClient::exportHandle(BufferDescriptor descriptor,
- Buffer buffer) {
- native_handle_t* handle;
- mClient->exportHandle(
- descriptor, buffer, [&](const auto& tmpError, const auto& tmpHandle) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to export buffer handle";
- ASSERT_NE(nullptr, tmpHandle.getNativeHandle())
- << "invalid buffer handle";
-
- handle = native_handle_clone(tmpHandle.getNativeHandle());
- ASSERT_NE(nullptr, handle) << "failed to clone handle";
- });
-
- return handle;
-}
-
-} // namespace tests
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
deleted file mode 100644
index c9bfe8f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorTestUtils.h
+++ /dev/null
@@ -1,98 +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 VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-#define VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
-
-#include <memory>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-
-class AllocatorClient;
-
-// A wrapper to IAllocator.
-class Allocator {
- public:
- Allocator();
-
- sp<IAllocator> getRaw() const;
-
- // Returns true when the allocator supports the specified capability.
- bool hasCapability(IAllocator::Capability capability) const;
-
- std::vector<IAllocator::Capability> getCapabilities();
- std::string dumpDebugInfo();
- std::unique_ptr<AllocatorClient> createClient();
-
- private:
- void init();
-
- sp<IAllocator> mAllocator;
- std::unordered_set<IAllocator::Capability> mCapabilities;
-};
-
-// A wrapper to IAllocatorClient.
-class AllocatorClient {
- public:
- AllocatorClient(const sp<IAllocatorClient>& client);
- ~AllocatorClient();
-
- sp<IAllocatorClient> getRaw() const;
-
- BufferDescriptor createDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& info);
- void destroyDescriptor(BufferDescriptor descriptor);
-
- Error testAllocate(const std::vector<BufferDescriptor>& descriptors);
- bool testAllocate(BufferDescriptor descriptor);
-
- Error allocate(const std::vector<BufferDescriptor>& descriptors,
- std::vector<Buffer>& buffers);
- Buffer allocate(BufferDescriptor descriptor);
- void free(Buffer buffer);
-
- // Returns a handle to the buffer. The ownership of the handle is
- // transferred to the caller.
- native_handle_t* exportHandle(BufferDescriptor descriptor, Buffer buffer);
-
- private:
- sp<IAllocatorClient> mClient;
-
- // Keep track of all descriptors and buffers. When a test fails with
- // ASSERT_*, the destructor will clean up the resources for the test.
- std::unordered_set<BufferDescriptor> mDescriptors;
- std::unordered_set<Buffer> mBuffers;
-};
-
-} // namespace tests
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // VTS_HAL_GRAPHICS_ALLOCATOR_UTILS
diff --git a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp b/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
deleted file mode 100644
index b1c764f..0000000
--- a/graphics/allocator/2.0/vts/functional/VtsHalGraphicsAllocatorV2_0TargetTest.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2016 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_allocator_hidl_hal_test"
-
-#include <android-base/logging.h>
-#include <VtsHalHidlTargetTestBase.h>
-
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace tests {
-namespace {
-
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME) \
- do { \
- if (!mAllocator->hasCapability(FEATURE_NAME)) { \
- std::cout << "[ SKIPPED ] Feature " << #FEATURE_NAME \
- << " not supported" << std::endl; \
- return; \
- } \
- } while (0)
-
-class GraphicsAllocatorHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
- ASSERT_NO_FATAL_FAILURE(mClient = mAllocator->createClient());
-
- mDummyDescriptorInfo.width = 64;
- mDummyDescriptorInfo.height = 64;
- mDummyDescriptorInfo.layerCount = 1;
- mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
- mDummyDescriptorInfo.producerUsageMask =
- static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
- mDummyDescriptorInfo.consumerUsageMask =
- static_cast<uint64_t>(ConsumerUsage::CPU_READ);
- }
-
- void TearDown() override {}
-
- std::unique_ptr<Allocator> mAllocator;
- std::unique_ptr<AllocatorClient> mClient;
- IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
-};
-
-TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) {
- auto capabilities = mAllocator->getCapabilities();
- for (auto cap : capabilities) {
- EXPECT_NE(IAllocator::Capability::INVALID, cap);
- }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) {
- mAllocator->dumpDebugInfo();
-}
-
-TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) {
- BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(descriptor =
- mClient->createDescriptor(mDummyDescriptorInfo));
- mClient->destroyDescriptor(descriptor);
-}
-
-/**
- * Test testAllocate with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) {
- CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
- BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(descriptor =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- ASSERT_TRUE(mClient->testAllocate(descriptor));
-}
-
-/**
- * Test testAllocate with two buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) {
- CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
-
- BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(descriptor =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- hidl_vec<BufferDescriptor> descriptors;
- descriptors.resize(2);
- descriptors[0] = descriptor;
- descriptors[1] = descriptor;
-
- auto error = mClient->testAllocate(descriptors);
- ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
-}
-
-/**
- * Test allocate/free with a single buffer descriptor.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) {
- BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(descriptor =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
- mClient->free(buffer);
-}
-
-/**
- * Test allocate/free with an array of buffer descriptors.
- */
-TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) {
- BufferDescriptor descriptor1;
- ASSERT_NO_FATAL_FAILURE(descriptor1 =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- BufferDescriptor descriptor2;
- ASSERT_NO_FATAL_FAILURE(descriptor2 =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- hidl_vec<BufferDescriptor> descriptors;
- descriptors.resize(3);
- descriptors[0] = descriptor1;
- descriptors[1] = descriptor1;
- descriptors[2] = descriptor2;
-
- std::vector<Buffer> buffers;
- ASSERT_NO_FATAL_FAILURE(mClient->allocate(descriptors, buffers));
-
- for (auto buf : buffers) {
- mClient->free(buf);
- }
-}
-
-TEST_F(GraphicsAllocatorHidlTest, ExportHandle) {
- BufferDescriptor descriptor;
- ASSERT_NO_FATAL_FAILURE(descriptor =
- mClient->createDescriptor(mDummyDescriptorInfo));
-
- Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = mClient->allocate(descriptor));
-
- native_handle_t* handle;
- ASSERT_NO_FATAL_FAILURE(handle = mClient->exportHandle(descriptor, buffer));
-
- native_handle_close(handle);
- native_handle_delete(handle);
-}
-
-} // namespace anonymous
-} // namespace tests
-} // namespace V2_0
-} // namespace allocator
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
-
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
-
- return status;
-}
diff --git a/graphics/common/1.0/Android.mk b/graphics/common/1.0/Android.mk
index c08053d..ae80c6a 100644
--- a/graphics/common/1.0/Android.mk
+++ b/graphics/common/1.0/Android.mk
@@ -13,6 +13,25 @@
HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
#
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
# Build types.hal (ColorMode)
#
GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
@@ -139,6 +158,25 @@
HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
#
+# Build types.hal (BufferUsage)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/BufferUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.graphics.common@1.0::types.BufferUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
# Build types.hal (ColorMode)
#
GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal
index 979e4c4..3bd1ec1 100644
--- a/graphics/common/1.0/types.hal
+++ b/graphics/common/1.0/types.hal
@@ -181,9 +181,17 @@
* - GRALLOC_USAGE_SW_*
* - GRALLOC_USAGE_RENDERSCRIPT
*
- * When used with ANativeWindow, the dataSpace should be
- * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
- * extra metadata to define.
+ * When used with ANativeWindow, the mapping of the dataSpace field to
+ * buffer contents for RAW16 is as follows:
+ *
+ * dataSpace value | Buffer contents
+ * -------------------------------+-----------------------------------------
+ * HAL_DATASPACE_ARBITRARY | Raw image sensor data, layout is as
+ * | defined above.
+ * HAL_DATASPACE_DEPTH | Unprocessed implementation-dependent raw
+ * | depth measurements, opaque with 16 bit
+ * | samples.
+ * Other | Unsupported
*/
RAW16 = 0x20,
@@ -442,6 +450,90 @@
};
/**
+ * Buffer usage definitions.
+ */
+enum BufferUsage : uint64_t {
+ /** bit 0-3 is an enum */
+ CPU_READ_MASK = 0xfULL,
+ /** buffer is never read by CPU */
+ CPU_READ_NEVER = 0,
+ /** buffer is rarely read by CPU */
+ CPU_READ_RARELY = 2,
+ /** buffer is often read by CPU */
+ CPU_READ_OFTEN = 3,
+
+ /** bit 4-7 is an enum */
+ CPU_WRITE_MASK = 0xfULL << 4,
+ /** buffer is never written by CPU */
+ CPU_WRITE_NEVER = 0 << 4,
+ /** buffer is rarely written by CPU */
+ CPU_WRITE_RARELY = 2 << 4,
+ /** buffer is often written by CPU */
+ CPU_WRITE_OFTEN = 3 << 4,
+
+ /** buffer is used as a GPU texture */
+ GPU_TEXTURE = 1ULL << 8,
+
+ /** buffer is used as a GPU render target */
+ GPU_RENDER_TARGET = 1ULL << 9,
+
+ /** bit 10 must be zero */
+
+ /** buffer is used as a composer HAL overlay layer */
+ COMPOSER_OVERLAY = 1ULL << 11,
+ /** buffer is used as a composer HAL client target */
+ COMPOSER_CLIENT_TARGET = 1ULL << 12,
+
+ /** bit 13 must be zero */
+
+ /**
+ * Buffer is allocated with hardware-level protection against copying the
+ * contents (or information derived from the contents) into unprotected
+ * memory.
+ */
+ PROTECTED = 1ULL << 14,
+
+ /** buffer is used as a hwcomposer HAL cursor layer */
+ COMPOSER_CURSOR = 1ULL << 15,
+
+ /** buffer is used as a video encoder input */
+ VIDEO_ENCODER = 1ULL << 16,
+
+ /** buffer is used as a camera HAL output */
+ CAMERA_OUTPUT = 1ULL << 17,
+
+ /** buffer is used as a camera HAL input */
+ CAMERA_INPUT = 1ULL << 18,
+
+ /** bit 19 must be zero */
+
+ /** buffer is used as a renderscript allocation */
+ RENDERSCRIPT = 1ULL << 20,
+
+ /** bit 21 must be zero */
+
+ /** buffer is used as a video decoder output */
+ VIDEO_DECODER = 1ULL << 22,
+
+ /** buffer is used as a sensor direct report output */
+ SENSOR_DIRECT_DATA = 1ULL << 23,
+
+ /**
+ * buffer is used as as an OpenGL shader storage or uniform
+ * buffer object
+ */
+ GPU_DATA_BUFFER = 1ULL << 24,
+
+ /** bits 25-27 must be zero and are reserved for future versions */
+ /** bits 28-31 are reserved for vendor extensions */
+ VENDOR_MASK = 0xfULL << 28,
+
+ /** bits 32-47 must be zero and are reserved for future versions */
+ /** bits 48-63 are reserved for vendor extensions */
+ VENDOR_MASK_HI = 0xffffULL << 48,
+};
+
+/**
* Transformation definitions
*
* IMPORTANT NOTE:
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 8e1f925..66323d4 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -52,7 +52,6 @@
],
static_libs: [
"libhwcomposer-command-buffer",
- "libVtsHalGraphicsAllocatorTestUtils",
"libVtsHalGraphicsComposerTestUtils",
"libVtsHalGraphicsMapperTestUtils",
"VtsHalHidlTargetTestBase",
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0da3a33..387222f 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -18,7 +18,6 @@
#include <IComposerCommandBuffer.h>
#include <android-base/logging.h>
-#include "VtsHalGraphicsAllocatorTestUtils.h"
#include "VtsHalGraphicsComposerTestUtils.h"
#include "VtsHalGraphicsMapperTestUtils.h"
@@ -40,22 +39,15 @@
namespace tests {
namespace {
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::ConsumerUsage;
-using android::hardware::graphics::allocator::V2_0::IAllocator;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::ProducerUsage;
-using android::hardware::graphics::allocator::V2_0::tests::Allocator;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
+using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::ColorTransform;
using android::hardware::graphics::common::V1_0::Dataspace;
using android::hardware::graphics::common::V1_0::PixelFormat;
using android::hardware::graphics::common::V1_0::Transform;
using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Mapper;
-using GrallocError = android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
// IComposerCallback to be installed with IComposerClient::registerCallback.
class GraphicsComposerCallback : public IComposerCallback {
@@ -409,9 +401,7 @@
void SetUp() override {
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
- ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
- ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
- ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
mWriter = std::make_unique<CommandWriterBase>(1024);
mReader = std::make_unique<CommandReader>();
@@ -422,15 +412,15 @@
}
const native_handle_t* allocate() {
- IAllocatorClient::BufferDescriptorInfo info{};
- info.width = 64;
- info.height = 64;
- info.layerCount = 1;
- info.format = PixelFormat::RGBA_8888;
- info.producerUsageMask = static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
- info.consumerUsageMask = static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+ IMapper::BufferDescriptorInfo info{};
+ info.width = 64;
+ info.height = 64;
+ info.layerCount = 1;
+ info.format = PixelFormat::RGBA_8888;
+ info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::CPU_READ_OFTEN);
- return mMapper->allocate(mAllocatorClient, info);
+ return mGralloc->allocate(info);
}
void execute() {
@@ -507,9 +497,7 @@
std::unique_ptr<CommandReader> mReader;
private:
- std::unique_ptr<Allocator> mAllocator;
- std::unique_ptr<AllocatorClient> mAllocatorClient;
- std::unique_ptr<Mapper> mMapper;
+ std::unique_ptr<Gralloc> mGralloc;
};
/**
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
index 98a509b..cc2bd73 100644
--- a/graphics/mapper/2.0/Android.bp
+++ b/graphics/mapper/2.0/Android.bp
@@ -51,7 +51,6 @@
"liblog",
"libutils",
"libcutils",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
@@ -60,7 +59,6 @@
"libhidltransport",
"libhwbinder",
"libutils",
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.common@1.0",
"android.hidl.base@1.0",
],
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
index 573dcd0..246be24 100644
--- a/graphics/mapper/2.0/IMapper.hal
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -16,10 +16,39 @@
package android.hardware.graphics.mapper@2.0;
-import android.hardware.graphics.common@1.0::PixelFormat;
-import android.hardware.graphics.allocator@2.0;
+import android.hardware.graphics.common@1.0;
interface IMapper {
+ struct BufferDescriptorInfo {
+ /**
+ * The width specifies how many columns of pixels must be in the
+ * allocated buffer, but does not necessarily represent the offset in
+ * columns between the same column in adjacent rows. The rows may be
+ * padded.
+ */
+ uint32_t width;
+
+ /**
+ * The height specifies how many rows of pixels must be in the
+ * allocated buffer.
+ */
+ uint32_t height;
+
+ /**
+ * The number of image layers that must be in the allocated buffer.
+ */
+ uint32_t layerCount;
+
+ /** Buffer pixel format. */
+ PixelFormat format;
+
+ /**
+ * Buffer usage mask; valid flags can be found in the definition of
+ * BufferUsage.
+ */
+ bitfield<BufferUsage> usage;
+ };
+
struct Rect {
int32_t left;
int32_t top;
@@ -28,170 +57,76 @@
};
/**
- * Adds a reference to the given buffer handle.
+ * Creates a buffer descriptor. The descriptor can be used with IAllocator
+ * to allocate buffers.
*
- * A buffer handle received from a remote process or exported by
- * IAllocator::exportHandle is unknown to the mapper. There is also no
- * guarantee that the buffer's backing store will stay alive. This
- * function must be called at least once in both cases to intrdouce the
- * buffer handle to the mapper and to secure the backing store. It may
- * also be called more than once to increase the reference count if two
- * components in the same process want to interact with the buffer
- * independently.
+ * Since the buffer descriptor fully describes a buffer, any device
+ * dependent or device independent checks must be performed here whenever
+ * possible. Specifically, when layered buffers are not supported, this
+ * function must return UNSUPPORTED if layerCount is great than 1.
*
- * @param bufferHandle is the buffer to which a reference must be added.
+ * @param descriptorInfo specifies the attributes of the descriptor.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid
- * NO_RESOURCES when it is not possible to add a
- * reference to this buffer at this time
+ * BAD_VALUE when any of the specified attributes is
+ * invalid or conflicting.
+ * NO_RESOURCES when the creation cannot be fullfilled at
+ * this time.
+ * UNSUPPORTED when any of the specified attributes is
+ * not supported.
+ * @return descriptor is the newly created buffer descriptor.
*/
@entry
@callflow(next="*")
- retain(handle bufferHandle) generates (Error error);
+ createDescriptor(BufferDescriptorInfo descriptorInfo)
+ generates (Error error,
+ BufferDescriptor descriptor);
/**
- * Removes a reference from the given buffer buffer.
+ * Imports a raw buffer handle to create an imported buffer handle for use
+ * with the rest of the mapper or with other in-process libraries.
*
- * If no references remain, the buffer handle must be freed with
- * native_handle_close/native_handle_delete by the mapper. When the last
- * buffer handle referring to a particular backing store is freed, that
- * backing store must also be freed.
+ * A buffer handle is considered raw when it is cloned or when it is
+ * received from another HAL or another process. A raw buffer handle must
+ * not be used to access the underlying graphics buffer. It must be
+ * imported to create an imported handle first.
*
- * @param bufferHandle is the buffer from which a reference must be
- * removed.
+ * This function must at least validate the raw handle before creating the
+ * imported handle. It must also support importing the same raw handle
+ * multiple times to create multiple imported handles. The imported handle
+ * must be considered valid everywhere in the process, including in
+ * another instance of the mapper.
+ *
+ * @param rawHandle is the raw buffer handle to import.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
+ * BAD_BUFFER when the raw handle is invalid.
+ * NO_RESOURCES when the raw handle cannot be imported at
+ * this time.
+ * @return buffer is the imported buffer handle and has the type
+ * buffer_handle_t.
+ */
+ @entry
+ @callflow(next="*")
+ importBuffer(handle rawHandle) generates (Error error, pointer buffer);
+
+ /**
+ * Frees a buffer handle. Buffer handles returned by importBuffer must be
+ * freed with this function when no longer needed.
+ *
+ * This function must free up all resources allocated by importBuffer for
+ * the imported handle. For example, if the imported handle was created
+ * with native_handle_create, this function must call native_handle_close
+ * and native_handle_delete.
+ *
+ * @return error is NONE upon success. Otherwise,
+ * BAD_BUFFER when the buffer is invalid.
*/
@exit
- release(handle bufferHandle) generates (Error error);
-
- /**
- * Gets the width and height of the buffer in pixels.
- *
- * See IAllocator::BufferDescriptorInfo for more information.
- *
- * @param bufferHandle is the buffer from which to get the dimensions.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return width is the width of the buffer in pixels.
- * @return height is the height of the buffer in pixels.
- */
@callflow(next="*")
- getDimensions(handle bufferHandle)
- generates (Error error,
- uint32_t width,
- uint32_t height);
-
- /**
- * Gets the format of the buffer.
- *
- * See IAllocator::BufferDescriptorInfo for more information.
- *
- * @param bufferHandle is the buffer from which to get format.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return format is the format of the buffer.
- */
- @callflow(next="*")
- getFormat(handle bufferHandle)
- generates (Error error,
- PixelFormat format);
-
- /**
- * Gets the number of layers of the buffer.
- *
- * See IAllocator::BufferDescriptorInfo for more information.
- *
- * @param bufferHandle is the buffer from which to get format.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return layerCount is the number of layers of the buffer.
- */
- @callflow(next="*")
- getLayerCount(handle bufferHandle)
- generates (Error error,
- uint32_t layerCount);
-
- /**
- * Gets the producer usage flags which were used to allocate this buffer.
- *
- * See IAllocator::BufferDescriptorInfo for more information.
- *
- * @param bufferHandle is the buffer from which to get the producer usage
- * flags.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return usageMask contains the producer usage flags of the buffer.
- */
- @callflow(next="*")
- getProducerUsageMask(handle bufferHandle)
- generates (Error error,
- uint64_t usageMask);
-
- /**
- * Gets the consumer usage flags which were used to allocate this buffer.
- *
- * See IAllocator::BufferDescriptorInfo for more information.
- *
- * @param bufferHandle is the buffer from which to get the consumer usage
- * flags.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return usageMask contains the consumer usage flags of the buffer.
- */
- @callflow(next="*")
- getConsumerUsageMask(handle bufferHandle)
- generates (Error error,
- uint64_t usageMask);
-
- /**
- * Gets a value that uniquely identifies the backing store of the given
- * buffer.
- *
- * Buffers which share a backing store should return the same value from
- * this function. If the buffer is present in more than one process, the
- * backing store value for that buffer is not required to be the same in
- * every process.
- *
- * @param device is the mapper device.
- * @param bufferHandle is the buffer from which to get the backing store
- * identifier.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return store is the backing store identifier for this buffer.
- */
- @callflow(next="*")
- getBackingStore(handle bufferHandle)
- generates (Error error,
- BackingStore store);
-
- /**
- * Gets the stride of the buffer in pixels.
- *
- * The stride is the offset in pixel-sized elements between the same
- * column in two adjacent rows of pixels. This may not be equal to the
- * width of the buffer.
- *
- * @param device is the mapper device.
- * @param bufferHandle is the buffer from which to get the stride.
- * @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * UNDEFINED when the notion of a stride is not
- * meaningful for the buffer format.
- * @return store is the stride in pixels.
- */
- @callflow(next="*")
- getStride(handle bufferHandle)
- generates (Error error,
- uint32_t stride);
+ freeBuffer(pointer buffer) generates (Error error);
/**
* Locks the given buffer for the specified CPU usage.
*
- * Exactly one of producerUsageMask and consumerUsageMask must be 0. The
- * usage which is not 0 must be one of the *Usage::CPU* values, as
- * applicable. Locking a buffer for a non-CPU usage is not supported.
- *
* Locking the same buffer simultaneously from multiple threads is
* permitted, but if any of the threads attempt to lock the buffer for
* writing, the behavior is undefined, except that it must not cause
@@ -209,39 +144,27 @@
* address will represent the top-left corner of the entire buffer, even
* if accessRegion does not begin at the top-left corner.
*
- * acquireFence is a file descriptor referring to a acquire sync fence
- * object, which will be signaled when it is safe for the device to access
- * the contents of the buffer (prior to locking). If it is already safe to
- * access the buffer contents, -1 may be passed instead.
- *
- * @param bufferHandle is the buffer to lock.
- * @param producerUsageMask contains the producer usage flags to request;
- * either this or consumerUsagemask must be 0, and the other must
- * be a CPU usage.
- * @param consumerUsageMask contains the consumer usage flags to request;
- * either this or producerUsageMask must be 0, and the other must
- * be a CPU usage.
+ * @param buffer is the buffer to lock.
+ * @param cpuUsage specifies one or more CPU usage flags to request.
* @param accessRegion is the portion of the buffer that the client
* intends to access.
- * @param acquireFence is a sync fence file descriptor as described above.
+ * @param acquireFence, when non-empty, is a handle containing a file
+ * descriptor referring to a sync fence object, which will be
+ * signaled when it is safe for the mapper to lock the buffer. If
+ * it is already safe to lock, acquireFence is empty.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * BAD_VALUE when neither or both of producerUsageMask
- * and consumerUsageMask were 0, or the usage
- * which was not 0 was not a CPU usage.
+ * BAD_BUFFER when the buffer is invalid or is
+ * incompatible with this function.
+ * BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+ * flags, or is incompatible with the buffer.
* NO_RESOURCES when the buffer cannot be locked at this
* time, but locking may succeed at a future
* time.
- * UNSUPPORTED when the buffer cannot be locked with the
- * given usage, and any future attempts at
- * locking will also fail.
- * @return data will be filled with a CPU-accessible pointer to the buffer
- * data.
+ * @return data is a CPU-accessible pointer to the buffer data.
*/
@callflow(next="unlock")
- lock(handle bufferHandle,
- uint64_t producerUsageMask,
- uint64_t consumerUsageMask,
+ lock(pointer buffer,
+ bitfield<BufferUsage> cpuUsage,
Rect accessRegion,
handle acquireFence)
generates (Error error,
@@ -249,7 +172,7 @@
/**
* This is largely the same as lock(), except that instead of returning a
- * pointer directly to the buffer data, it returns an FlexLayout struct
+ * pointer directly to the buffer data, it returns an YCbCrLayout struct
* describing how to access the data planes.
*
* This function must work on buffers with PixelFormat::YCbCr_*_888 if
@@ -257,67 +180,46 @@
* multimedia codecs when they are configured with a
* flexible-YUV-compatible color format.
*
- * This function may also be called on buffers of other formats, including
- * non-YUV formats, but if the buffer format is not compatible with a
- * flexible representation, it may return UNSUPPORTED.
- *
- * @param device is the mapper device.
- * @param bufferHandle is the buffer to lock.
- * @param producerUsageMask contains the producer usage flags to request;
- * either this or consumerUsagemask must be 0, and the other must
- * be a CPU usage.
- * @param consumerUsageMask contains the consumer usage flags to request;
- * either this or producerUsageMask must be 0, and the other must
- * be a CPU usage.
+ * @param buffer is the buffer to lock.
+ * @param cpuUsage specifies one or more CPU usage flags to request.
* @param accessRegion is the portion of the buffer that the client
* intends to access.
- * @param acquireFence is a sync fence file descriptor as described in
- * lock().
+ * @param acquireFence, when non-empty, is a handle containing a file
+ * descriptor referring to a sync fence object, which will be
+ * signaled when it is safe for the mapper to lock the buffer. If
+ * it is already safe to lock, acquireFence is empty.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * BAD_VALUE when neither or both of producerUsageMask
- * and consumerUsageMask were 0, or the usage
- * which was not 0 was not a CPU usage.
+ * BAD_BUFFER when the buffer is invalid or is
+ * incompatible with this function.
+ * BAD_VALUE when cpuUsage is 0, contains non-CPU usage
+ * flags, or is incompatible with the buffer.
* NO_RESOURCES when the buffer cannot be locked at this
* time, but locking may succeed at a future
* time.
- * UNSUPPORTED when the buffer cannot be locked with the
- * given usage, and any future attempts at
- * locking will also fail.
- * @return flexLayout will be filled with the description of the planes in
- * the buffer.
+ * @return layout is the data layout of the buffer.
*/
@callflow(next="unlock")
- lockFlex(handle bufferHandle,
- uint64_t producerUsageMask,
- uint64_t consumerUsageMask,
- Rect accessRegion,
- handle acquireFence)
+ lockYCbCr(pointer buffer,
+ bitfield<BufferUsage> cpuUsage,
+ Rect accessRegion,
+ handle acquireFence)
generates (Error error,
- FlexLayout layout);
+ YCbCrLayout layout);
/**
- * This function indicates to the device that the client will be done with
- * the buffer when releaseFence signals.
+ * Unlocks a buffer to indicate all CPU accesses to the buffer have
+ * completed.
*
- * releaseFence will be filled with a file descriptor referring to a
- * release sync fence object, which will be signaled when it is safe to
- * access the contents of the buffer (after the buffer has been unlocked).
- * If it is already safe to access the buffer contents, then -1 may be
- * returned instead.
- *
- * This function is used to unlock both buffers locked by lock() and those
- * locked by lockFlex().
- *
- * @param device is the mapper device.
- * @param bufferHandle is the buffer to unlock.
+ * @param buffer is the buffer to unlock.
* @return error is NONE upon success. Otherwise,
- * BAD_BUFFER when the buffer handle is invalid.
- * @return releaseFence is a sync fence file descriptor as described
- * above.
+ * BAD_BUFFER when the buffer is invalid or not locked.
+ * @return releaseFence, when non-empty, is a handle containing a file
+ * descriptor referring to a sync fence object. The sync fence
+ * object will be signaled when the mapper has completed any
+ * pending work.
*/
@callflow(next="*")
- unlock(handle bufferHandle)
+ unlock(pointer buffer)
generates (Error error,
handle releaseFence);
};
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 1dc5aea..090c61f 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,10 +18,9 @@
defaults: ["hidl_defaults"],
proprietary: true,
relative_install_path: "hw",
- srcs: ["GrallocMapper.cpp"],
+ srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
cppflags: ["-Wall", "-Wextra"],
shared_libs: [
- "android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
"libbase",
"libcutils",
@@ -29,6 +28,12 @@
"libhidlbase",
"libhidltransport",
"liblog",
+ "libsync",
"libutils",
],
}
+
+cc_library_static {
+ name: "libgrallocmapperincludes",
+ export_include_dirs: ["."],
+}
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
new file mode 100644
index 0000000..28f5016
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2016 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 "Gralloc0Mapper"
+
+#include "Gralloc0Mapper.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
+ : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
+ mMinor(module->module_api_version & 0xff) {
+ mCapabilities.highUsageBits = false;
+ mCapabilities.layeredBuffers = false;
+ mCapabilities.unregisterImplyDelete = false;
+}
+
+Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+ int result = mModule->registerBuffer(mModule, bufferHandle);
+ return result ? Error::BAD_BUFFER : Error::NONE;
+}
+
+void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+ mModule->unregisterBuffer(mModule, bufferHandle);
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData) {
+ int result;
+ void* data = nullptr;
+ if (mMinor >= 3 && mModule->lockAsync) {
+ // Dup fenceFd as it is going to be owned by gralloc. Note that it is
+ // gralloc's responsibility to close it, even on locking errors.
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
+ accessRegion.left, accessRegion.top,
+ accessRegion.width, accessRegion.height,
+ &data, fenceFd);
+ } else {
+ waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
+
+ result = mModule->lock(mModule, bufferHandle, cpuUsage,
+ accessRegion.left, accessRegion.top,
+ accessRegion.width, accessRegion.height, &data);
+ }
+
+ if (result) {
+ return Error::BAD_VALUE;
+ } else {
+ *outData = data;
+ return Error::NONE;
+ }
+}
+
+Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ YCbCrLayout* outLayout) {
+ int result;
+ android_ycbcr ycbcr = {};
+ if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+ // Dup fenceFd as it is going to be owned by gralloc. Note that it is
+ // gralloc's responsibility to close it, even on locking errors.
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
+ accessRegion.left, accessRegion.top,
+ accessRegion.width,
+ accessRegion.height, &ycbcr, fenceFd);
+ } else {
+ waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
+
+ if (mModule->lock_ycbcr) {
+ result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
+ accessRegion.left, accessRegion.top,
+ accessRegion.width,
+ accessRegion.height, &ycbcr);
+ } else {
+ result = -EINVAL;
+ }
+ }
+
+ if (result) {
+ return Error::BAD_VALUE;
+ } else {
+ outLayout->y = ycbcr.y;
+ outLayout->cb = ycbcr.cb;
+ outLayout->cr = ycbcr.cr;
+ outLayout->yStride = ycbcr.ystride;
+ outLayout->cStride = ycbcr.cstride;
+ outLayout->chromaStep = ycbcr.chroma_step;
+ return Error::NONE;
+ }
+}
+
+Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+ int* outFenceFd) {
+ int result;
+ int fenceFd = -1;
+ if (mMinor >= 3 && mModule->unlockAsync) {
+ result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+ } else {
+ result = mModule->unlock(mModule, bufferHandle);
+ }
+
+ if (result) {
+ // we always own the fenceFd even when unlock failed
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+
+ return Error::BAD_VALUE;
+ } else {
+ *outFenceFd = fenceFd;
+ return Error::NONE;
+ }
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h
new file mode 100644
index 0000000..e792a69
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc0Mapper.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 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_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc0Mapper : public GrallocMapper {
+ public:
+ Gralloc0Mapper(const hw_module_t* module);
+
+ private:
+ Error registerBuffer(buffer_handle_t bufferHandle) override;
+ void unregisterBuffer(buffer_handle_t bufferHandle) override;
+ Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData) override;
+ Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ YCbCrLayout* outLayout) override;
+ Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+ const gralloc_module_t* mModule;
+ uint8_t mMinor;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
new file mode 100644
index 0000000..c1e5adc
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2016 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 "Gralloc1Mapper"
+
+#include "Gralloc1Mapper.h"
+
+#include <vector>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+
+Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
+ : mDevice(nullptr), mDispatch() {
+ int result = gralloc1_open(module, &mDevice);
+ if (result) {
+ LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+ strerror(-result));
+ }
+
+ initCapabilities();
+ initDispatch();
+}
+
+Gralloc1Mapper::~Gralloc1Mapper() {
+ gralloc1_close(mDevice);
+}
+
+void Gralloc1Mapper::initCapabilities() {
+ mCapabilities.highUsageBits = true;
+ mCapabilities.layeredBuffers = false;
+ mCapabilities.unregisterImplyDelete = false;
+
+ uint32_t count = 0;
+ mDevice->getCapabilities(mDevice, &count, nullptr);
+
+ std::vector<int32_t> capabilities(count);
+ mDevice->getCapabilities(mDevice, &count, capabilities.data());
+ capabilities.resize(count);
+
+ for (auto capability : capabilities) {
+ switch (capability) {
+ case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+ mCapabilities.layeredBuffers = true;
+ break;
+ case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+ mCapabilities.unregisterImplyDelete = true;
+ break;
+ }
+ }
+}
+
+template <typename T>
+void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
+ T* outPfn) {
+ auto pfn = mDevice->getFunction(mDevice, desc);
+ if (!pfn) {
+ LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
+ }
+
+ *outPfn = reinterpret_cast<T>(pfn);
+}
+
+void Gralloc1Mapper::initDispatch() {
+ initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
+ initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+ initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
+ &mDispatch.getNumFlexPlanes);
+ initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
+ initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
+ initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
+}
+
+Error Gralloc1Mapper::toError(int32_t error) {
+ switch (error) {
+ case GRALLOC1_ERROR_NONE:
+ return Error::NONE;
+ case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+ return Error::BAD_DESCRIPTOR;
+ case GRALLOC1_ERROR_BAD_HANDLE:
+ return Error::BAD_BUFFER;
+ case GRALLOC1_ERROR_BAD_VALUE:
+ return Error::BAD_VALUE;
+ case GRALLOC1_ERROR_NOT_SHARED:
+ return Error::NONE; // this is fine
+ case GRALLOC1_ERROR_NO_RESOURCES:
+ return Error::NO_RESOURCES;
+ case GRALLOC1_ERROR_UNDEFINED:
+ case GRALLOC1_ERROR_UNSUPPORTED:
+ default:
+ return Error::UNSUPPORTED;
+ }
+}
+
+bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
+ YCbCrLayout* outLayout) {
+ // must be YCbCr
+ if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+ return false;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ const auto& plane = flex.planes[i];
+ // must have 8-bit depth
+ if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+ return false;
+ }
+
+ if (plane.component == FLEX_COMPONENT_Y) {
+ // Y must not be interleaved
+ if (plane.h_increment != 1) {
+ return false;
+ }
+ } else {
+ // Cb and Cr can be interleaved
+ if (plane.h_increment != 1 && plane.h_increment != 2) {
+ return false;
+ }
+ }
+
+ if (!plane.v_increment) {
+ return false;
+ }
+ }
+
+ if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+ flex.planes[1].component != FLEX_COMPONENT_Cb ||
+ flex.planes[2].component != FLEX_COMPONENT_Cr) {
+ return false;
+ }
+
+ const auto& y = flex.planes[0];
+ const auto& cb = flex.planes[1];
+ const auto& cr = flex.planes[2];
+
+ if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+ return false;
+ }
+
+ outLayout->y = y.top_left;
+ outLayout->cb = cb.top_left;
+ outLayout->cr = cr.top_left;
+ outLayout->yStride = y.v_increment;
+ outLayout->cStride = cb.v_increment;
+ outLayout->chromaStep = cb.h_increment;
+
+ return true;
+}
+
+gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
+ return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+}
+
+Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
+ return toError(mDispatch.retain(mDevice, bufferHandle));
+}
+
+void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
+ mDispatch.release(mDevice, bufferHandle);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData) {
+ // Dup fenceFd as it is going to be owned by gralloc. Note that it is
+ // gralloc's responsibility to close it, even on locking errors.
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ const uint64_t consumerUsage =
+ cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+ const auto accessRect = asGralloc1Rect(accessRegion);
+ void* data = nullptr;
+ int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
+ consumerUsage, &accessRect, &data, fenceFd);
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outData = data;
+ }
+
+ return toError(error);
+}
+
+Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ YCbCrLayout* outLayout) {
+ // prepare flex layout
+ android_flex_layout flex = {};
+ int32_t error =
+ mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+ if (error != GRALLOC1_ERROR_NONE) {
+ return toError(error);
+ }
+ std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+ flex.planes = flexPlanes.data();
+
+ // Dup fenceFd as it is going to be owned by gralloc. Note that it is
+ // gralloc's responsibility to close it, even on locking errors.
+ if (fenceFd >= 0) {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0) {
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ const uint64_t consumerUsage =
+ cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+ const auto accessRect = asGralloc1Rect(accessRegion);
+ error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
+ &accessRect, &flex, fenceFd);
+ if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+ ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+
+ // undo the lock
+ fenceFd = -1;
+ mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+
+ error = GRALLOC1_ERROR_BAD_HANDLE;
+ }
+
+ return toError(error);
+}
+
+Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
+ int* outFenceFd) {
+ int fenceFd = -1;
+ int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+ if (error == GRALLOC1_ERROR_NONE) {
+ *outFenceFd = fenceFd;
+ } else if (fenceFd >= 0) {
+ // we always own the fenceFd even when unlock failed
+ close(fenceFd);
+ }
+
+ return toError(error);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h
new file mode 100644
index 0000000..452afdf
--- /dev/null
+++ b/graphics/mapper/2.0/default/Gralloc1Mapper.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 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_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
+
+#include "GrallocMapper.h"
+
+#include <hardware/gralloc1.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+class Gralloc1Mapper : public GrallocMapper {
+ public:
+ Gralloc1Mapper(const hw_module_t* module);
+ ~Gralloc1Mapper();
+
+ private:
+ void initCapabilities();
+
+ template <typename T>
+ void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+ void initDispatch();
+
+ static Error toError(int32_t error);
+ static bool toYCbCrLayout(const android_flex_layout& flex,
+ YCbCrLayout* outLayout);
+ static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
+
+ Error registerBuffer(buffer_handle_t bufferHandle) override;
+ void unregisterBuffer(buffer_handle_t bufferHandle) override;
+ Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData) override;
+ Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ YCbCrLayout* outLayout) override;
+ Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
+
+ gralloc1_device_t* mDevice;
+
+ struct {
+ GRALLOC1_PFN_RETAIN retain;
+ GRALLOC1_PFN_RELEASE release;
+ GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+ GRALLOC1_PFN_LOCK lock;
+ GRALLOC1_PFN_LOCK_FLEX lockFlex;
+ GRALLOC1_PFN_UNLOCK unlock;
+ } mDispatch;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
new file mode 100644
index 0000000..9b5ab04
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2016 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_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+/**
+ * BufferDescriptor is created by IMapper and consumed by IAllocator. It is
+ * versioned so that IMapper and IAllocator can be updated independently.
+ */
+constexpr uint32_t grallocBufferDescriptorSize = 7;
+constexpr uint32_t grallocBufferDescriptorMagicVersion = ((0x9487 << 16) | 0);
+
+inline BufferDescriptor grallocEncodeBufferDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ BufferDescriptor descriptor;
+ descriptor.resize(grallocBufferDescriptorSize);
+ descriptor[0] = grallocBufferDescriptorMagicVersion;
+ descriptor[1] = descriptorInfo.width;
+ descriptor[2] = descriptorInfo.height;
+ descriptor[3] = descriptorInfo.layerCount;
+ descriptor[4] = static_cast<uint32_t>(descriptorInfo.format);
+ descriptor[5] = static_cast<uint32_t>(descriptorInfo.usage);
+ descriptor[6] = static_cast<uint32_t>(descriptorInfo.usage >> 32);
+
+ return descriptor;
+}
+
+inline bool grallocDecodeBufferDescriptor(
+ const BufferDescriptor& descriptor,
+ IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+ if (descriptor.size() != grallocBufferDescriptorSize ||
+ descriptor[0] != grallocBufferDescriptorMagicVersion) {
+ return false;
+ }
+
+ *outDescriptorInfo = IMapper::BufferDescriptorInfo{
+ descriptor[1],
+ descriptor[2],
+ descriptor[3],
+ static_cast<PixelFormat>(descriptor[4]),
+ (static_cast<uint64_t>(descriptor[6]) << 32) | descriptor[5],
+ };
+
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace mapper
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
index 526aca2..339317a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -17,14 +17,14 @@
#include "GrallocMapper.h"
-#include <mutex>
-#include <vector>
-#include <unordered_map>
+#include "Gralloc0Mapper.h"
+#include "Gralloc1Mapper.h"
+#include "GrallocBufferDescriptor.h"
-#include <string.h>
+#include <inttypes.h>
-#include <hardware/gralloc1.h>
#include <log/log.h>
+#include <sync/sync.h>
namespace android {
namespace hardware {
@@ -33,374 +33,251 @@
namespace V2_0 {
namespace implementation {
-namespace {
-
-using android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::common::V1_0::BufferUsage;
using android::hardware::graphics::common::V1_0::PixelFormat;
-class GrallocMapperHal : public IMapper {
-public:
- GrallocMapperHal(const hw_module_t* module);
- ~GrallocMapperHal();
+std::mutex GrallocMapper::mMutex;
+std::unordered_set<buffer_handle_t> GrallocMapper::mRegisteredHandles;
- // IMapper interface
- Return<Error> retain(const hidl_handle& bufferHandle) override;
- Return<Error> release(const hidl_handle& bufferHandle) override;
- Return<void> getDimensions(const hidl_handle& bufferHandle,
- getDimensions_cb hidl_cb) override;
- Return<void> getFormat(const hidl_handle& bufferHandle,
- getFormat_cb hidl_cb) override;
- Return<void> getLayerCount(const hidl_handle& bufferHandle,
- getLayerCount_cb hidl_cb) override;
- Return<void> getProducerUsageMask(const hidl_handle& bufferHandle,
- getProducerUsageMask_cb hidl_cb) override;
- Return<void> getConsumerUsageMask(const hidl_handle& bufferHandle,
- getConsumerUsageMask_cb hidl_cb) override;
- Return<void> getBackingStore(const hidl_handle& bufferHandle,
- getBackingStore_cb hidl_cb) override;
- Return<void> getStride(const hidl_handle& bufferHandle,
- getStride_cb hidl_cb) override;
- Return<void> lock(const hidl_handle& bufferHandle,
- uint64_t producerUsageMask, uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
- lock_cb hidl_cb) override;
- Return<void> lockFlex(const hidl_handle& bufferHandle,
- uint64_t producerUsageMask, uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
- lockFlex_cb hidl_cb) override;
- Return<void> unlock(const hidl_handle& bufferHandle,
- unlock_cb hidl_cb) override;
+bool GrallocMapper::validateDescriptorInfo(
+ const BufferDescriptorInfo& descriptorInfo) const {
+ const uint64_t validUsageBits =
+ BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
+ BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
+ BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
+ BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+ BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+ BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+ (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
+ : static_cast<BufferUsage>(0));
-private:
- void initCapabilities();
-
- template<typename T>
- void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
- void initDispatch();
-
- static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
- static bool dupFence(const hidl_handle& fenceHandle, int* outFd);
-
- gralloc1_device_t* mDevice;
-
- struct {
- bool layeredBuffers;
- } mCapabilities;
-
- struct {
- GRALLOC1_PFN_RETAIN retain;
- GRALLOC1_PFN_RELEASE release;
- GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
- GRALLOC1_PFN_GET_FORMAT getFormat;
- GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
- GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
- GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
- GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
- GRALLOC1_PFN_GET_STRIDE getStride;
- GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
- GRALLOC1_PFN_LOCK lock;
- GRALLOC1_PFN_LOCK_FLEX lockFlex;
- GRALLOC1_PFN_UNLOCK unlock;
- } mDispatch;
-
- std::mutex mMutex;
- std::unordered_map<buffer_handle_t, size_t> mBufferReferenceCounts;
-};
-
-GrallocMapperHal::GrallocMapperHal(const hw_module_t* module)
- : mDevice(nullptr), mCapabilities(), mDispatch()
-{
- int status = gralloc1_open(module, &mDevice);
- if (status) {
- LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
- strerror(-status));
- }
-
- initCapabilities();
- initDispatch();
-}
-
-GrallocMapperHal::~GrallocMapperHal()
-{
- gralloc1_close(mDevice);
-}
-
-void GrallocMapperHal::initCapabilities()
-{
- uint32_t count = 0;
- mDevice->getCapabilities(mDevice, &count, nullptr);
-
- std::vector<int32_t> caps(count);
- mDevice->getCapabilities(mDevice, &count, caps.data());
- caps.resize(count);
-
- for (auto cap : caps) {
- switch (cap) {
- case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
- mCapabilities.layeredBuffers = true;
- break;
- default:
- break;
- }
- }
-}
-
-template<typename T>
-void GrallocMapperHal::initDispatch(gralloc1_function_descriptor_t desc,
- T* outPfn)
-{
- auto pfn = mDevice->getFunction(mDevice, desc);
- if (!pfn) {
- LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
- }
-
- *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void GrallocMapperHal::initDispatch()
-{
- initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
- initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
- initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions);
- initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat);
- if (mCapabilities.layeredBuffers) {
- initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT,
- &mDispatch.getLayerCount);
- }
- initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE,
- &mDispatch.getProducerUsage);
- initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE,
- &mDispatch.getConsumerUsage);
- initDispatch(GRALLOC1_FUNCTION_GET_BACKING_STORE,
- &mDispatch.getBackingStore);
- initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
- initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
- &mDispatch.getNumFlexPlanes);
- initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
- initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
- initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
-}
-
-gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect)
-{
- return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
-}
-
-bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd)
-{
- auto handle = fenceHandle.getNativeHandle();
- if (!handle || handle->numFds == 0) {
- *outFd = -1;
- return true;
- }
-
- if (handle->numFds > 1) {
- ALOGE("invalid fence handle with %d fds", handle->numFds);
+ if (!descriptorInfo.width || !descriptorInfo.height ||
+ !descriptorInfo.layerCount) {
return false;
}
- *outFd = dup(handle->data[0]);
- return (*outFd >= 0);
-}
-
-Return<Error> GrallocMapperHal::retain(const hidl_handle& bufferHandle)
-{
- int32_t err = mDispatch.retain(mDevice, bufferHandle);
- if (err == GRALLOC1_ERROR_NONE) {
- auto nativeHandle = bufferHandle.getNativeHandle();
- std::lock_guard<std::mutex> lock(mMutex);
-
- ++mBufferReferenceCounts[nativeHandle];
- }
- return static_cast<Error>(err);
-}
-
-Return<Error> GrallocMapperHal::release(const hidl_handle& bufferHandle)
-{
- int32_t err = mDispatch.release(mDevice, bufferHandle);
- if (err == GRALLOC1_ERROR_NONE) {
- auto nativeHandle = bufferHandle.getNativeHandle();
- std::lock_guard<std::mutex> lock(mMutex);
-
- auto iter = mBufferReferenceCounts.find(bufferHandle);
- if (iter == mBufferReferenceCounts.end()) {
- // this should never happen
- err = GRALLOC1_ERROR_BAD_HANDLE;
- } else if (--iter->second == 0) {
- native_handle_close(nativeHandle);
- native_handle_delete(const_cast<native_handle_t*>(nativeHandle));
-
- mBufferReferenceCounts.erase(iter);
- }
+ if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
+ return false;
}
- return static_cast<Error>(err);
-}
-
-Return<void> GrallocMapperHal::getDimensions(const hidl_handle& bufferHandle,
- getDimensions_cb hidl_cb)
-{
- uint32_t width = 0;
- uint32_t height = 0;
- int32_t err = mDispatch.getDimensions(mDevice, bufferHandle,
- &width, &height);
-
- hidl_cb(static_cast<Error>(err), width, height);
- return Void();
-}
-
-Return<void> GrallocMapperHal::getFormat(const hidl_handle& bufferHandle,
- getFormat_cb hidl_cb)
-{
- int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
- int32_t err = mDispatch.getFormat(mDevice, bufferHandle, &format);
-
- hidl_cb(static_cast<Error>(err), static_cast<PixelFormat>(format));
- return Void();
-}
-
-Return<void> GrallocMapperHal::getLayerCount(const hidl_handle& bufferHandle,
- getLayerCount_cb hidl_cb)
-{
- int32_t err = GRALLOC1_ERROR_NONE;
- uint32_t count = 1;
- if (mCapabilities.layeredBuffers) {
- err = mDispatch.getLayerCount(mDevice, bufferHandle, &count);
+ if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+ return false;
}
- hidl_cb(static_cast<Error>(err), count);
+ if (descriptorInfo.usage & ~validUsageBits) {
+ // could not fail as gralloc may use the reserved bits...
+ ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+ descriptorInfo.usage & ~validUsageBits);
+ }
+
+ return true;
+}
+
+Return<void> GrallocMapper::createDescriptor(
+ const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
+ if (validateDescriptorInfo(descriptorInfo)) {
+ hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
+ } else {
+ hidl_cb(Error::BAD_VALUE, BufferDescriptor());
+ }
+
return Void();
}
-Return<void> GrallocMapperHal::getProducerUsageMask(
- const hidl_handle& bufferHandle, getProducerUsageMask_cb hidl_cb)
-{
- uint64_t mask = 0x0;
- int32_t err = mDispatch.getProducerUsage(mDevice, bufferHandle, &mask);
-
- hidl_cb(static_cast<Error>(err), mask);
- return Void();
+bool GrallocMapper::addRegisteredHandle(buffer_handle_t bufferHandle) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.insert(bufferHandle).second;
}
-Return<void> GrallocMapperHal::getConsumerUsageMask(
- const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb)
-{
- uint64_t mask = 0x0;
- int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask);
+native_handle_t* GrallocMapper::popRegisteredHandle(void* buffer) {
+ auto bufferHandle = static_cast<native_handle_t*>(buffer);
- hidl_cb(static_cast<Error>(err), mask);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> GrallocMapperHal::getBackingStore(
- const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb)
-{
- uint64_t store = 0;
- int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store);
+buffer_handle_t GrallocMapper::getRegisteredHandle(const void* buffer) {
+ auto bufferHandle = static_cast<buffer_handle_t>(buffer);
- hidl_cb(static_cast<Error>(err), store);
- return Void();
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mRegisteredHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
}
-Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
- getStride_cb hidl_cb)
-{
- uint32_t stride = 0;
- int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
+ importBuffer_cb hidl_cb) {
+ // importing an already imported handle rather than a raw handle
+ if (getRegisteredHandle(rawHandle.getNativeHandle())) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
- hidl_cb(static_cast<Error>(err), stride);
- return Void();
-}
+ if (!rawHandle.getNativeHandle()) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
-Return<void> GrallocMapperHal::lock(const hidl_handle& bufferHandle,
- uint64_t producerUsageMask, uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
- lock_cb hidl_cb)
-{
- gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
-
- int fence = -1;
- if (!dupFence(acquireFence, &fence)) {
+ native_handle_t* bufferHandle =
+ native_handle_clone(rawHandle.getNativeHandle());
+ if (!bufferHandle) {
hidl_cb(Error::NO_RESOURCES, nullptr);
return Void();
}
+ Error error = registerBuffer(bufferHandle);
+ if (error != Error::NONE) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+
+ hidl_cb(error, nullptr);
+ return Void();
+ }
+
+ // The newly cloned handle is already registered? This can only happen
+ // when a handle previously registered was native_handle_delete'd instead
+ // of freeBuffer'd.
+ if (!addRegisteredHandle(bufferHandle)) {
+ ALOGE("handle %p has already been imported; potential fd leaking",
+ bufferHandle);
+ unregisterBuffer(bufferHandle);
+ if (!mCapabilities.unregisterImplyDelete) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ }
+
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return Void();
+ }
+
+ hidl_cb(Error::NONE, bufferHandle);
+ return Void();
+}
+
+Return<Error> GrallocMapper::freeBuffer(void* buffer) {
+ native_handle_t* bufferHandle = popRegisteredHandle(buffer);
+ if (!bufferHandle) {
+ return Error::BAD_BUFFER;
+ }
+
+ unregisterBuffer(bufferHandle);
+ if (!mCapabilities.unregisterImplyDelete) {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ }
+
+ return Error::NONE;
+}
+
+void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
+ if (fenceFd < 0) {
+ return;
+ }
+
+ const int warningTimeout = 3500;
+ const int error = sync_wait(fenceFd, warningTimeout);
+ if (error < 0 && errno == ETIME) {
+ ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
+ warningTimeout);
+ sync_wait(fenceFd, -1);
+ }
+}
+
+bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
+ int* outFenceFd) {
+ auto handle = fenceHandle.getNativeHandle();
+ if (handle && handle->numFds > 1) {
+ ALOGE("invalid fence handle with %d fds", handle->numFds);
+ return false;
+ }
+
+ *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ return true;
+}
+
+hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
+ native_handle_t* handle = nullptr;
+ if (fenceFd >= 0) {
+ handle = native_handle_init(handleStorage, 1, 0);
+ handle->data[0] = fenceFd;
+ }
+
+ return hidl_handle(handle);
+}
+
+Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lock_cb hidl_cb) {
+ buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ int fenceFd;
+ if (!getFenceFd(acquireFence, &fenceFd)) {
+ hidl_cb(Error::BAD_VALUE, nullptr);
+ return Void();
+ }
+
void* data = nullptr;
- int32_t err = mDispatch.lock(mDevice, bufferHandle, producerUsageMask,
- consumerUsageMask, &rect, &data, fence);
- if (err != GRALLOC1_ERROR_NONE) {
- close(fence);
- }
+ Error error =
+ lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
- hidl_cb(static_cast<Error>(err), data);
+ hidl_cb(error, data);
return Void();
}
-Return<void> GrallocMapperHal::lockFlex(const hidl_handle& bufferHandle,
- uint64_t producerUsageMask, uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
- lockFlex_cb hidl_cb)
-{
- FlexLayout layout_reply{};
+Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lockYCbCr_cb hidl_cb) {
+ YCbCrLayout layout = {};
- uint32_t planeCount = 0;
- int32_t err = mDispatch.getNumFlexPlanes(mDevice, bufferHandle,
- &planeCount);
- if (err != GRALLOC1_ERROR_NONE) {
- hidl_cb(static_cast<Error>(err), layout_reply);
+ buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, layout);
return Void();
}
- gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
-
- int fence = -1;
- if (!dupFence(acquireFence, &fence)) {
- hidl_cb(Error::NO_RESOURCES, layout_reply);
+ int fenceFd;
+ if (!getFenceFd(acquireFence, &fenceFd)) {
+ hidl_cb(Error::BAD_VALUE, layout);
return Void();
}
- std::vector<android_flex_plane_t> planes(planeCount);
- android_flex_layout_t layout{};
- layout.num_planes = planes.size();
- layout.planes = planes.data();
+ Error error =
+ lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
- err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask,
- consumerUsageMask, &rect, &layout, fence);
- if (err == GRALLOC1_ERROR_NONE) {
- layout_reply.format = static_cast<FlexFormat>(layout.format);
+ hidl_cb(error, layout);
+ return Void();
+}
- planes.resize(layout.num_planes);
- layout_reply.planes.setToExternal(
- reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
+Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
+ buffer_handle_t bufferHandle = getRegisteredHandle(buffer);
+ if (!bufferHandle) {
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return Void();
+ }
+
+ int fenceFd;
+ Error error = unlockBuffer(bufferHandle, &fenceFd);
+ if (error == Error::NONE) {
+ NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
} else {
- close(fence);
+ hidl_cb(error, nullptr);
}
- hidl_cb(static_cast<Error>(err), layout_reply);
return Void();
}
-Return<void> GrallocMapperHal::unlock(const hidl_handle& bufferHandle,
- unlock_cb hidl_cb)
-{
- int32_t fence = -1;
- int32_t err = mDispatch.unlock(mDevice, bufferHandle, &fence);
-
- NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
- hidl_handle fenceHandle;
- if (err == GRALLOC1_ERROR_NONE && fence >= 0) {
- auto nativeHandle = native_handle_init(fenceStorage, 1, 0);
- nativeHandle->data[0] = fence;
-
- fenceHandle = nativeHandle;
- }
-
- hidl_cb(static_cast<Error>(err), fenceHandle);
- return Void();
-}
-
-} // anonymous namespace
-
IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
const hw_module_t* module = nullptr;
int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
@@ -410,12 +287,15 @@
}
uint8_t major = (module->module_api_version >> 8) & 0xff;
- if (major != 1) {
- ALOGE("unknown gralloc module major version %d", major);
- return nullptr;
+ switch (major) {
+ case 1:
+ return new Gralloc1Mapper(module);
+ case 0:
+ return new Gralloc0Mapper(module);
+ default:
+ ALOGE("unknown gralloc module major version %d", major);
+ return nullptr;
}
-
- return new GrallocMapperHal(module);
}
} // namespace implementation
diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h
index a2f89d1..c9c6d8a 100644
--- a/graphics/mapper/2.0/default/GrallocMapper.h
+++ b/graphics/mapper/2.0/default/GrallocMapper.h
@@ -18,6 +18,10 @@
#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+
+#include <mutex>
+#include <unordered_set>
namespace android {
namespace hardware {
@@ -26,6 +30,68 @@
namespace V2_0 {
namespace implementation {
+class GrallocMapper : public IMapper {
+ public:
+ // IMapper interface
+ Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+ createDescriptor_cb hidl_cb) override;
+ Return<void> importBuffer(const hidl_handle& rawHandle,
+ importBuffer_cb hidl_cb) override;
+ Return<Error> freeBuffer(void* buffer) override;
+ Return<void> lock(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lock_cb hidl_cb) override;
+ Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence,
+ lockYCbCr_cb hidl_cb) override;
+ Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
+
+ protected:
+ static void waitFenceFd(int fenceFd, const char* logname);
+
+ struct {
+ bool highUsageBits;
+ bool layeredBuffers;
+ bool unregisterImplyDelete;
+ } mCapabilities = {};
+
+ private:
+ virtual bool validateDescriptorInfo(
+ const BufferDescriptorInfo& descriptorInfo) const;
+
+ // Register a buffer. The handle is already cloned by the caller.
+ virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
+
+ // Unregister a buffer. The handle is closed and deleted by the
+ // callee if and only if mCapabilities.unregisterImplyDelete is set.
+ virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
+
+ // Lock a buffer. The fence is owned by the caller.
+ virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData) = 0;
+ virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ YCbCrLayout* outLayout) = 0;
+
+ // Unlock a buffer. The returned fence is owned by the caller.
+ virtual Error unlockBuffer(buffer_handle_t bufferHandle,
+ int* outFenceFd) = 0;
+
+ static bool addRegisteredHandle(buffer_handle_t bufferHandle);
+ static buffer_handle_t getRegisteredHandle(const void* buffer);
+ static native_handle_t* popRegisteredHandle(void* buffer);
+
+ static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
+ static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
+
+ // these are static and shared by all mappers
+ static std::mutex mMutex;
+ static std::unordered_set<buffer_handle_t> mRegisteredHandles;
+};
+
extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
} // namespace implementation
diff --git a/graphics/mapper/2.0/types.hal b/graphics/mapper/2.0/types.hal
index 2946e85..e9b2f3a 100644
--- a/graphics/mapper/2.0/types.hal
+++ b/graphics/mapper/2.0/types.hal
@@ -16,101 +16,50 @@
package android.hardware.graphics.mapper@2.0;
+enum Error : int32_t {
+ NONE = 0, /** no error */
+ BAD_DESCRIPTOR = 1, /** invalid BufferDescriptor */
+ BAD_BUFFER = 2, /** invalid buffer handle */
+ BAD_VALUE = 3, /** invalid width, height, etc. */
+ /* 4 is reserved */
+ NO_RESOURCES = 5, /** temporary failure due to resource contention */
+ /* 6 is reserved */
+ UNSUPPORTED = 7, /** permanent failure */
+};
+
/**
- * Structures for describing flexible YUVA/RGBA formats for consumption by
- * applications. Such flexible formats contain a plane for each component (e.g.
- * red, green, blue), where each plane is laid out in a grid-like pattern
- * occupying unique byte addresses and with consistent byte offsets between
- * neighboring pixels.
- *
- * The FlexLayout structure is used with any pixel format that can be
- * represented by it, such as:
- * - PixelFormat::YCBCR_*_888
- * - PixelFormat::FLEX_RGB*_888
- * - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888
- * - PixelFormat::YV12,Y8,Y16,YCBCR_422_SP/I,YCRCB_420_SP
- * - even implementation defined formats that can be represented by
- * the structures
- *
- * Vertical increment (aka. row increment or stride) describes the distance in
- * bytes from the first pixel of one row to the first pixel of the next row
- * (below) for the component plane. This can be negative.
- *
- * Horizontal increment (aka. column or pixel increment) describes the distance
- * in bytes from one pixel to the next pixel (to the right) on the same row for
- * the component plane. This can be negative.
- *
- * Each plane can be subsampled either vertically or horizontally by
- * a power-of-two factor.
- *
- * The bit-depth of each component can be arbitrary, as long as the pixels are
- * laid out on whole bytes, in native byte-order, using the most significant
- * bits of each unit.
+ * A buffer descriptor is an implementation-defined opaque data returned by
+ * createDescriptor. It describes the properties of a buffer and is consumed
+ * by the allocator.
*/
+typedef vec<uint32_t> BufferDescriptor;
-enum FlexComponent : int32_t {
- Y = 1 << 0, /** luma */
- CB = 1 << 1, /** chroma blue */
- CR = 1 << 2, /** chroma red */
-
- R = 1 << 10, /** red */
- G = 1 << 11, /** green */
- B = 1 << 12, /** blue */
-
- A = 1 << 30, /** alpha */
+/**
+ * Structure for describing YCbCr formats for consumption by applications.
+ * This is used with PixelFormat::YCBCR_*_888.
+ *
+ * Buffer chroma subsampling is defined in the format.
+ * e.g. PixelFormat::YCBCR_420_888 has subsampling 4:2:0.
+ *
+ * Buffers must have a 8 bit depth.
+ *
+ * y, cb, and cr point to the first byte of their respective planes.
+ *
+ * Stride describes the distance in bytes from the first value of one row of
+ * the image to the first value of the next row. It includes the width of the
+ * image plus padding.
+ * yStride is the stride of the luma plane.
+ * cStride is the stride of the chroma planes.
+ *
+ * chromaStep is the distance in bytes from one chroma pixel value to the
+ * next. This is 2 bytes for semiplanar (because chroma values are interleaved
+ * and each chroma value is one byte) and 1 for planar.
+ */
+struct YCbCrLayout {
+ pointer y;
+ pointer cb;
+ pointer cr;
+ uint32_t yStride;
+ uint32_t cStride;
+ uint32_t chromaStep;
};
-
-enum FlexFormat : int32_t {
- /** not a flexible format */
- INVALID = 0x0,
-
- Y = FlexComponent:Y,
- YCBCR = Y | FlexComponent:CB | FlexComponent:CR,
- YCBCRA = YCBCR | FlexComponent:A,
-
- RGB = FlexComponent:R | FlexComponent:G | FlexComponent:B,
- RGBA = RGB | FlexComponent:A,
-};
-
-struct FlexPlane {
- /** Pointer to the first byte of the top-left pixel of the plane. */
- pointer topLeft;
-
- FlexComponent component;
-
- /**
- * Bits allocated for the component in each pixel. Must be a positive
- * multiple of 8.
- */
- int32_t bitsPerComponent;
-
- /**
- * Number of the most significant bits used in the format for this
- * component. Must be between 1 and bitsPerComponent, inclusive.
- */
- int32_t bitsUsed;
-
- /** Horizontal increment. */
- int32_t hIncrement;
- /** Vertical increment. */
- int32_t vIncrement;
- /** Horizontal subsampling. Must be a positive power of 2. */
- int32_t hSubsampling;
- /** Vertical subsampling. Must be a positive power of 2. */
- int32_t vSubsampling;
-};
-
-struct FlexLayout {
- /** The kind of flexible format. */
- FlexFormat format;
-
- /**
- * A plane for each component; ordered in increasing component value
- * order. E.g. FlexFormat::RGBA maps 0 -> R, 1 -> G, etc. Can have size 0
- * for FlexFormat::INVALID.
- */
- vec<FlexPlane> planes;
-};
-
-/** Backing store ID of a buffer. See IMapper::getBackingStore. */
-typedef uint64_t BackingStore;
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index e26f087..1c0e4c5 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -24,7 +24,6 @@
],
static_libs: [
"VtsHalHidlTargetTestBase",
- "libVtsHalGraphicsAllocatorTestUtils",
],
cflags: [
"-Wall",
@@ -54,7 +53,6 @@
"android.hardware.graphics.common@1.0",
],
static_libs: [
- "libVtsHalGraphicsAllocatorTestUtils",
"libVtsHalGraphicsMapperTestUtils",
"VtsHalHidlTargetTestBase",
],
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
index f6a26ac..c534889 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
@@ -25,228 +25,233 @@
namespace V2_0 {
namespace tests {
-using android::hardware::graphics::allocator::V2_0::Buffer;
-using android::hardware::graphics::allocator::V2_0::BufferDescriptor;
-using android::hardware::graphics::allocator::V2_0::Error;
-
-Mapper::Mapper() { init(); }
-
-void Mapper::init() {
- mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
- ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
- ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+Gralloc::Gralloc() {
+ init();
}
-Mapper::~Mapper() {
- for (auto it : mHandles) {
- while (it.second) {
- EXPECT_EQ(Error::NONE, mMapper->release(it.first))
- << "failed to release handle " << it.first;
- it.second--;
+void Gralloc::init() {
+ mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>();
+ ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
+
+ mMapper = ::testing::VtsHalHidlTargetTestBase::getService<IMapper>();
+ ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
+ ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
+}
+
+Gralloc::~Gralloc() {
+ for (auto bufferHandle : mClonedBuffers) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
}
- }
- mHandles.clear();
+ mClonedBuffers.clear();
+
+ for (auto bufferHandle : mImportedBuffers) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
+ << "failed to free buffer " << buffer;
+ }
+ mImportedBuffers.clear();
}
-sp<IMapper> Mapper::getRaw() const { return mMapper; }
-
-void Mapper::retain(const native_handle_t* handle) {
- Error error = mMapper->retain(handle);
- ASSERT_EQ(Error::NONE, error) << "failed to retain handle " << handle;
-
- mHandles[handle]++;
+sp<IAllocator> Gralloc::getAllocator() const {
+ return mAllocator;
}
-void Mapper::release(const native_handle_t* handle) {
- Error error = mMapper->release(handle);
- ASSERT_EQ(Error::NONE, error) << "failed to release handle " << handle;
+std::string Gralloc::dumpDebugInfo() {
+ std::string debugInfo;
+ mAllocator->dumpDebugInfo(
+ [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
- if (--mHandles[handle] == 0) {
- mHandles.erase(handle);
- }
+ return debugInfo;
}
-Mapper::Dimensions Mapper::getDimensions(const native_handle_t* handle) {
- Dimensions dimensions = {};
- mMapper->getDimensions(handle, [&](const auto& tmpError, const auto& tmpWidth,
- const auto& tmpHeight) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get dimensions for handle " << handle;
- dimensions.width = tmpWidth;
- dimensions.height = tmpHeight;
- });
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+ const native_handle_t* bufferHandle =
+ native_handle_clone(rawHandle.getNativeHandle());
+ EXPECT_NE(nullptr, bufferHandle);
- return dimensions;
+ if (bufferHandle) {
+ mClonedBuffers.insert(bufferHandle);
+ }
+
+ return bufferHandle;
}
-PixelFormat Mapper::getFormat(const native_handle_t* handle) {
- PixelFormat format = static_cast<PixelFormat>(0);
- mMapper->getFormat(handle, [&](const auto& tmpError, const auto& tmpFormat) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get format for handle " << handle;
- format = tmpFormat;
- });
+std::vector<const native_handle_t*> Gralloc::allocate(
+ const BufferDescriptor& descriptor, uint32_t count, bool import,
+ uint32_t* outStride) {
+ std::vector<const native_handle_t*> bufferHandles;
+ bufferHandles.reserve(count);
+ mAllocator->allocate(
+ descriptor, count, [&](const auto& tmpError, const auto& tmpStride,
+ const auto& tmpBuffers) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+ ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
- return format;
+ for (uint32_t i = 0; i < count; i++) {
+ if (import) {
+ ASSERT_NO_FATAL_FAILURE(
+ bufferHandles.push_back(importBuffer(tmpBuffers[i])));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(
+ bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+ }
+ }
+
+ if (outStride) {
+ *outStride = tmpStride;
+ }
+ });
+
+ if (::testing::Test::HasFatalFailure()) {
+ bufferHandles.clear();
+ }
+
+ return bufferHandles;
}
-uint32_t Mapper::getLayerCount(const native_handle_t* handle) {
- uint32_t count = 0;
- mMapper->getLayerCount(
- handle, [&](const auto& tmpError, const auto& tmpCount) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get layer count for handle " << handle;
- count = tmpCount;
- });
+const native_handle_t* Gralloc::allocate(
+ const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+ uint32_t* outStride) {
+ BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
- return count;
+ auto buffers = allocate(descriptor, 1, import, outStride);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+
+ return buffers[0];
}
-uint64_t Mapper::getProducerUsageMask(const native_handle_t* handle) {
- uint64_t usageMask = 0;
- mMapper->getProducerUsageMask(
- handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get producer usage mask for handle " << handle;
- usageMask = tmpUsageMask;
- });
-
- return usageMask;
+sp<IMapper> Gralloc::getMapper() const {
+ return mMapper;
}
-uint64_t Mapper::getConsumerUsageMask(const native_handle_t* handle) {
- uint64_t usageMask = 0;
- mMapper->getConsumerUsageMask(
- handle, [&](const auto& tmpError, const auto& tmpUsageMask) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get consumer usage mask for handle " << handle;
- usageMask = tmpUsageMask;
- });
+BufferDescriptor Gralloc::createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ BufferDescriptor descriptor;
+ mMapper->createDescriptor(
+ descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+ descriptor = tmpDescriptor;
+ });
- return usageMask;
+ return descriptor;
}
-BackingStore Mapper::getBackingStore(const native_handle_t* handle) {
- BackingStore backingStore = 0;
- mMapper->getBackingStore(
- handle, [&](const auto& tmpError, const auto& tmpBackingStore) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get backing store for handle " << handle;
- backingStore = tmpBackingStore;
- });
+const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
+ const native_handle_t* bufferHandle = nullptr;
+ mMapper->importBuffer(
+ rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to import buffer %p"
+ << rawHandle.getNativeHandle();
+ bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+ });
- return backingStore;
+ if (bufferHandle) {
+ mImportedBuffers.insert(bufferHandle);
+ }
+
+ return bufferHandle;
}
-uint32_t Mapper::getStride(const native_handle_t* handle) {
- uint32_t stride = 0;
- mMapper->getStride(handle, [&](const auto& tmpError, const auto& tmpStride) {
- ASSERT_EQ(Error::NONE, tmpError)
- << "failed to get stride for handle " << handle;
- stride = tmpStride;
- });
+void Gralloc::freeBuffer(const native_handle_t* bufferHandle) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
- return stride;
+ if (mImportedBuffers.erase(bufferHandle)) {
+ Error error = mMapper->freeBuffer(buffer);
+ ASSERT_EQ(Error::NONE, error) << "failed to free buffer " << buffer;
+ } else {
+ mClonedBuffers.erase(bufferHandle);
+ native_handle_close(buffer);
+ native_handle_delete(buffer);
+ }
}
-void* Mapper::lock(const native_handle_t* handle, uint64_t producerUsageMask,
- uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, int acquireFence) {
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
- native_handle_t* acquireFenceHandle = nullptr;
- if (acquireFence >= 0) {
- acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
- acquireFenceHandle->data[0] = acquireFence;
- }
+void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int acquireFence) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
- void* data = nullptr;
- mMapper->lock(
- handle, producerUsageMask, consumerUsageMask, accessRegion,
- acquireFenceHandle, [&](const auto& tmpError, const auto& tmpData) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to lock handle " << handle;
- data = tmpData;
- });
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ hidl_handle acquireFenceHandle;
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
- if (acquireFence >= 0) {
- close(acquireFence);
- }
-
- return data;
-}
-
-FlexLayout Mapper::lockFlex(const native_handle_t* handle,
- uint64_t producerUsageMask,
- uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion,
- int acquireFence) {
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 0, 1);
- native_handle_t* acquireFenceHandle = nullptr;
- if (acquireFence >= 0) {
- acquireFenceHandle = native_handle_init(acquireFenceStorage, 0, 1);
- acquireFenceHandle->data[0] = acquireFence;
- }
-
- FlexLayout layout = {};
- mMapper->lockFlex(handle, producerUsageMask, consumerUsageMask, accessRegion,
- acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpLayout) {
+ void* data = nullptr;
+ mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpData) {
ASSERT_EQ(Error::NONE, tmpError)
- << "failed to lockFlex handle " << handle;
- layout = tmpLayout;
- });
+ << "failed to lock buffer " << buffer;
+ data = tmpData;
+ });
- if (acquireFence >= 0) {
- close(acquireFence);
- }
-
- return layout;
-}
-
-int Mapper::unlock(const native_handle_t* handle) {
- int releaseFence = -1;
- mMapper->unlock(handle, [&](const auto& tmpError,
- const auto& tmpReleaseFence) {
- ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock handle " << handle;
-
- auto handle = tmpReleaseFence.getNativeHandle();
- if (handle) {
- ASSERT_EQ(0, handle->numInts) << "invalid fence handle " << handle;
- if (handle->numFds == 1) {
- releaseFence = dup(handle->data[0]);
- ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
- } else {
- ASSERT_EQ(0, handle->numFds) << " invalid fence handle " << handle;
- }
+ if (acquireFence >= 0) {
+ close(acquireFence);
}
- });
- return releaseFence;
+ return data;
}
-const native_handle_t* Mapper::allocate(
- std::unique_ptr<AllocatorClient>& allocatorClient,
- const IAllocatorClient::BufferDescriptorInfo& info) {
- BufferDescriptor descriptor = allocatorClient->createDescriptor(info);
- if (::testing::Test::HasFatalFailure()) {
- return nullptr;
- }
+YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
- Buffer buffer = allocatorClient->allocate(descriptor);
- if (::testing::Test::HasFatalFailure()) {
- allocatorClient->destroyDescriptor(descriptor);
- return nullptr;
- }
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ hidl_handle acquireFenceHandle;
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
- const native_handle_t* handle =
- allocatorClient->exportHandle(descriptor, buffer);
- if (handle) {
- retain(handle);
- }
+ YCbCrLayout layout = {};
+ mMapper->lockYCbCr(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpLayout) {
+ ASSERT_EQ(Error::NONE, tmpError)
+ << "failed to lockYCbCr buffer " << buffer;
+ layout = tmpLayout;
+ });
- allocatorClient->free(buffer);
- allocatorClient->destroyDescriptor(descriptor);
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
- return handle;
+ return layout;
+}
+
+int Gralloc::unlock(const native_handle_t* bufferHandle) {
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ int releaseFence = -1;
+ mMapper->unlock(
+ buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to unlock buffer "
+ << buffer;
+
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle) {
+ ASSERT_EQ(0, fenceHandle->numInts) << "invalid fence handle "
+ << fenceHandle;
+ if (fenceHandle->numFds == 1) {
+ releaseFence = dup(fenceHandle->data[0]);
+ ASSERT_LT(0, releaseFence) << "failed to dup fence fd";
+ } else {
+ ASSERT_EQ(0, fenceHandle->numFds)
+ << " invalid fence handle " << fenceHandle;
+ }
+ }
+ });
+
+ return releaseFence;
}
} // namespace tests
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
index c186b00..757f20b 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
@@ -17,14 +17,12 @@
#ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS
#define VTS_HAL_GRAPHICS_MAPPER_UTILS
-#include <memory>
-#include <unordered_map>
+#include <unordered_set>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <utils/StrongPointer.h>
-#include "VtsHalGraphicsAllocatorTestUtils.h"
-
namespace android {
namespace hardware {
namespace graphics {
@@ -32,59 +30,62 @@
namespace V2_0 {
namespace tests {
-using android::hardware::graphics::common::V1_0::PixelFormat;
-using android::hardware::graphics::allocator::V2_0::IAllocatorClient;
-using android::hardware::graphics::allocator::V2_0::tests::AllocatorClient;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
-// A wrapper to IMapper.
-class Mapper {
- public:
- Mapper();
- ~Mapper();
+// A wrapper to IAllocator and IMapper.
+class Gralloc {
+ public:
+ Gralloc();
+ ~Gralloc();
- sp<IMapper> getRaw() const;
+ // IAllocator methods
- void retain(const native_handle_t* handle);
- void release(const native_handle_t* handle);
+ sp<IAllocator> getAllocator() const;
- struct Dimensions {
- uint32_t width;
- uint32_t height;
- };
- Dimensions getDimensions(const native_handle_t* handle);
+ std::string dumpDebugInfo();
- PixelFormat getFormat(const native_handle_t* handle);
- uint32_t getLayerCount(const native_handle_t* handle);
- uint64_t getProducerUsageMask(const native_handle_t* handle);
- uint64_t getConsumerUsageMask(const native_handle_t* handle);
- BackingStore getBackingStore(const native_handle_t* handle);
- uint32_t getStride(const native_handle_t* handle);
+ // When import is false, this simply calls IAllocator::allocate. When import
+ // is true, the returned buffers are also imported into the mapper.
+ //
+ // Either case, the returned buffers must be freed with freeBuffer.
+ std::vector<const native_handle_t*> allocate(
+ const BufferDescriptor& descriptor, uint32_t count, bool import = true,
+ uint32_t* outStride = nullptr);
+ const native_handle_t* allocate(
+ const IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
+ uint32_t* outStride = nullptr);
- // We use fd instead of hidl_handle in these functions to pass fences
- // in and out of the mapper. The ownership of the fd is always transferred
- // with each of these functions.
- void* lock(const native_handle_t* handle, uint64_t producerUsageMask,
- uint64_t consumerUsageMask, const IMapper::Rect& accessRegion,
- int acquireFence);
- FlexLayout lockFlex(const native_handle_t* handle, uint64_t producerUsageMask,
- uint64_t consumerUsageMask,
- const IMapper::Rect& accessRegion, int acquireFence);
- int unlock(const native_handle_t* handle);
+ // IMapper methods
- // Requests AllocatorClient to allocate a buffer, export the handle, and
- // register the handle with mapper.
- const native_handle_t* allocate(
- std::unique_ptr<AllocatorClient>& allocatorClient,
- const IAllocatorClient::BufferDescriptorInfo& info);
+ sp<IMapper> getMapper() const;
- private:
- void init();
+ BufferDescriptor createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo);
- sp<IMapper> mMapper;
+ const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+ void freeBuffer(const native_handle_t* bufferHandle);
- // Keep track of all registered (retained) handles. When a test fails with
- // ASSERT_*, the destructor will release the handles for the test.
- std::unordered_map<const native_handle_t*, uint64_t> mHandles;
+ // We use fd instead of hidl_handle in these functions to pass fences
+ // in and out of the mapper. The ownership of the fd is always transferred
+ // with each of these functions.
+ void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int acquireFence);
+ YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle,
+ uint64_t cpuUsage, const IMapper::Rect& accessRegion,
+ int acquireFence);
+ int unlock(const native_handle_t* bufferHandle);
+
+ private:
+ void init();
+ const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+
+ sp<IAllocator> mAllocator;
+ sp<IMapper> mMapper;
+
+ // Keep track of all cloned and imported handles. When a test fails with
+ // ASSERT_*, the destructor will free the handles for the test.
+ std::unordered_set<const native_handle_t*> mClonedBuffers;
+ std::unordered_set<const native_handle_t*> mImportedBuffers;
};
} // namespace tests
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 92d74d5..f066a1e 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#define LOG_TAG "graphics_mapper_hidl_hal_test"
+#define LOG_TAG "VtsHalGraphicsMapperV2_0TargetTest"
-#include <android-base/logging.h>
#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
#include <sync/sync.h>
#include "VtsHalGraphicsMapperTestUtils.h"
@@ -29,202 +29,384 @@
namespace tests {
namespace {
-using namespace android::hardware::graphics::allocator::V2_0;
-using namespace android::hardware::graphics::allocator::V2_0::tests;
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_0::PixelFormat;
class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
protected:
void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mAllocator = std::make_unique<Allocator>());
- ASSERT_NO_FATAL_FAILURE(mAllocatorClient = mAllocator->createClient());
- ASSERT_NO_FATAL_FAILURE(mMapper = std::make_unique<Mapper>());
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
- mDummyDescriptorInfo.width = 64;
- mDummyDescriptorInfo.height = 64;
- mDummyDescriptorInfo.layerCount = 1;
- mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
- mDummyDescriptorInfo.producerUsageMask =
- static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
- mDummyDescriptorInfo.consumerUsageMask =
- static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+ mDummyDescriptorInfo.width = 64;
+ mDummyDescriptorInfo.height = 64;
+ mDummyDescriptorInfo.layerCount = 1;
+ mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+ mDummyDescriptorInfo.usage = static_cast<uint64_t>(
+ BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
}
void TearDown() override {}
- std::unique_ptr<Allocator> mAllocator;
- std::unique_ptr<AllocatorClient> mAllocatorClient;
- std::unique_ptr<Mapper> mMapper;
- IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
+ std::unique_ptr<Gralloc> mGralloc;
+ IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
};
/**
- * Test IMapper::retain and IMapper::release.
+ * Test IAllocator::dumpDebugInfo by calling it.
*/
-TEST_F(GraphicsMapperHidlTest, RetainRelease) {
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(
- buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
-
- const int maxRefs = 10;
- for (int i = 0; i < maxRefs; i++) {
- ASSERT_NO_FATAL_FAILURE(mMapper->retain(buffer));
- }
- for (int i = 0; i < maxRefs; i++) {
- ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
- }
-
- ASSERT_NO_FATAL_FAILURE(mMapper->release(buffer));
+TEST_F(GraphicsMapperHidlTest, AllocatorDumpDebugInfo) {
+ mGralloc->dumpDebugInfo();
}
/**
- * Test IMapper::get* getters.
+ * Test IAllocator::allocate with valid buffer descriptors.
*/
-TEST_F(GraphicsMapperHidlTest, Getters) {
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(
- buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
+ BufferDescriptor descriptor;
+ ASSERT_NO_FATAL_FAILURE(
+ descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
- IAllocatorClient::BufferDescriptorInfo info = {};
+ for (uint32_t count = 0; count < 5; count++) {
+ std::vector<const native_handle_t*> bufferHandles;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandles = mGralloc->allocate(
+ descriptor, count, false, &stride));
- Mapper::Dimensions dimensions;
- ASSERT_NO_FATAL_FAILURE(dimensions = mMapper->getDimensions(buffer));
- info.width = dimensions.width;
- info.height = dimensions.height;
+ if (count >= 1) {
+ EXPECT_LE(mDummyDescriptorInfo.width, stride)
+ << "invalid buffer stride";
+ }
- ASSERT_NO_FATAL_FAILURE(info.format = mMapper->getFormat(buffer));
- ASSERT_NO_FATAL_FAILURE(info.producerUsageMask =
- mMapper->getProducerUsageMask(buffer));
- ASSERT_NO_FATAL_FAILURE(info.consumerUsageMask =
- mMapper->getConsumerUsageMask(buffer));
+ for (auto bufferHandle : bufferHandles) {
+ mGralloc->freeBuffer(bufferHandle);
+ }
+ }
+}
- EXPECT_EQ(mDummyDescriptorInfo.width, info.width);
- EXPECT_EQ(mDummyDescriptorInfo.height, info.height);
- EXPECT_EQ(mDummyDescriptorInfo.format, info.format);
- EXPECT_EQ(mDummyDescriptorInfo.producerUsageMask, info.producerUsageMask);
- EXPECT_EQ(mDummyDescriptorInfo.consumerUsageMask, info.consumerUsageMask);
+/**
+ * Test IAllocator::allocate with invalid buffer descriptors.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNegative) {
+ // this assumes any valid descriptor is non-empty
+ BufferDescriptor descriptor;
+ mGralloc->getAllocator()->allocate(
+ descriptor, 1, [&](const auto& tmpError, const auto&, const auto&) {
+ EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+ });
+}
- ASSERT_NO_FATAL_FAILURE(mMapper->getBackingStore(buffer));
+/**
+ * Test IAllocator::allocate does not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, AllocatorAllocateNoLeak) {
+ auto info = mDummyDescriptorInfo;
+ info.width = 1024;
+ info.height = 1024;
- uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
- EXPECT_LE(info.width, stride);
+ for (int i = 0; i < 2048; i++) {
+ auto bufferHandle = mGralloc->allocate(info, false);
+ mGralloc->freeBuffer(bufferHandle);
+ }
+}
+
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorBasic) {
+ ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptorNegative) {
+ auto info = mDummyDescriptorInfo;
+ info.width = 0;
+ mGralloc->getMapper()->createDescriptor(
+ info, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_VALUE, tmpError)
+ << "createDescriptor did not fail with BAD_VALUE";
+ });
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with allocated buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
+ const native_handle_t* bufferHandle;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle =
+ mGralloc->allocate(mDummyDescriptorInfo, true));
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer with cloned buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
+ const native_handle_t* clonedBufferHandle;
+ ASSERT_NO_FATAL_FAILURE(
+ clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+ // A cloned handle is a raw handle. Check that we can import it multiple
+ // times.
+ const native_handle_t* importedBufferHandles[2];
+ ASSERT_NO_FATAL_FAILURE(importedBufferHandles[0] =
+ mGralloc->importBuffer(clonedBufferHandle));
+ ASSERT_NO_FATAL_FAILURE(importedBufferHandles[1] =
+ mGralloc->importBuffer(clonedBufferHandle));
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[0]));
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(importedBufferHandles[1]));
+
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(clonedBufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
+ const native_handle_t* rawHandle;
+ ASSERT_NO_FATAL_FAILURE(
+ rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+
+ native_handle_t* importedHandle = nullptr;
+ mGralloc->getMapper()->importBuffer(
+ rawHandle, [&](const auto& tmpError, const auto& buffer) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ importedHandle = static_cast<native_handle_t*>(buffer);
+ });
+
+ // free the imported handle with another mapper
+ std::unique_ptr<Gralloc> anotherGralloc;
+ ASSERT_NO_FATAL_FAILURE(anotherGralloc = std::make_unique<Gralloc>());
+ Error error = mGralloc->getMapper()->freeBuffer(importedHandle);
+ ASSERT_EQ(Error::NONE, error);
+
+ ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(rawHandle));
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer do not leak.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportFreeBufferNoLeak) {
+ auto info = mDummyDescriptorInfo;
+ info.width = 1024;
+ info.height = 1024;
+
+ for (int i = 0; i < 2048; i++) {
+ auto bufferHandle = mGralloc->allocate(info, true);
+ mGralloc->freeBuffer(bufferHandle);
+ }
+}
+
+/**
+ * Test IMapper::importBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ImportBufferNegative) {
+ native_handle_t* invalidHandle = nullptr;
+ mGralloc->getMapper()->importBuffer(
+ invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "importBuffer with nullptr did not fail with BAD_BUFFER";
+ });
+
+ invalidHandle = native_handle_create(0, 0);
+ mGralloc->getMapper()->importBuffer(invalidHandle, [&](const auto& tmpError,
+ const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "importBuffer with invalid handle did not fail with BAD_BUFFER";
+ });
+ native_handle_delete(invalidHandle);
+
+ const native_handle_t* importedHandle;
+ ASSERT_NO_FATAL_FAILURE(importedHandle =
+ mGralloc->allocate(mDummyDescriptorInfo, true));
+ mGralloc->getMapper()->importBuffer(
+ importedHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "importBuffer with an "
+ "already imported handle did "
+ "not fail with BAD_BUFFER";
+ });
+ mGralloc->freeBuffer(importedHandle);
+}
+
+/**
+ * Test IMapper::freeBuffer with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, FreeBufferNegative) {
+ native_handle_t* invalidHandle = nullptr;
+ Error error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+ EXPECT_EQ(Error::BAD_BUFFER, error)
+ << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+
+ invalidHandle = native_handle_create(0, 0);
+ error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+ EXPECT_EQ(Error::BAD_BUFFER, error)
+ << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
+ native_handle_delete(invalidHandle);
+
+ const native_handle_t* clonedBufferHandle;
+ ASSERT_NO_FATAL_FAILURE(
+ clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+ error = mGralloc->getMapper()->freeBuffer(invalidHandle);
+ EXPECT_EQ(Error::BAD_BUFFER, error)
+ << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
+
+ mGralloc->freeBuffer(clonedBufferHandle);
}
/**
* Test IMapper::lock and IMapper::unlock.
*/
-TEST_F(GraphicsMapperHidlTest, LockBasic) {
- const auto& info = mDummyDescriptorInfo;
+TEST_F(GraphicsMapperHidlTest, LockUnlockBasic) {
+ const auto& info = mDummyDescriptorInfo;
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(
- buffer = mMapper->allocate(mAllocatorClient, mDummyDescriptorInfo));
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle =
+ mGralloc->allocate(info, true, &stride));
- uint32_t stride;
- ASSERT_NO_FATAL_FAILURE(stride = mMapper->getStride(buffer));
+ // lock buffer for writing
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ int fence = -1;
+ uint8_t* data;
+ ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+ bufferHandle, info.usage, region, fence)));
- // lock buffer for writing
- const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
- static_cast<int32_t>(info.height)};
- int fence = -1;
- uint32_t* data;
- ASSERT_NO_FATAL_FAILURE(
- data = static_cast<uint32_t*>(
- mMapper->lock(buffer, info.producerUsageMask, 0, region, fence)));
+ // RGBA_8888
+ size_t strideInBytes = stride * 4;
+ size_t writeInBytes = info.width * 4;
- for (uint32_t y = 0; y < info.height; y++) {
- for (uint32_t x = 0; x < info.width; x++) {
- data[stride * y + x] = info.height * y + x;
+ for (uint32_t y = 0; y < info.height; y++) {
+ memset(data, y, writeInBytes);
+ data += strideInBytes;
}
- }
- ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
- // lock buffer for reading
- ASSERT_NO_FATAL_FAILURE(
- data = static_cast<uint32_t*>(
- mMapper->lock(buffer, 0, info.consumerUsageMask, region, fence)));
- for (uint32_t y = 0; y < info.height; y++) {
- for (uint32_t x = 0; x < info.width; x++) {
- EXPECT_EQ(info.height * y + x, data[stride * y + x]);
+ // lock again for reading
+ ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(
+ bufferHandle, info.usage, region, fence)));
+ for (uint32_t y = 0; y < info.height; y++) {
+ for (size_t i = 0; i < writeInBytes; i++) {
+ EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
+ }
+ data += strideInBytes;
}
- }
- ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
- if (fence >= 0) {
- close(fence);
- }
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+ if (fence >= 0) {
+ close(fence);
+ }
}
/**
- * Test IMapper::lockFlex. This locks a YV12 buffer, and makes sure we can
+ * Test IMapper::lockYCbCr. This locks a YV12 buffer, and makes sure we can
* write to and read from it.
*/
-TEST_F(GraphicsMapperHidlTest, LockFlexBasic) {
- auto info = mDummyDescriptorInfo;
- info.format = PixelFormat::YV12;
+TEST_F(GraphicsMapperHidlTest, LockYCbCrBasic) {
+ auto info = mDummyDescriptorInfo;
+ info.format = PixelFormat::YV12;
- const native_handle_t* buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = mMapper->allocate(mAllocatorClient, info));
+ const native_handle_t* bufferHandle;
+ uint32_t stride;
+ ASSERT_NO_FATAL_FAILURE(bufferHandle =
+ mGralloc->allocate(info, true, &stride));
- // lock buffer for writing
- const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
- static_cast<int32_t>(info.height)};
- int fence = -1;
- FlexLayout layout;
- ASSERT_NO_FATAL_FAILURE(
- layout =
- mMapper->lockFlex(buffer, info.producerUsageMask, 0, region, fence));
- ASSERT_EQ(FlexFormat::YCBCR, layout.format);
- ASSERT_EQ(3u, layout.planes.size());
+ // lock buffer for writing
+ const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+ static_cast<int32_t>(info.height)};
+ int fence = -1;
+ YCbCrLayout layout;
+ ASSERT_NO_FATAL_FAILURE(
+ layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
- const auto y_stride = layout.planes[0].vIncrement;
- const auto c_stride = layout.planes[1].vIncrement;
- auto y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
- auto cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
- auto cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
+ auto yData = static_cast<uint8_t*>(layout.y);
+ auto cbData = static_cast<uint8_t*>(layout.cb);
+ auto crData = static_cast<uint8_t*>(layout.cr);
+ for (uint32_t y = 0; y < info.height; y++) {
+ for (uint32_t x = 0; x < info.width; x++) {
+ auto val = static_cast<uint8_t>(info.height * y + x);
- for (uint32_t y = 0; y < info.height; y++) {
- for (uint32_t x = 0; x < info.width; x++) {
- auto val = static_cast<uint8_t>(info.height * y + x);
-
- y_data[y_stride * y + x] = val;
- if (y % 2 == 0 && x % 2 == 0) {
- cb_data[c_stride * y / 2 + x / 2] = val;
- cr_data[c_stride * y / 2 + x / 2] = val;
- }
+ yData[layout.yStride * y + x] = val;
+ if (y % 2 == 0 && x % 2 == 0) {
+ cbData[layout.cStride * y / 2 + x / 2] = val;
+ crData[layout.cStride * y / 2 + x / 2] = val;
+ }
+ }
}
- }
- ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
- // lock buffer for reading
- ASSERT_NO_FATAL_FAILURE(
- layout =
- mMapper->lockFlex(buffer, 0, info.consumerUsageMask, region, fence));
+ // lock again for reading
+ ASSERT_NO_FATAL_FAILURE(
+ layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
- y_data = static_cast<uint8_t*>(layout.planes[0].topLeft);
- cb_data = static_cast<uint8_t*>(layout.planes[1].topLeft);
- cr_data = static_cast<uint8_t*>(layout.planes[2].topLeft);
- for (uint32_t y = 0; y < info.height; y++) {
- for (uint32_t x = 0; x < info.width; x++) {
- auto val = static_cast<uint8_t>(info.height * y + x);
+ yData = static_cast<uint8_t*>(layout.y);
+ cbData = static_cast<uint8_t*>(layout.cb);
+ crData = static_cast<uint8_t*>(layout.cr);
+ for (uint32_t y = 0; y < info.height; y++) {
+ for (uint32_t x = 0; x < info.width; x++) {
+ auto val = static_cast<uint8_t>(info.height * y + x);
- EXPECT_EQ(val, y_data[y_stride * y + x]);
- if (y % 2 == 0 && x % 2 == 0) {
- EXPECT_EQ(val, cb_data[c_stride * y / 2 + x / 2]);
- EXPECT_EQ(val, cr_data[c_stride * y / 2 + x / 2]);
- }
+ EXPECT_EQ(val, yData[layout.yStride * y + x]);
+ if (y % 2 == 0 && x % 2 == 0) {
+ EXPECT_EQ(val, cbData[layout.cStride * y / 2 + x / 2]);
+ EXPECT_EQ(val, crData[layout.cStride * y / 2 + x / 2]);
+ }
+ }
}
- }
- ASSERT_NO_FATAL_FAILURE(fence = mMapper->unlock(buffer));
- if (fence >= 0) {
- close(fence);
- }
+ ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+ if (fence >= 0) {
+ close(fence);
+ }
}
-} // namespace anonymous
+/**
+ * Test IMapper::unlock with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, UnlockNegative) {
+ native_handle_t* invalidHandle = nullptr;
+ mGralloc->getMapper()->unlock(
+ invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with nullptr did not fail with BAD_BUFFER";
+ });
+
+ invalidHandle = native_handle_create(0, 0);
+ mGralloc->getMapper()->unlock(
+ invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with invalid handle did not fail with BAD_BUFFER";
+ });
+ native_handle_delete(invalidHandle);
+
+ ASSERT_NO_FATAL_FAILURE(invalidHandle =
+ const_cast<native_handle_t*>(mGralloc->allocate(
+ mDummyDescriptorInfo, false)));
+ mGralloc->getMapper()->unlock(invalidHandle, [&](const auto& tmpError,
+ const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with un-imported handle did not fail with BAD_BUFFER";
+ });
+ mGralloc->freeBuffer(invalidHandle);
+
+// disabled as it fails on many existing drivers
+#if 0
+ ASSERT_NO_FATAL_FAILURE(invalidHandle = const_cast<native_handle_t*>(
+ mGralloc->allocate(mDummyDescriptorInfo, true)));
+ mGralloc->getMapper()->unlock(
+ invalidHandle, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_BUFFER, tmpError)
+ << "unlock with unlocked handle did not fail with BAD_BUFFER";
+ });
+ mGralloc->freeBuffer(invalidHandle);
+#endif
+}
+
+} // namespace
} // namespace tests
} // namespace V2_0
} // namespace mapper
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
index fd43178..849d270 100644
--- a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -1,4 +1,4 @@
service keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
- class hal
+ class early_hal
user system
group system drmrpc
diff --git a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
index a8d8aea..6ff566e 100644
--- a/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
+++ b/memtrack/1.0/vts/functional/VtsHalMemtrackV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
#include <VtsHalHidlTargetTestBase.h>
+#include <fcntl.h>
#include <algorithm>
#include <vector>
diff --git a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
index cd1a261..c94fa4f 100644
--- a/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
+++ b/power/1.0/vts/functional/VtsHalPowerV1_0TargetTest.cpp
@@ -24,6 +24,7 @@
#include <VtsHalHidlTargetTestBase.h>
+#include <fcntl.h>
#include <algorithm>
using ::android::hardware::power::V1_0::IPower;
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 9094f39..d40f15a 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -18,7 +18,7 @@
void RadioHidlTest::SetUp() {
radio = ::testing::VtsHalHidlTargetTestBase::getService<IRadio>(
- hidl_string("rild"));
+ hidl_string(RADIO_SERVICE_NAME));
ASSERT_NE(radio, nullptr);
radioRsp = new RadioResponse(*this);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils.h b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
index 6826238..51db87b 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils.h
@@ -81,6 +81,7 @@
using ::android::sp;
#define TIMEOUT_PERIOD 40
+#define RADIO_SERVICE_NAME "slot1"
class RadioHidlTest;
extern CardStatus cardStatus;
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index 88274cd..02accef 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -18,7 +18,7 @@
void SapHidlTest::SetUp() {
sap = ::testing::VtsHalHidlTargetTestBase::getService<ISap>(
- hidl_string("sap_uim_socket1"));
+ hidl_string(SAP_SERVICE_NAME));
ASSERT_NE(sap, nullptr);
sapCb = new SapCallback(*this);
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_utils.h b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
index 2ee3c96..38fb003 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_utils.h
+++ b/radio/1.0/vts/functional/sap_hidl_hal_utils.h
@@ -34,6 +34,7 @@
using ::android::sp;
#define TIMEOUT_PERIOD 40
+#define SAP_SERVICE_NAME "slot1"
class SapHidlTest;
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index a65c7b8..f757a64 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,14 +15,14 @@
*/
#define LOG_TAG "sensors_hidl_hal_test"
+#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/sensors/1.0/ISensors.h>
#include <android/hardware/sensors/1.0/types.h>
-#include <android/log.h>
#include <cutils/ashmem.h>
+#include <hardware/sensors.h> // for sensor type strings
+#include <log/log.h>
#include <utils/SystemClock.h>
-#include <VtsHalHidlTargetTestBase.h>
-#include <hardware/sensors.h> // for sensor type strings
#include <algorithm>
#include <cinttypes>
@@ -616,7 +616,7 @@
switch (type) {
#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
- case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType); break;
+ case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType.c_str()); break;
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
diff --git a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
index 3fbef18..2eca8f4 100644
--- a/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
+++ b/soundtrigger/2.0/vts/functional/VtsHalSoundtriggerV2_0TargetTest.cpp
@@ -23,6 +23,7 @@
#include <android/log.h>
#include <cutils/native_handle.h>
+#include <log/log.h>
#include <android/hardware/audio/common/2.0/types.h>
#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
diff --git a/tests/baz/1.0/Android.bp b/tests/baz/1.0/Android.bp
index 8f327e3..1d5013b 100644
--- a/tests/baz/1.0/Android.bp
+++ b/tests/baz/1.0/Android.bp
@@ -7,6 +7,7 @@
"IBase.hal",
"IBaz.hal",
"IBazCallback.hal",
+ "IQuux.hal",
],
}
@@ -22,6 +23,7 @@
"android/hardware/tests/baz/1.0/BaseAll.cpp",
"android/hardware/tests/baz/1.0/BazAll.cpp",
"android/hardware/tests/baz/1.0/BazCallbackAll.cpp",
+ "android/hardware/tests/baz/1.0/QuuxAll.cpp",
],
}
@@ -50,6 +52,11 @@
"android/hardware/tests/baz/1.0/BnHwBazCallback.h",
"android/hardware/tests/baz/1.0/BpHwBazCallback.h",
"android/hardware/tests/baz/1.0/BsBazCallback.h",
+ "android/hardware/tests/baz/1.0/IQuux.h",
+ "android/hardware/tests/baz/1.0/IHwQuux.h",
+ "android/hardware/tests/baz/1.0/BnHwQuux.h",
+ "android/hardware/tests/baz/1.0/BpHwQuux.h",
+ "android/hardware/tests/baz/1.0/BsQuux.h",
],
}
diff --git a/tests/baz/1.0/Android.mk b/tests/baz/1.0/Android.mk
index 40026ec..9d4d6b6 100644
--- a/tests/baz/1.0/Android.mk
+++ b/tests/baz/1.0/Android.mk
@@ -76,6 +76,25 @@
$(GEN): $(LOCAL_PATH)/IBazCallback.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IQuux.hal
+#
+GEN := $(intermediates)/android/hardware/tests/baz/V1_0/IQuux.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IQuux.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.tests.baz@1.0::IQuux
+
+$(GEN): $(LOCAL_PATH)/IQuux.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_JAVA_LIBRARY)
@@ -153,6 +172,25 @@
$(GEN): $(LOCAL_PATH)/IBazCallback.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IQuux.hal
+#
+GEN := $(intermediates)/android/hardware/tests/baz/V1_0/IQuux.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IQuux.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+ $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+ -Ljava \
+ -randroid.hardware:hardware/interfaces \
+ -randroid.hidl:system/libhidl/transport \
+ android.hardware.tests.baz@1.0::IQuux
+
+$(GEN): $(LOCAL_PATH)/IQuux.hal
+ $(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/baz/1.0/IQuux.hal b/tests/baz/1.0/IQuux.hal
new file mode 100644
index 0000000..ccf3212
--- /dev/null
+++ b/tests/baz/1.0/IQuux.hal
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tests.baz@1.0;
+
+interface IQuux {
+};
diff --git a/usb/1.0/default/Usb.h b/usb/1.0/default/Usb.h
index c34d080..ddfcac6 100644
--- a/usb/1.0/default/Usb.h
+++ b/usb/1.0/default/Usb.h
@@ -4,7 +4,7 @@
#include <android/hardware/usb/1.0/IUsb.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
-#include <utils/Log.h>
+#include <log/log.h>
#ifdef LOG_TAG
#undef LOG_TAG
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index ea6d4a9..b77398f 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -22,6 +22,7 @@
#include <android/hardware/usb/1.0/types.h>
#include <VtsHalHidlTargetTestBase.h>
+#include <log/log.h>
#include <stdlib.h>
#include <chrono>
#include <condition_variable>
diff --git a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
index a983731..23f4c71 100644
--- a/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
+++ b/vr/1.0/vts/functional/VtsHalVrV1_0TargetTest.cpp
@@ -15,11 +15,11 @@
*/
#define LOG_TAG "vr_hidl_hal_test"
+#include <VtsHalHidlTargetTestBase.h>
#include <android-base/logging.h>
#include <android/hardware/vr/1.0/IVr.h>
-#include <android/log.h>
-#include <VtsHalHidlTargetTestBase.h>
#include <hardware/vr.h>
+#include <log/log.h>
using ::android::hardware::vr::V1_0::IVr;
using ::android::hardware::Return;
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index 42d9a96..c0af30b 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -20,9 +20,13 @@
#include <VtsHalHidlTargetTestBase.h>
+#include "wifi_hidl_call_util.h"
#include "wifi_hidl_test_utils.h"
+using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifiApIface;
+using ::android::hardware::wifi::V1_0::WifiBand;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::sp;
/**
@@ -30,11 +34,15 @@
*/
class WifiApIfaceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
public:
- virtual void SetUp() override {}
+ virtual void SetUp() override {
+ wifi_ap_iface_ = getWifiApIface();
+ ASSERT_NE(nullptr, wifi_ap_iface_.get());
+ }
virtual void TearDown() override { stopWifi(); }
protected:
+ sp<IWifiApIface> wifi_ap_iface_;
};
/*
@@ -46,3 +54,36 @@
EXPECT_NE(nullptr, getWifiApIface().get());
stopWifi();
}
+
+/*
+ * GetType:
+ * Ensures that the correct interface type is returned for AP interface.
+ */
+TEST_F(WifiApIfaceHidlTest, GetType) {
+ const auto& status_and_type = HIDL_INVOKE(wifi_ap_iface_, getType);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
+ EXPECT_EQ(IfaceType::AP, status_and_type.second);
+}
+
+/*
+ * SetCountryCode:
+ * Ensures that a call to set the country code will return with a success
+ * status code.
+ */
+TEST_F(WifiApIfaceHidlTest, SetCountryCode) {
+ const android::hardware::hidl_array<int8_t, 2> kCountryCode{
+ std::array<int8_t, 2>{{0x55, 0x53}}};
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_ap_iface_, setCountryCode, kCountryCode).code);
+}
+
+/*
+ * GetValidFrequenciesForBand:
+ * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
+ */
+TEST_F(WifiApIfaceHidlTest, GetValidFrequenciesForBand) {
+ const auto& status_and_freqs = HIDL_INVOKE(
+ wifi_ap_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
+ EXPECT_GT(status_and_freqs.second.size(), 0u);
+}
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
index 084067c..0627a99 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_test.cpp
@@ -76,15 +76,14 @@
// Helper function to configure the Chip in one of the supported modes.
// Most of the non-mode-configuration-related methods require chip
// to be first configured.
- ChipModeId configureChipForIfaceType(IfaceType type) {
+ ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) {
ChipModeId mode_id;
- EXPECT_TRUE(
- configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
+ EXPECT_EQ(expectSuccess, configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
return mode_id;
}
uint32_t configureChipForStaIfaceAndGetCapabilities() {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
return status_and_caps.second;
@@ -183,7 +182,7 @@
* GetCapabilities:
*/
TEST_F(WifiChipHidlTest, GetCapabilities) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
EXPECT_NE(0u, status_and_caps.second);
@@ -193,7 +192,7 @@
* GetMode:
*/
TEST_F(WifiChipHidlTest, GetMode) {
- ChipModeId chip_mode_id = configureChipForIfaceType(IfaceType::STA);
+ ChipModeId chip_mode_id = configureChipForIfaceType(IfaceType::STA, true);
const auto& status_and_mode = HIDL_INVOKE(wifi_chip_, getMode);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_mode.first.code);
EXPECT_EQ(chip_mode_id, status_and_mode.second);
@@ -203,7 +202,7 @@
* RequestChipDebugInfo:
*/
TEST_F(WifiChipHidlTest, RequestChipDebugInfo) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
const auto& status_and_chip_info =
HIDL_INVOKE(wifi_chip_, requestChipDebugInfo);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_chip_info.first.code);
@@ -236,8 +235,10 @@
if (caps & IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_DRIVER_DUMP) {
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_driver_dump.first.code);
} else {
- EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
- status_and_driver_dump.first.code);
+ // API semantics (today) are such that function cannot be called if not capable!
+ //
+ // EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
+ // status_and_driver_dump.first.code);
}
}
@@ -336,7 +337,7 @@
* succeeds. The 2nd iface creation should be rejected.
*/
TEST_F(WifiChipHidlTest, CreateApIface) {
- configureChipForIfaceType(IfaceType::AP);
+ configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&iface));
@@ -352,7 +353,7 @@
* iface name is returned via the list.
*/
TEST_F(WifiChipHidlTest, GetApIfaceNames) {
- configureChipForIfaceType(IfaceType::AP);
+ configureChipForIfaceType(IfaceType::AP, true);
const auto& status_and_iface_names1 =
HIDL_INVOKE(wifi_chip_, getApIfaceNames);
@@ -384,7 +385,7 @@
* doesn't retrieve an iface object.
*/
TEST_F(WifiChipHidlTest, GetApIface) {
- configureChipForIfaceType(IfaceType::AP);
+ configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> ap_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&ap_iface));
@@ -410,7 +411,7 @@
* doesn't remove the iface.
*/
TEST_F(WifiChipHidlTest, RemoveApIface) {
- configureChipForIfaceType(IfaceType::AP);
+ configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> ap_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&ap_iface));
@@ -431,13 +432,10 @@
* succeeds. The 2nd iface creation should be rejected.
*/
TEST_F(WifiChipHidlTest, CreateNanIface) {
- configureChipForIfaceType(IfaceType::NAN);
+ configureChipForIfaceType(IfaceType::NAN, false);
sp<IWifiNanIface> iface;
- EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&iface));
- EXPECT_NE(nullptr, iface.get());
-
- EXPECT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&iface));
+ ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&iface));
}
/*
@@ -447,29 +445,12 @@
* iface name is returned via the list.
*/
TEST_F(WifiChipHidlTest, GetNanIfaceNames) {
- configureChipForIfaceType(IfaceType::NAN);
+ configureChipForIfaceType(IfaceType::NAN, false);
const auto& status_and_iface_names1 =
HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names1.first.code);
+ ASSERT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names1.first.code);
EXPECT_EQ(0u, status_and_iface_names1.second.size());
-
- sp<IWifiNanIface> iface;
- EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&iface));
- EXPECT_NE(nullptr, iface.get());
-
- std::string iface_name = getIfaceName(iface);
- const auto& status_and_iface_names2 =
- HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names2.first.code);
- EXPECT_EQ(1u, status_and_iface_names2.second.size());
- EXPECT_EQ(iface_name, status_and_iface_names2.second[0]);
-
- EXPECT_EQ(WifiStatusCode::SUCCESS, removeNanIface(iface_name));
- const auto& status_and_iface_names3 =
- HIDL_INVOKE(wifi_chip_, getNanIfaceNames);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface_names3.first.code);
- EXPECT_EQ(0u, status_and_iface_names3.second.size());
}
/*
@@ -479,23 +460,10 @@
* doesn't retrieve an iface object.
*/
TEST_F(WifiChipHidlTest, GetNanIface) {
- configureChipForIfaceType(IfaceType::NAN);
+ configureChipForIfaceType(IfaceType::NAN, false);
sp<IWifiNanIface> nan_iface;
- EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&nan_iface));
- EXPECT_NE(nullptr, nan_iface.get());
-
- std::string iface_name = getIfaceName(nan_iface);
- const auto& status_and_iface1 =
- HIDL_INVOKE(wifi_chip_, getNanIface, iface_name);
- EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface1.first.code);
- EXPECT_NE(nullptr, status_and_iface1.second.get());
-
- std::string invalid_name = iface_name + "0";
- const auto& status_and_iface2 =
- HIDL_INVOKE(wifi_chip_, getNanIface, invalid_name);
- EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, status_and_iface2.first.code);
- EXPECT_EQ(nullptr, status_and_iface2.second.get());
+ ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&nan_iface));
}
/*
@@ -505,20 +473,10 @@
* doesn't remove the iface.
*/
TEST_F(WifiChipHidlTest, RemoveNanIface) {
- configureChipForIfaceType(IfaceType::NAN);
+ configureChipForIfaceType(IfaceType::NAN, false);
sp<IWifiNanIface> nan_iface;
- EXPECT_EQ(WifiStatusCode::SUCCESS, createNanIface(&nan_iface));
- EXPECT_NE(nullptr, nan_iface.get());
-
- std::string iface_name = getIfaceName(nan_iface);
- std::string invalid_name = iface_name + "0";
- EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(invalid_name));
-
- EXPECT_EQ(WifiStatusCode::SUCCESS, removeNanIface(iface_name));
-
- // No such iface exists now. So, this should return failure.
- EXPECT_EQ(WifiStatusCode::ERROR_INVALID_ARGS, removeNanIface(iface_name));
+ ASSERT_EQ(WifiStatusCode::ERROR_NOT_AVAILABLE, createNanIface(&nan_iface));
}
/*
@@ -527,7 +485,7 @@
* succeeds. The 2nd iface creation should be rejected.
*/
TEST_F(WifiChipHidlTest, CreateP2pIface) {
- configureChipForIfaceType(IfaceType::P2P);
+ configureChipForIfaceType(IfaceType::P2P, true);
sp<IWifiP2pIface> iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&iface));
@@ -543,7 +501,7 @@
* iface name is returned via the list.
*/
TEST_F(WifiChipHidlTest, GetP2pIfaceNames) {
- configureChipForIfaceType(IfaceType::P2P);
+ configureChipForIfaceType(IfaceType::P2P, true);
const auto& status_and_iface_names1 =
HIDL_INVOKE(wifi_chip_, getP2pIfaceNames);
@@ -575,7 +533,7 @@
* doesn't retrieve an iface object.
*/
TEST_F(WifiChipHidlTest, GetP2pIface) {
- configureChipForIfaceType(IfaceType::P2P);
+ configureChipForIfaceType(IfaceType::P2P, true);
sp<IWifiP2pIface> p2p_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
@@ -601,7 +559,7 @@
* doesn't remove the iface.
*/
TEST_F(WifiChipHidlTest, RemoveP2pIface) {
- configureChipForIfaceType(IfaceType::P2P);
+ configureChipForIfaceType(IfaceType::P2P, true);
sp<IWifiP2pIface> p2p_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createP2pIface(&p2p_iface));
@@ -622,7 +580,7 @@
* succeeds. The 2nd iface creation should be rejected.
*/
TEST_F(WifiChipHidlTest, CreateStaIface) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
sp<IWifiStaIface> iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&iface));
@@ -638,7 +596,7 @@
* iface name is returned via the list.
*/
TEST_F(WifiChipHidlTest, GetStaIfaceNames) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
const auto& status_and_iface_names1 =
HIDL_INVOKE(wifi_chip_, getStaIfaceNames);
@@ -670,7 +628,7 @@
* doesn't retrieve an iface object.
*/
TEST_F(WifiChipHidlTest, GetStaIface) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
sp<IWifiStaIface> sta_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
@@ -696,7 +654,7 @@
* doesn't remove the iface.
*/
TEST_F(WifiChipHidlTest, RemoveStaIface) {
- configureChipForIfaceType(IfaceType::STA);
+ configureChipForIfaceType(IfaceType::STA, true);
sp<IWifiStaIface> sta_iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createStaIface(&sta_iface));
@@ -715,7 +673,7 @@
* CreateRttController
*/
TEST_F(WifiChipHidlTest, CreateRttController) {
- configureChipForIfaceType(IfaceType::AP);
+ configureChipForIfaceType(IfaceType::AP, true);
sp<IWifiApIface> iface;
EXPECT_EQ(WifiStatusCode::SUCCESS, createApIface(&iface));
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index 95add61..83f83b6 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -24,7 +24,16 @@
#include "wifi_hidl_test_utils.h"
using ::android::sp;
+using ::android::hardware::wifi::V1_0::Bssid;
+using ::android::hardware::wifi::V1_0::CommandId;
+using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifiStaIface;
+using ::android::hardware::wifi::V1_0::Rssi;
+using ::android::hardware::wifi::V1_0::Ssid;
+using ::android::hardware::wifi::V1_0::StaApfPacketFilterCapabilities;
+using ::android::hardware::wifi::V1_0::StaRoamingConfig;
+using ::android::hardware::wifi::V1_0::StaRoamingState;
+using ::android::hardware::wifi::V1_0::WifiBand;
using ::android::hardware::wifi::V1_0::WifiStatus;
using ::android::hardware::wifi::V1_0::WifiStatusCode;
@@ -41,6 +50,13 @@
virtual void TearDown() override { stopWifi(); }
protected:
+ bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask cap_mask) {
+ const auto& status_and_caps =
+ HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+ return (status_and_caps.second & cap_mask) != 0;
+ }
+
sp<IWifiStaIface> wifi_sta_iface_;
};
@@ -60,5 +76,190 @@
TEST_F(WifiStaIfaceHidlTest, GetCapabilities) {
const auto& status_and_caps = HIDL_INVOKE(wifi_sta_iface_, getCapabilities);
EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
- EXPECT_NE(0u, status_and_caps.second);
+ EXPECT_GT(status_and_caps.second, 0u);
+}
+
+/*
+ * GetType:
+ * Ensures that the correct interface type is returned for station interface.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetType) {
+ const auto& status_and_type = HIDL_INVOKE(wifi_sta_iface_, getType);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_type.first.code);
+ EXPECT_EQ(IfaceType::STA, status_and_type.second);
+}
+
+/*
+ * GetApfPacketFilterCapabilities:
+ * Ensures that we can retrieve APF packet filter capabilites.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetApfPacketFilterCapabilities) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
+ // No-op if APF packet filer is not supported.
+ return;
+ }
+
+ const auto& status_and_caps =
+ HIDL_INVOKE(wifi_sta_iface_, getApfPacketFilterCapabilities);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+}
+
+/*
+ * GetBackgroundScanCapabilities:
+ * Ensures that we can retrieve background scan capabilities.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetBackgroundScanCapabilities) {
+ if (!isCapabilitySupported(
+ IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN)) {
+ // No-op if background scan is not supported.
+ return;
+ }
+
+ const auto& status_and_caps =
+ HIDL_INVOKE(wifi_sta_iface_, getBackgroundScanCapabilities);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+}
+
+/*
+ * GetValidFrequenciesForBand:
+ * Ensures that we can retrieve valid frequencies for 2.4 GHz band.
+ */
+TEST_F(WifiStaIfaceHidlTest, GetValidFrequenciesForBand) {
+ const auto& status_and_freqs = HIDL_INVOKE(
+ wifi_sta_iface_, getValidFrequenciesForBand, WifiBand::BAND_24GHZ);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_freqs.first.code);
+ EXPECT_GT(status_and_freqs.second.size(), 0u);
+}
+
+/*
+ * LinkLayerStatsCollection:
+ * Ensures that calls to enable, disable, and retrieve link layer stats
+ * will return a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, LinkLayerStatsCollection) {
+ if (!isCapabilitySupported(
+ IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+ // No-op if link layer stats is not supported.
+ return;
+ }
+
+ // Enable link layer stats collection.
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
+ .code);
+ // Retrieve link layer stats.
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, getLinkLayerStats).first.code);
+ // Disable link layer stats collection.
+ EXPECT_EQ(
+ WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, disableLinkLayerStatsCollection).code);
+}
+
+/*
+ * RSSIMonitoring:
+ * Ensures that calls to enable and disable RSSI monitoring will return
+ * a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, RSSIMonitoring) {
+ if (!isCapabilitySupported(
+ IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR)) {
+ // No-op if RSSI monitor is not supported.
+ return;
+ }
+
+ const CommandId kCmd = 1;
+ const Rssi kMaxRssi = -50;
+ const Rssi kMinRssi = -90;
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, startRssiMonitoring, kCmd, kMaxRssi,
+ kMinRssi)
+ .code);
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, stopRssiMonitoring, kCmd).code);
+}
+
+/*
+ * RoamingControl:
+ * Ensures that calls to configure and enable roaming will return a success
+ * status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, RoamingControl) {
+ if (!isCapabilitySupported(
+ IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING)) {
+ // No-op if roaming control is not supported.
+ return;
+ }
+
+ // Retrieve roaming capabilities.
+ const auto& status_and_cap =
+ HIDL_INVOKE(wifi_sta_iface_, getRoamingCapabilities);
+ EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_cap.first.code);
+
+ // Setup roaming configuration based on roaming capabilities.
+ const auto& cap = status_and_cap.second;
+ StaRoamingConfig roaming_config;
+ if (cap.maxBlacklistSize > 0) {
+ Bssid black_list_bssid{
+ std::array<uint8_t, 6>{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}}};
+ roaming_config.bssidBlacklist =
+ android::hardware::hidl_vec<Bssid>{black_list_bssid};
+ }
+ if (cap.maxWhitelistSize > 0) {
+ Ssid white_list_ssid{
+ std::array<uint8_t, 32>{{0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC}}};
+ roaming_config.ssidWhitelist =
+ android::hardware::hidl_vec<Ssid>{white_list_ssid};
+ }
+
+ // Configure roaming.
+ EXPECT_EQ(
+ WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, configureRoaming, roaming_config).code);
+
+ // Enable roaming.
+ EXPECT_EQ(
+ WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, setRoamingState, StaRoamingState::ENABLED)
+ .code);
+}
+
+/*
+ * EnableNDOffload:
+ * Ensures that calls to enable neighbor discovery offload will return a success
+ * status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, EnableNDOffload) {
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, enableNdOffload, true).code);
+}
+
+/*
+ * SetScanningMacOui:
+ * Ensures that calls to set scanning MAC OUI will return a success status
+ * code.
+ */
+TEST_F(WifiStaIfaceHidlTest, SetScanningMacOui) {
+ const android::hardware::hidl_array<uint8_t, 3> kOui{
+ std::array<uint8_t, 3>{{0x10, 0x22, 0x33}}};
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, setScanningMacOui, kOui).code);
+}
+
+/*
+ * PacketFateMonitoring:
+ * Ensures that calls to start packet fate monitoring and retrieve TX/RX
+ * packets will return a success status code.
+ */
+TEST_F(WifiStaIfaceHidlTest, PacketFateMonitoring) {
+ // Start packet fate monitoring.
+ EXPECT_EQ(
+ WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, startDebugPacketFateMonitoring).code);
+
+ // Retrieve packets.
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, getDebugTxPacketFates).first.code);
+ EXPECT_EQ(WifiStatusCode::SUCCESS,
+ HIDL_INVOKE(wifi_sta_iface_, getDebugRxPacketFates).first.code);
}
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
new file mode 100644
index 0000000..1c0fcec
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_call_util.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+// This file is copied from
+// hardware/interfaces/wifi/1.0/vts/functional/wifi_hidl_call_util.h
+// Please make sure these two file are consistent.
+
+#pragma once
+
+#include <functional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace {
+namespace detail {
+template <typename>
+struct functionArgSaver;
+
+// Provides a std::function that takes one argument, and a buffer
+// wherein the function will store its argument. The buffer has
+// the same type as the argument, but with const and reference
+// modifiers removed.
+template <typename ArgT>
+struct functionArgSaver<std::function<void(ArgT)>> final {
+ using StorageT = typename std::remove_const<
+ typename std::remove_reference<ArgT>::type>::type;
+
+ std::function<void(ArgT)> saveArgs = [this](ArgT arg) {
+ this->saved_values = arg;
+ };
+
+ StorageT saved_values;
+};
+
+// Provides a std::function that takes two arguments, and a buffer
+// wherein the function will store its arguments. The buffer is a
+// std::pair, whose elements have the same types as the arguments
+// (but with const and reference modifiers removed).
+template <typename Arg1T, typename Arg2T>
+struct functionArgSaver<std::function<void(Arg1T, Arg2T)>> final {
+ using StorageT =
+ std::pair<typename std::remove_const<
+ typename std::remove_reference<Arg1T>::type>::type,
+ typename std::remove_const<
+ typename std::remove_reference<Arg2T>::type>::type>;
+
+ std::function<void(Arg1T, Arg2T)> saveArgs = [this](Arg1T arg1,
+ Arg2T arg2) {
+ this->saved_values = {arg1, arg2};
+ };
+
+ StorageT saved_values;
+};
+
+// Provides a std::function that takes three or more arguments, and a
+// buffer wherein the function will store its arguments. The buffer is a
+// std::tuple whose elements have the same types as the arguments (but
+// with const and reference modifiers removed).
+template <typename... ArgT>
+struct functionArgSaver<std::function<void(ArgT...)>> final {
+ using StorageT = std::tuple<typename std::remove_const<
+ typename std::remove_reference<ArgT>::type>::type...>;
+
+ std::function<void(ArgT...)> saveArgs = [this](ArgT... arg) {
+ this->saved_values = {arg...};
+ };
+
+ StorageT saved_values;
+};
+
+// Invokes |method| on |object|, providing |method| a CallbackT as the
+// final argument. Returns a copy of the parameters that |method| provided
+// to CallbackT. (The parameters are returned by value.)
+template <typename CallbackT, typename MethodT, typename ObjectT,
+ typename... ArgT>
+typename functionArgSaver<CallbackT>::StorageT invokeMethod(
+ MethodT method, ObjectT object, ArgT&&... methodArg) {
+ functionArgSaver<CallbackT> result_buffer;
+ const auto& res = ((*object).*method)(std::forward<ArgT>(methodArg)...,
+ result_buffer.saveArgs);
+ EXPECT_TRUE(res.isOk());
+ return result_buffer.saved_values;
+}
+} // namespace detail
+} // namespace
+
+// Invokes |method| on |strong_pointer|, passing provided arguments through to
+// |method|.
+//
+// Returns either:
+// - A copy of the result callback parameter (for callbacks with a single
+// parameter), OR
+// - A pair containing a copy of the result callback parameters (for callbacks
+// with two parameters), OR
+// - A tuple containing a copy of the result callback paramters (for callbacks
+// with three or more parameters).
+//
+// Example usage:
+// EXPECT_EQ(WifiStatusCode::SUCCESS,
+// HIDL_INVOKE(strong_pointer, methodReturningWifiStatus).code);
+// EXPECT_EQ(WifiStatusCode::SUCCESS,
+// HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndOneMore)
+// .first.code);
+// EXPECT_EQ(WifiStatusCode::SUCCESS, std::get<0>(
+// HIDL_INVOKE(strong_pointer, methodReturningWifiStatusAndTwoMore))
+// .code);
+#define HIDL_INVOKE(strong_pointer, method, ...) \
+ (detail::invokeMethod< \
+ std::remove_reference<decltype(*strong_pointer)>::type::method##_cb>( \
+ &std::remove_reference<decltype(*strong_pointer)>::type::method, \
+ strong_pointer, ##__VA_ARGS__))
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 72a3c42..7bb43b8 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -219,10 +219,6 @@
p2p_iface_->stopFind([](const SupplicantStatus& status) {
EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
});
-
- p2p_iface_->stopFind([](const SupplicantStatus& status) {
- EXPECT_NE(SupplicantStatusCode::SUCCESS, status.code);
- });
}
/*