diff options
author | android-build-team Robot | 2018-05-13 02:20:21 -0500 |
---|---|---|
committer | android-build-team Robot | 2018-05-13 02:20:21 -0500 |
commit | 5753b07c0ad86dfbe4eec97632b04c3e1cf6335a (patch) | |
tree | 561f25c798c4961b3278af402ee44115efe583e5 | |
parent | 0541524eaa7388ea84260590b542b6c12e869eda (diff) | |
parent | 68995cb341a4617f3a09bff033e26e4737e51b0e (diff) | |
download | platform-hardware-interfaces-5753b07c0ad86dfbe4eec97632b04c3e1cf6335a.tar.gz platform-hardware-interfaces-5753b07c0ad86dfbe4eec97632b04c3e1cf6335a.tar.xz platform-hardware-interfaces-5753b07c0ad86dfbe4eec97632b04c3e1cf6335a.zip |
Snap for 4778776 from 68995cb341a4617f3a09bff033e26e4737e51b0e to pi-release
Change-Id: Ibe87ea0251977289fedeb848e0672be46e48fac1
18 files changed, 754 insertions, 188 deletions
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index 774bc4f8..22ab079f 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp | |||
@@ -62,6 +62,8 @@ cc_library_static { | |||
62 | "impl/vhal_v2_0/VehicleEmulator.cpp", | 62 | "impl/vhal_v2_0/VehicleEmulator.cpp", |
63 | "impl/vhal_v2_0/PipeComm.cpp", | 63 | "impl/vhal_v2_0/PipeComm.cpp", |
64 | "impl/vhal_v2_0/SocketComm.cpp", | 64 | "impl/vhal_v2_0/SocketComm.cpp", |
65 | "impl/vhal_v2_0/LinearFakeValueGenerator.cpp", | ||
66 | "impl/vhal_v2_0/JsonFakeValueGenerator.cpp", | ||
65 | ], | 67 | ], |
66 | local_include_dirs: ["common/include/vhal_v2_0"], | 68 | local_include_dirs: ["common/include/vhal_v2_0"], |
67 | export_include_dirs: ["impl"], | 69 | export_include_dirs: ["impl"], |
@@ -71,6 +73,7 @@ cc_library_static { | |||
71 | "libprotobuf-cpp-lite", | 73 | "libprotobuf-cpp-lite", |
72 | ], | 74 | ], |
73 | static_libs: [ | 75 | static_libs: [ |
76 | "libjsoncpp", | ||
74 | "libqemu_pipe", | 77 | "libqemu_pipe", |
75 | "android.hardware.automotive.vehicle@2.0-libproto-native", | 78 | "android.hardware.automotive.vehicle@2.0-libproto-native", |
76 | ], | 79 | ], |
@@ -107,6 +110,7 @@ cc_binary { | |||
107 | "android.hardware.automotive.vehicle@2.0-manager-lib", | 110 | "android.hardware.automotive.vehicle@2.0-manager-lib", |
108 | "android.hardware.automotive.vehicle@2.0-default-impl-lib", | 111 | "android.hardware.automotive.vehicle@2.0-default-impl-lib", |
109 | "android.hardware.automotive.vehicle@2.0-libproto-native", | 112 | "android.hardware.automotive.vehicle@2.0-libproto-native", |
113 | "libjsoncpp", | ||
110 | "libqemu_pipe", | 114 | "libqemu_pipe", |
111 | ], | 115 | ], |
112 | } | 116 | } |
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 348f8783..012af1e0 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 | |||
@@ -42,38 +42,66 @@ constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK; | |||
42 | constexpr int ALL_WHEELS = | 42 | constexpr int ALL_WHEELS = |
43 | (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR); | 43 | (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR); |
44 | 44 | ||
45 | /* | 45 | /** |
46 | * This property is used for test purpose to generate fake events. | 46 | * This property is used for test purpose to generate fake events. Here is the test package that |
47 | * | 47 | * is referencing this property definition: packages/services/Car/tests/vehiclehal_test |
48 | * It has the following format: | ||
49 | * | ||
50 | * int32Values[0] - command (see FakeDataCommand below for possible values) | ||
51 | * int32Values[1] - VehicleProperty to which command applies | ||
52 | */ | 48 | */ |
53 | const int32_t kGenerateFakeDataControllingProperty = | 49 | const int32_t kGenerateFakeDataControllingProperty = |
54 | 0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; | 50 | 0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED; |
55 | 51 | ||
52 | /** | ||
53 | * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty. | ||
54 | * All those commands can be send independently with each other. And each will override the one sent | ||
55 | * previously. | ||
56 | * | ||
57 | * The controlling property has the following format: | ||
58 | * | ||
59 | * int32Values[0] - command enum defined in FakeDataCommand | ||
60 | * | ||
61 | * The format of the arguments is defined for each command type as below: | ||
62 | */ | ||
56 | enum class FakeDataCommand : int32_t { | 63 | enum class FakeDataCommand : int32_t { |
57 | /** Stops generating of fake data that was triggered by Start command */ | ||
58 | Stop = 0, | ||
59 | |||
60 | /** | 64 | /** |
61 | * Starts fake data generation. Caller must provide additional data: | 65 | * Starts linear fake data generation. Caller must provide additional data: |
66 | * int32Values[1] - VehicleProperty to which command applies | ||
62 | * int64Values[0] - periodic interval in nanoseconds | 67 | * int64Values[0] - periodic interval in nanoseconds |
63 | * floatValues[0] - initial value | 68 | * floatValues[0] - initial value |
64 | * floatValues[1] - dispersion defines min and max range relative to initial value | 69 | * floatValues[1] - dispersion defines the min/max value relative to initial value, where |
70 | * max = initial_value + dispersion, min = initial_value - dispersion. | ||
71 | * Dispersion should be non-negative, otherwise the behavior is undefined. | ||
65 | * floatValues[2] - increment, with every timer tick the value will be incremented by this | 72 | * floatValues[2] - increment, with every timer tick the value will be incremented by this |
66 | * amount | 73 | * amount. When reaching to max value, the current value will be set to min. |
74 | * It should be non-negative, otherwise the behavior is undefined. | ||
75 | */ | ||
76 | StartLinear = 0, | ||
77 | |||
78 | /** Stops generating of fake data that was triggered by Start commands. | ||
79 | * int32Values[1] - VehicleProperty to which command applies. VHAL will stop the | ||
80 | * corresponding linear generation for that property. | ||
81 | */ | ||
82 | StopLinear = 1, | ||
83 | |||
84 | /** | ||
85 | * Starts JSON-based fake data generation. Caller must provide a string value specifying | ||
86 | * the path to fake value JSON file: | ||
87 | * stringValue - path to the fake values JSON file | ||
88 | */ | ||
89 | StartJson = 2, | ||
90 | |||
91 | /** | ||
92 | * Stops JSON-based fake data generation. No additional arguments needed. | ||
67 | */ | 93 | */ |
68 | Start = 1, | 94 | StopJson = 3, |
69 | 95 | ||
70 | /** | 96 | /** |
71 | * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every | 97 | * Injects key press event (HAL incorporates UP/DOWN acction and triggers 2 HAL events for every |
72 | * key-press). Caller must provide the following data: int32Values[2] - Android key code | 98 | * key-press). We set the enum with high number to leave space for future start/stop commands. |
99 | * Caller must provide the following data: | ||
100 | * int32Values[2] - Android key code | ||
73 | * int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see | 101 | * int32Values[3] - target display (0 - for main display, 1 - for instrument cluster, see |
74 | * VehicleDisplay) | 102 | * VehicleDisplay) |
75 | */ | 103 | */ |
76 | KeyPress = 2, | 104 | KeyPress = 100, |
77 | }; | 105 | }; |
78 | 106 | ||
79 | const int32_t kHvacPowerProperties[] = { | 107 | const int32_t kHvacPowerProperties[] = { |
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp index 2eb905dc..fb541958 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <android-base/macros.h> | 19 | #include <android-base/macros.h> |
20 | 20 | ||
21 | #include "EmulatedVehicleHal.h" | 21 | #include "EmulatedVehicleHal.h" |
22 | #include "JsonFakeValueGenerator.h" | ||
23 | #include "LinearFakeValueGenerator.h" | ||
22 | #include "Obd2SensorStore.h" | 24 | #include "Obd2SensorStore.h" |
23 | 25 | ||
24 | namespace android { | 26 | namespace android { |
@@ -88,10 +90,12 @@ static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorInt | |||
88 | EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore) | 90 | EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore) |
89 | : mPropStore(propStore), | 91 | : mPropStore(propStore), |
90 | mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)), | 92 | mHvacPowerProps(std::begin(kHvacPowerProperties), std::end(kHvacPowerProperties)), |
91 | mRecurrentTimer(std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, | 93 | mRecurrentTimer( |
92 | this, std::placeholders::_1)), | 94 | std::bind(&EmulatedVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)), |
93 | mFakeValueGenerator(std::bind(&EmulatedVehicleHal::onFakeValueGenerated, | 95 | mLinearFakeValueGenerator(std::make_unique<LinearFakeValueGenerator>( |
94 | this, std::placeholders::_1, std::placeholders::_2)) { | 96 | std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))), |
97 | mJsonFakeValueGenerator(std::make_unique<JsonFakeValueGenerator>( | ||
98 | std::bind(&EmulatedVehicleHal::onFakeValueGenerated, this, std::placeholders::_1))) { | ||
95 | initStaticConfig(); | 99 | initStaticConfig(); |
96 | for (size_t i = 0; i < arraysize(kVehicleProperties); i++) { | 100 | for (size_t i = 0; i < arraysize(kVehicleProperties); i++) { |
97 | mPropStore->registerProperty(kVehicleProperties[i].config); | 101 | mPropStore->registerProperty(kVehicleProperties[i].config); |
@@ -328,42 +332,29 @@ std::vector<VehiclePropValue> EmulatedVehicleHal::getAllProperties() const { | |||
328 | StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropValue& request) { | 332 | StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropValue& request) { |
329 | ALOGI("%s", __func__); | 333 | ALOGI("%s", __func__); |
330 | const auto& v = request.value; | 334 | const auto& v = request.value; |
331 | if (v.int32Values.size() < 2) { | 335 | if (!v.int32Values.size()) { |
332 | ALOGE("%s: expected at least 2 elements in int32Values, got: %zu", __func__, | 336 | ALOGE("%s: expected at least \"command\" field in int32Values", __func__); |
333 | v.int32Values.size()); | ||
334 | return StatusCode::INVALID_ARG; | 337 | return StatusCode::INVALID_ARG; |
335 | } | 338 | } |
336 | 339 | ||
337 | FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]); | 340 | FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]); |
338 | int32_t propId = v.int32Values[1]; | ||
339 | 341 | ||
340 | switch (command) { | 342 | switch (command) { |
341 | case FakeDataCommand::Start: { | 343 | case FakeDataCommand::StartLinear: { |
342 | if (!v.int64Values.size()) { | 344 | ALOGI("%s, FakeDataCommand::StartLinear", __func__); |
343 | ALOGE("%s: interval is not provided in int64Values", __func__); | 345 | return mLinearFakeValueGenerator->start(request); |
344 | return StatusCode::INVALID_ARG; | ||
345 | } | ||
346 | auto interval = std::chrono::nanoseconds(v.int64Values[0]); | ||
347 | |||
348 | if (v.floatValues.size() < 3) { | ||
349 | ALOGE("%s: expected at least 3 element sin floatValues, got: %zu", __func__, | ||
350 | v.floatValues.size()); | ||
351 | return StatusCode::INVALID_ARG; | ||
352 | } | ||
353 | float initialValue = v.floatValues[0]; | ||
354 | float dispersion = v.floatValues[1]; | ||
355 | float increment = v.floatValues[2]; | ||
356 | |||
357 | ALOGI("%s, propId: %d, initalValue: %f", __func__, propId, initialValue); | ||
358 | mFakeValueGenerator.startGeneratingHalEvents( | ||
359 | interval, propId, initialValue, dispersion, increment); | ||
360 | |||
361 | break; | ||
362 | } | 346 | } |
363 | case FakeDataCommand::Stop: { | 347 | case FakeDataCommand::StartJson: { |
364 | ALOGI("%s, FakeDataCommand::Stop", __func__); | 348 | ALOGI("%s, FakeDataCommand::StartJson", __func__); |
365 | mFakeValueGenerator.stopGeneratingHalEvents(propId); | 349 | return mJsonFakeValueGenerator->start(request); |
366 | break; | 350 | } |
351 | case FakeDataCommand::StopLinear: { | ||
352 | ALOGI("%s, FakeDataCommand::StopLinear", __func__); | ||
353 | return mLinearFakeValueGenerator->stop(request); | ||
354 | } | ||
355 | case FakeDataCommand::StopJson: { | ||
356 | ALOGI("%s, FakeDataCommand::StopJson", __func__); | ||
357 | return mJsonFakeValueGenerator->stop(request); | ||
367 | } | 358 | } |
368 | case FakeDataCommand::KeyPress: { | 359 | case FakeDataCommand::KeyPress: { |
369 | ALOGI("%s, FakeDataCommand::KeyPress", __func__); | 360 | ALOGI("%s, FakeDataCommand::KeyPress", __func__); |
@@ -374,7 +365,6 @@ StatusCode EmulatedVehicleHal::handleGenerateFakeDataRequest(const VehiclePropVa | |||
374 | doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display)); | 365 | doHalEvent(createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display)); |
375 | break; | 366 | break; |
376 | } | 367 | } |
377 | |||
378 | default: { | 368 | default: { |
379 | ALOGE("%s: unexpected command: %d", __func__, command); | 369 | ALOGE("%s: unexpected command: %d", __func__, command); |
380 | return StatusCode::INVALID_ARG; | 370 | return StatusCode::INVALID_ARG; |
@@ -396,30 +386,16 @@ VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createHwInputKeyProp( | |||
396 | return keyEvent; | 386 | return keyEvent; |
397 | } | 387 | } |
398 | 388 | ||
399 | void EmulatedVehicleHal::onFakeValueGenerated(int32_t propId, float value) { | 389 | void EmulatedVehicleHal::onFakeValueGenerated(const VehiclePropValue& value) { |
390 | ALOGD("%s: %s", __func__, toString(value).c_str()); | ||
400 | static constexpr bool shouldUpdateStatus = false; | 391 | static constexpr bool shouldUpdateStatus = false; |
401 | 392 | ||
402 | VehiclePropValuePtr updatedPropValue {}; | 393 | VehiclePropValuePtr updatedPropValue = getValuePool()->obtain(value); |
403 | switch (getPropType(propId)) { | ||
404 | case VehiclePropertyType::FLOAT: | ||
405 | updatedPropValue = getValuePool()->obtainFloat(value); | ||
406 | break; | ||
407 | case VehiclePropertyType::INT32: | ||
408 | updatedPropValue = getValuePool()->obtainInt32(static_cast<int32_t>(value)); | ||
409 | break; | ||
410 | default: | ||
411 | ALOGE("%s: data type for property: 0x%x not supported", __func__, propId); | ||
412 | return; | ||
413 | |||
414 | } | ||
415 | |||
416 | if (updatedPropValue) { | 394 | if (updatedPropValue) { |
417 | updatedPropValue->prop = propId; | ||
418 | updatedPropValue->areaId = 0; // Add area support if necessary. | ||
419 | updatedPropValue->timestamp = elapsedRealtimeNano(); | 395 | updatedPropValue->timestamp = elapsedRealtimeNano(); |
420 | updatedPropValue->status = VehiclePropertyStatus::AVAILABLE; | 396 | updatedPropValue->status = VehiclePropertyStatus::AVAILABLE; |
421 | mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus); | 397 | mPropStore->writeValue(*updatedPropValue, shouldUpdateStatus); |
422 | auto changeMode = mPropStore->getConfigOrDie(propId)->changeMode; | 398 | auto changeMode = mPropStore->getConfigOrDie(value.prop)->changeMode; |
423 | if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) { | 399 | if (VehiclePropertyChangeMode::ON_CHANGE == changeMode) { |
424 | doHalEvent(move(updatedPropValue)); | 400 | doHalEvent(move(updatedPropValue)); |
425 | } | 401 | } |
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h index d291dbad..c188aefe 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h | |||
@@ -30,9 +30,10 @@ | |||
30 | #include "vhal_v2_0/VehiclePropertyStore.h" | 30 | #include "vhal_v2_0/VehiclePropertyStore.h" |
31 | 31 | ||
32 | #include "DefaultConfig.h" | 32 | #include "DefaultConfig.h" |
33 | #include "VehicleEmulator.h" | ||
34 | #include "FakeValueGenerator.h" | 33 | #include "FakeValueGenerator.h" |
35 | 34 | ||
35 | #include "VehicleEmulator.h" | ||
36 | |||
36 | namespace android { | 37 | namespace android { |
37 | namespace hardware { | 38 | namespace hardware { |
38 | namespace automotive { | 39 | namespace automotive { |
@@ -66,7 +67,7 @@ private: | |||
66 | } | 67 | } |
67 | 68 | ||
68 | StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request); | 69 | StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request); |
69 | void onFakeValueGenerated(int32_t propId, float value); | 70 | void onFakeValueGenerated(const VehiclePropValue& value); |
70 | VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode, | 71 | VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode, |
71 | int32_t targetDisplay); | 72 | int32_t targetDisplay); |
72 | 73 | ||
@@ -84,7 +85,8 @@ private: | |||
84 | VehiclePropertyStore* mPropStore; | 85 | VehiclePropertyStore* mPropStore; |
85 | std::unordered_set<int32_t> mHvacPowerProps; | 86 | std::unordered_set<int32_t> mHvacPowerProps; |
86 | RecurrentTimer mRecurrentTimer; | 87 | RecurrentTimer mRecurrentTimer; |
87 | FakeValueGenerator mFakeValueGenerator; | 88 | std::unique_ptr<FakeValueGenerator> mLinearFakeValueGenerator; |
89 | std::unique_ptr<FakeValueGenerator> mJsonFakeValueGenerator; | ||
88 | }; | 90 | }; |
89 | 91 | ||
90 | } // impl | 92 | } // impl |
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h index 7bbbb08f..1eeb88df 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/FakeValueGenerator.h | |||
@@ -14,15 +14,11 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ | 17 | #ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_ |
18 | #define android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ | 18 | #define android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_ |
19 | |||
20 | #include <chrono> | ||
21 | 19 | ||
22 | #include <android/hardware/automotive/vehicle/2.0/types.h> | 20 | #include <android/hardware/automotive/vehicle/2.0/types.h> |
23 | 21 | ||
24 | #include <vhal_v2_0/RecurrentTimer.h> | ||
25 | |||
26 | namespace android { | 22 | namespace android { |
27 | namespace hardware { | 23 | namespace hardware { |
28 | namespace automotive { | 24 | namespace automotive { |
@@ -31,89 +27,27 @@ namespace V2_0 { | |||
31 | 27 | ||
32 | namespace impl { | 28 | namespace impl { |
33 | 29 | ||
34 | class FakeValueGenerator { | 30 | using OnHalEvent = std::function<void(const VehiclePropValue& event)>; |
35 | private: | 31 | using MuxGuard = std::lock_guard<std::mutex>; |
36 | // In every timer tick we may want to generate new value based on initial value for debug | ||
37 | // purpose. It's better to have sequential values to see if events gets delivered in order | ||
38 | // to the client. | ||
39 | |||
40 | struct GeneratorCfg { | ||
41 | float initialValue; // | ||
42 | float currentValue; // Should be in range (initialValue +/- dispersion). | ||
43 | float dispersion; // Defines minimum and maximum value based on initial value. | ||
44 | float increment; // Value that we will be added to currentValue with each timer tick. | ||
45 | }; | ||
46 | 32 | ||
33 | class FakeValueGenerator { | ||
47 | public: | 34 | public: |
48 | using OnHalEvent = std::function<void(int32_t propId, float value)>; | 35 | virtual ~FakeValueGenerator() = default; |
49 | 36 | /** | |
50 | FakeValueGenerator(const OnHalEvent& onHalEvent) : | 37 | * Starts generating VHAL events |
51 | mOnHalEvent(onHalEvent), | 38 | * |
52 | mRecurrentTimer(std::bind(&FakeValueGenerator::onTimer, this, | 39 | * @param request in VehiclePropValue with required information to start fake data generation |
53 | std::placeholders::_1)) | 40 | * @return StatusCode of the start request |
54 | {} | 41 | */ |
55 | 42 | virtual StatusCode start(const VehiclePropValue& request) = 0; | |
56 | ~FakeValueGenerator() = default; | 43 | /** |
57 | 44 | * Stops generating VHAL events | |
58 | 45 | * @param request in VehiclePropValue with required information to stop fake data generation | |
59 | void startGeneratingHalEvents(std::chrono::nanoseconds interval, int propId, float initialValue, | 46 | * @return StatusCode of the stop request |
60 | float dispersion, float increment) { | 47 | */ |
61 | MuxGuard g(mLock); | 48 | virtual StatusCode stop(const VehiclePropValue& request) = 0; |
62 | |||
63 | removeLocked(propId); | ||
64 | |||
65 | mGenCfg.insert({propId, GeneratorCfg { | ||
66 | .initialValue = initialValue, | ||
67 | .currentValue = initialValue, | ||
68 | .dispersion = dispersion, | ||
69 | .increment = increment, | ||
70 | }}); | ||
71 | |||
72 | mRecurrentTimer.registerRecurrentEvent(interval, propId); | ||
73 | } | ||
74 | |||
75 | void stopGeneratingHalEvents(int propId) { | ||
76 | MuxGuard g(mLock); | ||
77 | if (propId == 0) { | ||
78 | // Remove all. | ||
79 | for (auto&& it : mGenCfg) { | ||
80 | removeLocked(it.first); | ||
81 | } | ||
82 | } else { | ||
83 | removeLocked(propId); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | private: | ||
88 | void removeLocked(int propId) { | ||
89 | if (mGenCfg.erase(propId)) { | ||
90 | mRecurrentTimer.unregisterRecurrentEvent(propId); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | void onTimer(const std::vector<int32_t>& properties) { | ||
95 | MuxGuard g(mLock); | ||
96 | |||
97 | for (int32_t propId : properties) { | ||
98 | auto& cfg = mGenCfg[propId]; | ||
99 | cfg.currentValue += cfg.increment; | ||
100 | if (cfg.currentValue > cfg.initialValue + cfg.dispersion) { | ||
101 | cfg.currentValue = cfg.initialValue - cfg.dispersion; | ||
102 | } | ||
103 | mOnHalEvent(propId, cfg.currentValue); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | private: | ||
108 | using MuxGuard = std::lock_guard<std::mutex>; | ||
109 | |||
110 | mutable std::mutex mLock; | ||
111 | OnHalEvent mOnHalEvent; | ||
112 | RecurrentTimer mRecurrentTimer; | ||
113 | std::unordered_map<int32_t, GeneratorCfg> mGenCfg; | ||
114 | }; | 49 | }; |
115 | 50 | ||
116 | |||
117 | } // impl | 51 | } // impl |
118 | 52 | ||
119 | } // namespace V2_0 | 53 | } // namespace V2_0 |
@@ -122,6 +56,4 @@ private: | |||
122 | } // namespace hardware | 56 | } // namespace hardware |
123 | } // namespace android | 57 | } // namespace android |
124 | 58 | ||
125 | 59 | #endif // android_hardware_automotive_vehicle_V2_0_impl_FakeValueGenerator_H_ | |
126 | |||
127 | #endif //android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ | ||
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp new file mode 100644 index 00000000..88b8f865 --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp | |||
@@ -0,0 +1,174 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "JsonFakeValueGenerator" | ||
18 | |||
19 | #include <fstream> | ||
20 | |||
21 | #include <log/log.h> | ||
22 | #include <vhal_v2_0/VehicleUtils.h> | ||
23 | |||
24 | #include "JsonFakeValueGenerator.h" | ||
25 | |||
26 | namespace android { | ||
27 | namespace hardware { | ||
28 | namespace automotive { | ||
29 | namespace vehicle { | ||
30 | namespace V2_0 { | ||
31 | |||
32 | namespace impl { | ||
33 | |||
34 | JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent) | ||
35 | : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {} | ||
36 | |||
37 | JsonFakeValueGenerator::~JsonFakeValueGenerator() { | ||
38 | mStopRequested = true; | ||
39 | { | ||
40 | MuxGuard g(mLock); | ||
41 | mGenCfg.index = 0; | ||
42 | mGenCfg.events.clear(); | ||
43 | } | ||
44 | mCond.notify_one(); | ||
45 | if (mThread.joinable()) { | ||
46 | mThread.join(); | ||
47 | } | ||
48 | } | ||
49 | |||
50 | StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) { | ||
51 | const auto& v = request.value; | ||
52 | if (v.stringValue.empty()) { | ||
53 | ALOGE("%s: path to JSON file is missing", __func__); | ||
54 | return StatusCode::INVALID_ARG; | ||
55 | } | ||
56 | const char* file = v.stringValue.c_str(); | ||
57 | std::ifstream ifs(file); | ||
58 | if (!ifs) { | ||
59 | ALOGE("%s: couldn't open %s for parsing.", __func__, file); | ||
60 | return StatusCode::INTERNAL_ERROR; | ||
61 | } | ||
62 | std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs); | ||
63 | |||
64 | { | ||
65 | MuxGuard g(mLock); | ||
66 | mGenCfg = {0, fakeVhalEvents}; | ||
67 | } | ||
68 | mCond.notify_one(); | ||
69 | return StatusCode::OK; | ||
70 | } | ||
71 | |||
72 | StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) { | ||
73 | const auto& v = request.value; | ||
74 | if (!v.stringValue.empty()) { | ||
75 | ALOGI("%s: %s", __func__, v.stringValue.c_str()); | ||
76 | } | ||
77 | |||
78 | { | ||
79 | MuxGuard g(mLock); | ||
80 | mGenCfg.index = 0; | ||
81 | mGenCfg.events.clear(); | ||
82 | } | ||
83 | mCond.notify_one(); | ||
84 | return StatusCode::OK; | ||
85 | } | ||
86 | |||
87 | std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) { | ||
88 | std::vector<VehiclePropValue> fakeVhalEvents; | ||
89 | |||
90 | Json::Reader reader; | ||
91 | Json::Value rawEvents; | ||
92 | if (!reader.parse(is, rawEvents)) { | ||
93 | ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, | ||
94 | reader.getFormattedErrorMessages().c_str()); | ||
95 | return fakeVhalEvents; | ||
96 | } | ||
97 | |||
98 | for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) { | ||
99 | Json::Value rawEvent = rawEvents[i]; | ||
100 | if (!rawEvent.isObject()) { | ||
101 | ALOGE("%s: VHAL JSON event should be an object, %s", __func__, | ||
102 | rawEvent.toStyledString().c_str()); | ||
103 | continue; | ||
104 | } | ||
105 | if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() || | ||
106 | rawEvent["timestamp"].empty()) { | ||
107 | ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__, | ||
108 | rawEvent.toStyledString().c_str()); | ||
109 | continue; | ||
110 | } | ||
111 | VehiclePropValue event = {.prop = rawEvent["prop"].asInt(), | ||
112 | .areaId = rawEvent["areaId"].asInt(), | ||
113 | .timestamp = rawEvent["timestamp"].asInt64()}; | ||
114 | |||
115 | Json::Value rawEventValue = rawEvent["value"]; | ||
116 | auto& value = event.value; | ||
117 | switch (getPropType(event.prop)) { | ||
118 | case VehiclePropertyType::BOOLEAN: | ||
119 | case VehiclePropertyType::INT32: | ||
120 | value.int32Values.resize(1); | ||
121 | value.int32Values[0] = rawEventValue.asInt(); | ||
122 | break; | ||
123 | case VehiclePropertyType::INT64: | ||
124 | value.int64Values.resize(1); | ||
125 | value.int64Values[0] = rawEventValue.asInt64(); | ||
126 | break; | ||
127 | case VehiclePropertyType::FLOAT: | ||
128 | value.floatValues.resize(1); | ||
129 | value.floatValues[0] = rawEventValue.asFloat(); | ||
130 | break; | ||
131 | case VehiclePropertyType::STRING: | ||
132 | value.stringValue = rawEventValue.asString(); | ||
133 | break; | ||
134 | default: | ||
135 | ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__, | ||
136 | event.prop, rawEventValue.asString().c_str()); | ||
137 | continue; | ||
138 | } | ||
139 | fakeVhalEvents.push_back(event); | ||
140 | } | ||
141 | return fakeVhalEvents; | ||
142 | } | ||
143 | |||
144 | void JsonFakeValueGenerator::loop() { | ||
145 | static constexpr auto kInvalidTime = TimePoint(Nanos::max()); | ||
146 | |||
147 | while (!mStopRequested) { | ||
148 | auto nextEventTime = kInvalidTime; | ||
149 | { | ||
150 | MuxGuard g(mLock); | ||
151 | if (mGenCfg.index < mGenCfg.events.size()) { | ||
152 | mOnHalEvent(mGenCfg.events[mGenCfg.index]); | ||
153 | } | ||
154 | if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) { | ||
155 | Nanos intervalNano = | ||
156 | static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp - | ||
157 | mGenCfg.events[mGenCfg.index].timestamp); | ||
158 | nextEventTime = Clock::now() + intervalNano; | ||
159 | } | ||
160 | mGenCfg.index++; | ||
161 | } | ||
162 | |||
163 | std::unique_lock<std::mutex> g(mLock); | ||
164 | mCond.wait_until(g, nextEventTime); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | } // namespace impl | ||
169 | |||
170 | } // namespace V2_0 | ||
171 | } // namespace vehicle | ||
172 | } // namespace automotive | ||
173 | } // namespace hardware | ||
174 | } // namespace android | ||
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h new file mode 100644 index 00000000..51da4c53 --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_ | ||
18 | #define android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_ | ||
19 | |||
20 | #include <atomic> | ||
21 | #include <chrono> | ||
22 | #include <condition_variable> | ||
23 | #include <iostream> | ||
24 | #include <thread> | ||
25 | |||
26 | #include <json/json.h> | ||
27 | |||
28 | #include "FakeValueGenerator.h" | ||
29 | |||
30 | namespace android { | ||
31 | namespace hardware { | ||
32 | namespace automotive { | ||
33 | namespace vehicle { | ||
34 | namespace V2_0 { | ||
35 | |||
36 | namespace impl { | ||
37 | |||
38 | class JsonFakeValueGenerator : public FakeValueGenerator { | ||
39 | private: | ||
40 | using Nanos = std::chrono::nanoseconds; | ||
41 | using Clock = std::chrono::steady_clock; | ||
42 | using TimePoint = std::chrono::time_point<Clock, Nanos>; | ||
43 | |||
44 | struct GeneratorCfg { | ||
45 | size_t index; | ||
46 | std::vector<VehiclePropValue> events; | ||
47 | }; | ||
48 | |||
49 | public: | ||
50 | JsonFakeValueGenerator(const OnHalEvent& onHalEvent); | ||
51 | ~JsonFakeValueGenerator(); | ||
52 | StatusCode start(const VehiclePropValue& request) override; | ||
53 | StatusCode stop(const VehiclePropValue& request) override; | ||
54 | |||
55 | private: | ||
56 | std::vector<VehiclePropValue> parseFakeValueJson(std::istream& is); | ||
57 | void loop(); | ||
58 | |||
59 | private: | ||
60 | OnHalEvent mOnHalEvent; | ||
61 | std::thread mThread; | ||
62 | mutable std::mutex mLock; | ||
63 | std::condition_variable mCond; | ||
64 | GeneratorCfg mGenCfg; | ||
65 | std::atomic_bool mStopRequested{false}; | ||
66 | }; | ||
67 | |||
68 | } // namespace impl | ||
69 | |||
70 | } // namespace V2_0 | ||
71 | } // namespace vehicle | ||
72 | } // namespace automotive | ||
73 | } // namespace hardware | ||
74 | } // namespace android | ||
75 | |||
76 | #endif // android_hardware_automotive_vehicle_V2_0_impl_JsonFakeValueGenerator_H_ | ||
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp new file mode 100644 index 00000000..8cb9322f --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.cpp | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "LinearFakeValueGenerator" | ||
18 | |||
19 | #include <log/log.h> | ||
20 | #include <vhal_v2_0/VehicleUtils.h> | ||
21 | |||
22 | #include "LinearFakeValueGenerator.h" | ||
23 | |||
24 | namespace android { | ||
25 | namespace hardware { | ||
26 | namespace automotive { | ||
27 | namespace vehicle { | ||
28 | namespace V2_0 { | ||
29 | |||
30 | namespace impl { | ||
31 | |||
32 | LinearFakeValueGenerator::LinearFakeValueGenerator(const OnHalEvent& onHalEvent) | ||
33 | : mOnHalEvent(onHalEvent), | ||
34 | mRecurrentTimer(std::bind(&LinearFakeValueGenerator::onTimer, this, std::placeholders::_1)) {} | ||
35 | |||
36 | StatusCode LinearFakeValueGenerator::start(const VehiclePropValue& request) { | ||
37 | const auto& v = request.value; | ||
38 | if (v.int32Values.size() < 2) { | ||
39 | ALOGE("%s: expected property ID in int32Values", __func__); | ||
40 | return StatusCode::INVALID_ARG; | ||
41 | } | ||
42 | int32_t propId = v.int32Values[1]; | ||
43 | |||
44 | if (!v.int64Values.size()) { | ||
45 | ALOGE("%s: interval is not provided in int64Values", __func__); | ||
46 | return StatusCode::INVALID_ARG; | ||
47 | } | ||
48 | auto interval = std::chrono::nanoseconds(v.int64Values[0]); | ||
49 | |||
50 | if (v.floatValues.size() < 3) { | ||
51 | ALOGE("%s: expected at least 3 elements in floatValues, got: %zu", __func__, | ||
52 | v.floatValues.size()); | ||
53 | return StatusCode::INVALID_ARG; | ||
54 | } | ||
55 | float initialValue = v.floatValues[0]; | ||
56 | float dispersion = v.floatValues[1]; | ||
57 | float increment = v.floatValues[2]; | ||
58 | |||
59 | MuxGuard g(mLock); | ||
60 | removeLocked(propId); | ||
61 | mGenCfg.insert({propId, GeneratorCfg{ | ||
62 | .initialValue = initialValue, | ||
63 | .currentValue = initialValue, | ||
64 | .dispersion = dispersion, | ||
65 | .increment = increment,}}); | ||
66 | |||
67 | mRecurrentTimer.registerRecurrentEvent(interval, propId); | ||
68 | return StatusCode::OK; | ||
69 | } | ||
70 | |||
71 | StatusCode LinearFakeValueGenerator::stop(const VehiclePropValue& request) { | ||
72 | const auto& v = request.value; | ||
73 | if (v.int32Values.size() < 2) { | ||
74 | ALOGE("%s: expected property ID in int32Values", __func__); | ||
75 | return StatusCode::INVALID_ARG; | ||
76 | } | ||
77 | int32_t propId = v.int32Values[1]; | ||
78 | |||
79 | MuxGuard g(mLock); | ||
80 | if (propId == 0) { | ||
81 | // Remove all. | ||
82 | for (auto&& it : mGenCfg) { | ||
83 | removeLocked(it.first); | ||
84 | } | ||
85 | } else { | ||
86 | removeLocked(propId); | ||
87 | } | ||
88 | return StatusCode::OK; | ||
89 | } | ||
90 | |||
91 | void LinearFakeValueGenerator::removeLocked(int propId) { | ||
92 | if (mGenCfg.erase(propId)) { | ||
93 | mRecurrentTimer.unregisterRecurrentEvent(propId); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void LinearFakeValueGenerator::onTimer(const std::vector<int32_t>& properties) { | ||
98 | MuxGuard g(mLock); | ||
99 | |||
100 | for (int32_t propId : properties) { | ||
101 | auto& cfg = mGenCfg[propId]; | ||
102 | cfg.currentValue += cfg.increment; | ||
103 | if (cfg.currentValue > cfg.initialValue + cfg.dispersion) { | ||
104 | cfg.currentValue = cfg.initialValue - cfg.dispersion; | ||
105 | } | ||
106 | VehiclePropValue event = {.prop = propId}; | ||
107 | auto& value = event.value; | ||
108 | switch (getPropType(event.prop)) { | ||
109 | case VehiclePropertyType::INT32: | ||
110 | value.int32Values.resize(1); | ||
111 | value.int32Values[0] = static_cast<int32_t>(cfg.currentValue); | ||
112 | break; | ||
113 | case VehiclePropertyType::INT64: | ||
114 | value.int64Values.resize(1); | ||
115 | value.int64Values[0] = static_cast<int64_t>(cfg.currentValue); | ||
116 | break; | ||
117 | case VehiclePropertyType::FLOAT: | ||
118 | value.floatValues.resize(1); | ||
119 | value.floatValues[0] = cfg.currentValue; | ||
120 | break; | ||
121 | default: | ||
122 | ALOGE("%s: unsupported property type for 0x%x", __func__, event.prop); | ||
123 | continue; | ||
124 | } | ||
125 | mOnHalEvent(event); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | } // namespace impl | ||
130 | |||
131 | } // namespace V2_0 | ||
132 | } // namespace vehicle | ||
133 | } // namespace automotive | ||
134 | } // namespace hardware | ||
135 | } // namespace android | ||
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h new file mode 100644 index 00000000..fe6d0979 --- /dev/null +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/LinearFakeValueGenerator.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_ | ||
18 | #define android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_ | ||
19 | |||
20 | #include <vhal_v2_0/RecurrentTimer.h> | ||
21 | |||
22 | #include "FakeValueGenerator.h" | ||
23 | |||
24 | namespace android { | ||
25 | namespace hardware { | ||
26 | namespace automotive { | ||
27 | namespace vehicle { | ||
28 | namespace V2_0 { | ||
29 | |||
30 | namespace impl { | ||
31 | |||
32 | class LinearFakeValueGenerator : public FakeValueGenerator { | ||
33 | private: | ||
34 | // In every timer tick we may want to generate new value based on initial value for debug | ||
35 | // purpose. It's better to have sequential values to see if events gets delivered in order | ||
36 | // to the client. | ||
37 | |||
38 | struct GeneratorCfg { | ||
39 | float initialValue; // | ||
40 | float currentValue; // Should be in range (initialValue +/- dispersion). | ||
41 | float dispersion; // Defines minimum and maximum value based on initial value. | ||
42 | float increment; // Value that we will be added to currentValue with each timer tick. | ||
43 | }; | ||
44 | |||
45 | public: | ||
46 | LinearFakeValueGenerator(const OnHalEvent& onHalEvent); | ||
47 | ~LinearFakeValueGenerator() = default; | ||
48 | StatusCode start(const VehiclePropValue& request) override; | ||
49 | StatusCode stop(const VehiclePropValue& request) override; | ||
50 | |||
51 | private: | ||
52 | void removeLocked(int propId); | ||
53 | void onTimer(const std::vector<int32_t>& properties); | ||
54 | |||
55 | private: | ||
56 | mutable std::mutex mLock; | ||
57 | OnHalEvent mOnHalEvent; | ||
58 | RecurrentTimer mRecurrentTimer; | ||
59 | std::unordered_map<int32_t, GeneratorCfg> mGenCfg; | ||
60 | }; | ||
61 | |||
62 | } // namespace impl | ||
63 | |||
64 | } // namespace V2_0 | ||
65 | } // namespace vehicle | ||
66 | } // namespace automotive | ||
67 | } // namespace hardware | ||
68 | } // namespace android | ||
69 | |||
70 | #endif // android_hardware_automotive_vehicle_V2_0_impl_LinearFakeValueGenerator_H_ | ||
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp index 31c5fdd9..ae24d781 100644 --- a/camera/provider/2.4/default/Android.bp +++ b/camera/provider/2.4/default/Android.bp | |||
@@ -61,6 +61,30 @@ cc_binary { | |||
61 | ], | 61 | ], |
62 | } | 62 | } |
63 | 63 | ||
64 | |||
65 | cc_binary { | ||
66 | name: "android.hardware.camera.provider@2.4-service_64", | ||
67 | defaults: ["hidl_defaults"], | ||
68 | proprietary: true, | ||
69 | relative_install_path: "hw", | ||
70 | srcs: ["service.cpp"], | ||
71 | compile_multilib: "64", | ||
72 | init_rc: ["android.hardware.camera.provider@2.4-service_64.rc"], | ||
73 | shared_libs: [ | ||
74 | "libhidlbase", | ||
75 | "libhidltransport", | ||
76 | "libbinder", | ||
77 | "liblog", | ||
78 | "libutils", | ||
79 | "android.hardware.camera.device@1.0", | ||
80 | "android.hardware.camera.device@3.2", | ||
81 | "android.hardware.camera.device@3.3", | ||
82 | "android.hardware.camera.device@3.4", | ||
83 | "android.hardware.camera.provider@2.4", | ||
84 | "android.hardware.camera.common@1.0", | ||
85 | ], | ||
86 | } | ||
87 | |||
64 | cc_binary { | 88 | cc_binary { |
65 | name: "android.hardware.camera.provider@2.4-external-service", | 89 | name: "android.hardware.camera.provider@2.4-external-service", |
66 | defaults: ["hidl_defaults"], | 90 | defaults: ["hidl_defaults"], |
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc new file mode 100644 index 00000000..4c721ecb --- /dev/null +++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service_64.rc | |||
@@ -0,0 +1,7 @@ | |||
1 | service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service_64 | ||
2 | class hal | ||
3 | user cameraserver | ||
4 | group audio camera input drmrpc | ||
5 | ioprio rt 4 | ||
6 | capabilities SYS_NICE | ||
7 | writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks | ||
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp index 1f899337..6d5e2d5e 100644 --- a/cas/1.0/default/DescramblerImpl.cpp +++ b/cas/1.0/default/DescramblerImpl.cpp | |||
@@ -96,13 +96,13 @@ Return<void> DescramblerImpl::descramble( | |||
96 | descramble_cb _hidl_cb) { | 96 | descramble_cb _hidl_cb) { |
97 | ALOGV("%s", __FUNCTION__); | 97 | ALOGV("%s", __FUNCTION__); |
98 | 98 | ||
99 | // Get a local copy of the shared_ptr for the plugin. Note that before | 99 | // hidl_memory's size is stored in uint64_t, but mapMemory's mmap will map |
100 | // calling the HIDL callback, this shared_ptr must be manually reset, | 100 | // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed |
101 | // since the client side could proceed as soon as the callback is called | 101 | // but the mapped memory's actual size will be smaller than the reported size. |
102 | // without waiting for this method to go out of scope. | 102 | if (srcBuffer.heapBase.size() > SIZE_MAX) { |
103 | std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder); | 103 | ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size()); |
104 | if (holder.get() == nullptr) { | 104 | android_errorWriteLog(0x534e4554, "79376389"); |
105 | _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL); | 105 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); |
106 | return Void(); | 106 | return Void(); |
107 | } | 107 | } |
108 | 108 | ||
@@ -112,7 +112,6 @@ Return<void> DescramblerImpl::descramble( | |||
112 | // mapped ashmem, since the offset and size is controlled by client. | 112 | // mapped ashmem, since the offset and size is controlled by client. |
113 | if (srcMem == NULL) { | 113 | if (srcMem == NULL) { |
114 | ALOGE("Failed to map src buffer."); | 114 | ALOGE("Failed to map src buffer."); |
115 | holder.reset(); | ||
116 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); | 115 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); |
117 | return Void(); | 116 | return Void(); |
118 | } | 117 | } |
@@ -121,7 +120,6 @@ Return<void> DescramblerImpl::descramble( | |||
121 | ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu", | 120 | ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu", |
122 | srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize()); | 121 | srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize()); |
123 | android_errorWriteLog(0x534e4554, "67962232"); | 122 | android_errorWriteLog(0x534e4554, "67962232"); |
124 | holder.reset(); | ||
125 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); | 123 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); |
126 | return Void(); | 124 | return Void(); |
127 | } | 125 | } |
@@ -139,7 +137,6 @@ Return<void> DescramblerImpl::descramble( | |||
139 | "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", | 137 | "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", |
140 | srcOffset, totalBytesInSubSamples, srcBuffer.size); | 138 | srcOffset, totalBytesInSubSamples, srcBuffer.size); |
141 | android_errorWriteLog(0x534e4554, "67962232"); | 139 | android_errorWriteLog(0x534e4554, "67962232"); |
142 | holder.reset(); | ||
143 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); | 140 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); |
144 | return Void(); | 141 | return Void(); |
145 | } | 142 | } |
@@ -158,7 +155,6 @@ Return<void> DescramblerImpl::descramble( | |||
158 | "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", | 155 | "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu", |
159 | dstOffset, totalBytesInSubSamples, srcBuffer.size); | 156 | dstOffset, totalBytesInSubSamples, srcBuffer.size); |
160 | android_errorWriteLog(0x534e4554, "67962232"); | 157 | android_errorWriteLog(0x534e4554, "67962232"); |
161 | holder.reset(); | ||
162 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); | 158 | _hidl_cb(toStatus(BAD_VALUE), 0, NULL); |
163 | return Void(); | 159 | return Void(); |
164 | } | 160 | } |
@@ -167,6 +163,17 @@ Return<void> DescramblerImpl::descramble( | |||
167 | dstBuffer.secureMemory.getNativeHandle()); | 163 | dstBuffer.secureMemory.getNativeHandle()); |
168 | dstPtr = static_cast<void *>(handle); | 164 | dstPtr = static_cast<void *>(handle); |
169 | } | 165 | } |
166 | |||
167 | // Get a local copy of the shared_ptr for the plugin. Note that before | ||
168 | // calling the HIDL callback, this shared_ptr must be manually reset, | ||
169 | // since the client side could proceed as soon as the callback is called | ||
170 | // without waiting for this method to go out of scope. | ||
171 | std::shared_ptr<DescramblerPlugin> holder = std::atomic_load(&mPluginHolder); | ||
172 | if (holder.get() == nullptr) { | ||
173 | _hidl_cb(toStatus(INVALID_OPERATION), 0, NULL); | ||
174 | return Void(); | ||
175 | } | ||
176 | |||
170 | // Casting hidl SubSample to DescramblerPlugin::SubSample, but need | 177 | // Casting hidl SubSample to DescramblerPlugin::SubSample, but need |
171 | // to ensure structs are actually idential | 178 | // to ensure structs are actually idential |
172 | 179 | ||
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp index fac00174..066bca41 100644 --- a/keymaster/4.0/support/Keymaster.cpp +++ b/keymaster/4.0/support/Keymaster.cpp | |||
@@ -16,24 +16,73 @@ | |||
16 | 16 | ||
17 | #include <keymasterV4_0/Keymaster.h> | 17 | #include <keymasterV4_0/Keymaster.h> |
18 | 18 | ||
19 | #include <iomanip> | ||
20 | |||
19 | #include <android-base/logging.h> | 21 | #include <android-base/logging.h> |
20 | #include <android/hidl/manager/1.0/IServiceManager.h> | 22 | #include <android/hidl/manager/1.0/IServiceManager.h> |
21 | #include <keymasterV4_0/Keymaster3.h> | 23 | #include <keymasterV4_0/Keymaster3.h> |
22 | #include <keymasterV4_0/Keymaster4.h> | 24 | #include <keymasterV4_0/Keymaster4.h> |
25 | #include <keymasterV4_0/key_param_output.h> | ||
26 | #include <keymasterV4_0/keymaster_utils.h> | ||
23 | 27 | ||
24 | namespace android { | 28 | namespace android { |
25 | namespace hardware { | 29 | namespace hardware { |
30 | |||
31 | template <class T> | ||
32 | std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) { | ||
33 | os << "{ "; | ||
34 | if (vec.size()) { | ||
35 | for (size_t i = 0; i < vec.size() - 1; ++i) os << vec[i] << ", "; | ||
36 | os << vec[vec.size() - 1]; | ||
37 | } | ||
38 | os << " }"; | ||
39 | return os; | ||
40 | } | ||
41 | |||
42 | std::ostream& operator<<(std::ostream& os, const hidl_vec<uint8_t>& vec) { | ||
43 | std::ios_base::fmtflags flags(os.flags()); | ||
44 | os << std::setw(2) << std::setfill('0') << std::hex; | ||
45 | for (uint8_t c : vec) os << static_cast<int>(c); | ||
46 | os.flags(flags); | ||
47 | return os; | ||
48 | } | ||
49 | |||
50 | template <size_t N> | ||
51 | std::ostream& operator<<(std::ostream& os, const hidl_array<uint8_t, N>& vec) { | ||
52 | std::ios_base::fmtflags flags(os.flags()); | ||
53 | os << std::setw(2) << std::setfill('0') << std::hex; | ||
54 | for (size_t i = 0; i < N; ++i) os << static_cast<int>(vec[i]); | ||
55 | os.flags(flags); | ||
56 | return os; | ||
57 | } | ||
58 | |||
26 | namespace keymaster { | 59 | namespace keymaster { |
27 | namespace V4_0 { | 60 | namespace V4_0 { |
61 | |||
62 | std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) { | ||
63 | // Note that by design, although seed and nonce are used to compute a secret, they are | ||
64 | // not secrets and it's just fine to log them. | ||
65 | os << "(seed: " << params.seed << ", nonce: " << params.nonce << ')'; | ||
66 | return os; | ||
67 | } | ||
68 | |||
28 | namespace support { | 69 | namespace support { |
29 | 70 | ||
30 | using ::android::sp; | 71 | using ::android::sp; |
31 | using ::android::hidl::manager::V1_0::IServiceManager; | 72 | using ::android::hidl::manager::V1_0::IServiceManager; |
32 | 73 | ||
74 | std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster) { | ||
75 | auto& version = keymaster.halVersion(); | ||
76 | os << version.keymasterName << " from " << version.authorName | ||
77 | << " SecurityLevel: " << toString(version.securityLevel) | ||
78 | << " HAL: " << keymaster.descriptor() << "/" << keymaster.instanceName(); | ||
79 | return os; | ||
80 | } | ||
81 | |||
33 | template <typename Wrapper> | 82 | template <typename Wrapper> |
34 | std::vector<std::unique_ptr<Keymaster>> enumerateDevices( | 83 | std::vector<std::unique_ptr<Keymaster>> enumerateDevices( |
35 | const sp<IServiceManager>& serviceManager) { | 84 | const sp<IServiceManager>& serviceManager) { |
36 | std::vector<std::unique_ptr<Keymaster>> result; | 85 | Keymaster::KeymasterSet result; |
37 | 86 | ||
38 | bool foundDefault = false; | 87 | bool foundDefault = false; |
39 | auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor; | 88 | auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor; |
@@ -57,7 +106,7 @@ std::vector<std::unique_ptr<Keymaster>> enumerateDevices( | |||
57 | return result; | 106 | return result; |
58 | } | 107 | } |
59 | 108 | ||
60 | std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { | 109 | Keymaster::KeymasterSet Keymaster::enumerateAvailableDevices() { |
61 | auto serviceManager = IServiceManager::getService(); | 110 | auto serviceManager = IServiceManager::getService(); |
62 | CHECK(serviceManager) << "Could not retrieve ServiceManager"; | 111 | CHECK(serviceManager) << "Could not retrieve ServiceManager"; |
63 | 112 | ||
@@ -73,18 +122,62 @@ std::vector<std::unique_ptr<Keymaster>> Keymaster::enumerateAvailableDevices() { | |||
73 | 122 | ||
74 | size_t i = 1; | 123 | size_t i = 1; |
75 | LOG(INFO) << "List of Keymaster HALs found:"; | 124 | LOG(INFO) << "List of Keymaster HALs found:"; |
76 | for (auto& hal : result) { | 125 | for (auto& hal : result) LOG(INFO) << "Keymaster HAL #" << i++ << ": " << *hal; |
77 | auto& version = hal->halVersion(); | ||
78 | LOG(INFO) << "Keymaster HAL #" << i << ": " << version.keymasterName << " from " | ||
79 | << version.authorName << " SecurityLevel: " << toString(version.securityLevel) | ||
80 | << " HAL : " << hal->descriptor() << " instance " << hal->instanceName(); | ||
81 | } | ||
82 | 126 | ||
83 | return result; | 127 | return result; |
84 | } | 128 | } |
85 | 129 | ||
130 | static hidl_vec<HmacSharingParameters> getHmacParameters( | ||
131 | const Keymaster::KeymasterSet& keymasters) { | ||
132 | std::vector<HmacSharingParameters> params_vec; | ||
133 | params_vec.reserve(keymasters.size()); | ||
134 | for (auto& keymaster : keymasters) { | ||
135 | if (keymaster->halVersion().majorVersion < 4) continue; | ||
136 | auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) { | ||
137 | CHECK(error == ErrorCode::OK) | ||
138 | << "Failed to get HMAC parameters from " << *keymaster << " error " << error; | ||
139 | params_vec.push_back(params); | ||
140 | }); | ||
141 | CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster | ||
142 | << " error: " << rc.description(); | ||
143 | } | ||
144 | std::sort(params_vec.begin(), params_vec.end()); | ||
145 | |||
146 | return params_vec; | ||
147 | } | ||
148 | |||
149 | static void computeHmac(const Keymaster::KeymasterSet& keymasters, | ||
150 | const hidl_vec<HmacSharingParameters>& params) { | ||
151 | if (!params.size()) return; | ||
152 | |||
153 | hidl_vec<uint8_t> sharingCheck; | ||
154 | bool firstKeymaster = true; | ||
155 | LOG(DEBUG) << "Computing HMAC with params " << params; | ||
156 | for (auto& keymaster : keymasters) { | ||
157 | if (keymaster->halVersion().majorVersion < 4) continue; | ||
158 | LOG(DEBUG) << "Computing HMAC for " << *keymaster; | ||
159 | auto rc = keymaster->computeSharedHmac(params, [&](auto error, auto& curSharingCheck) { | ||
160 | CHECK(error == ErrorCode::OK) | ||
161 | << "Failed to get HMAC parameters from " << *keymaster << " error " << error; | ||
162 | if (firstKeymaster) { | ||
163 | sharingCheck = curSharingCheck; | ||
164 | firstKeymaster = false; | ||
165 | } | ||
166 | // TODO: Validate that curSharingCheck == sharingCheck. b/77588764 | ||
167 | // CHECK(curSharingCheck == sharingCheck) << "HMAC computation failed for " << | ||
168 | // *keymaster; | ||
169 | }); | ||
170 | CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster | ||
171 | << " error: " << rc.description(); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | void Keymaster::performHmacKeyAgreement(const KeymasterSet& keymasters) { | ||
176 | computeHmac(keymasters, getHmacParameters(keymasters)); | ||
177 | } | ||
178 | |||
86 | } // namespace support | 179 | } // namespace support |
87 | } // namespace V4_0 | 180 | } // namespace V4_0 |
88 | } // namespace keymaster | 181 | } // namespace keymaster |
89 | } // namespace hardware | 182 | } // namespace hardware |
90 | }; // namespace android | 183 | } // namespace android |
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h index f9efd516..83b1d699 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h +++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h | |||
@@ -37,6 +37,8 @@ namespace support { | |||
37 | */ | 37 | */ |
38 | class Keymaster : public IKeymasterDevice { | 38 | class Keymaster : public IKeymasterDevice { |
39 | public: | 39 | public: |
40 | using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>; | ||
41 | |||
40 | Keymaster(const hidl_string& descriptor, const hidl_string& instanceName) | 42 | Keymaster(const hidl_string& descriptor, const hidl_string& instanceName) |
41 | : descriptor_(descriptor), instanceName_(instanceName) {} | 43 | : descriptor_(descriptor), instanceName_(instanceName) {} |
42 | virtual ~Keymaster() {} | 44 | virtual ~Keymaster() {} |
@@ -55,21 +57,33 @@ class Keymaster : public IKeymasterDevice { | |||
55 | } | 57 | } |
56 | }; | 58 | }; |
57 | 59 | ||
58 | virtual const VersionResult& halVersion() = 0; | 60 | virtual const VersionResult& halVersion() const = 0; |
59 | const hidl_string& descriptor() { return descriptor_; } | 61 | const hidl_string& descriptor() const { return descriptor_; } |
60 | const hidl_string& instanceName() { return instanceName_; } | 62 | const hidl_string& instanceName() const { return instanceName_; } |
61 | 63 | ||
62 | /** | 64 | /** |
63 | * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least | 65 | * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least |
64 | * secure (as defined by VersionResult::operator<). | 66 | * secure (as defined by VersionResult::operator<). |
65 | */ | 67 | */ |
66 | static std::vector<std::unique_ptr<Keymaster>> enumerateAvailableDevices(); | 68 | static KeymasterSet enumerateAvailableDevices(); |
69 | |||
70 | /** | ||
71 | * Ask provided Keymaster instances to compute a shared HMAC key using | ||
72 | * getHmacSharingParameters() and computeSharedHmac(). This computation is idempotent as long | ||
73 | * as the same set of Keymaster instances is used each time (and if all of the instances work | ||
74 | * correctly). It must be performed once per boot, but should do no harm to be repeated. | ||
75 | * | ||
76 | * If key agreement fails, this method will crash the process (with CHECK). | ||
77 | */ | ||
78 | static void performHmacKeyAgreement(const KeymasterSet& keymasters); | ||
67 | 79 | ||
68 | private: | 80 | private: |
69 | hidl_string descriptor_; | 81 | hidl_string descriptor_; |
70 | hidl_string instanceName_; | 82 | hidl_string instanceName_; |
71 | }; | 83 | }; |
72 | 84 | ||
85 | std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster); | ||
86 | |||
73 | } // namespace support | 87 | } // namespace support |
74 | } // namespace V4_0 | 88 | } // namespace V4_0 |
75 | } // namespace keymaster | 89 | } // namespace keymaster |
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h index 2bb77ca7..c40be7c7 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h +++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h | |||
@@ -45,8 +45,8 @@ class Keymaster3 : public Keymaster { | |||
45 | km3_dev_(km3_dev), | 45 | km3_dev_(km3_dev), |
46 | haveVersion_(false) {} | 46 | haveVersion_(false) {} |
47 | 47 | ||
48 | const VersionResult& halVersion() override { | 48 | const VersionResult& halVersion() const override { |
49 | getVersionIfNeeded(); | 49 | const_cast<Keymaster3*>(this)->getVersionIfNeeded(); |
50 | return version_; | 50 | return version_; |
51 | } | 51 | } |
52 | 52 | ||
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h index 96afb13a..dfd03ef6 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h +++ b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h | |||
@@ -37,8 +37,8 @@ class Keymaster4 : public Keymaster { | |||
37 | haveVersion_(false), | 37 | haveVersion_(false), |
38 | dev_(km4_dev) {} | 38 | dev_(km4_dev) {} |
39 | 39 | ||
40 | const VersionResult& halVersion() override { | 40 | const VersionResult& halVersion() const override { |
41 | getVersionIfNeeded(); | 41 | const_cast<Keymaster4*>(this)->getVersionIfNeeded(); |
42 | return version_; | 42 | return version_; |
43 | } | 43 | } |
44 | 44 | ||
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h index 1c1b000b..90a0f1b2 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h | |||
@@ -23,6 +23,14 @@ namespace android { | |||
23 | namespace hardware { | 23 | namespace hardware { |
24 | namespace keymaster { | 24 | namespace keymaster { |
25 | namespace V4_0 { | 25 | namespace V4_0 { |
26 | |||
27 | /** | ||
28 | * Define a lexicographical ordering on HmacSharingParameters. The parameters to | ||
29 | * IKeymasterDevice::computeSharedHmac are required to be delivered in the order specified by this | ||
30 | * comparison operator. | ||
31 | */ | ||
32 | bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b); | ||
33 | |||
26 | namespace support { | 34 | namespace support { |
27 | 35 | ||
28 | inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length, | 36 | inline static hidl_vec<uint8_t> blob2hidlVec(const uint8_t* data, const size_t length, |
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp index bc610aa3..729e1c1d 100644 --- a/keymaster/4.0/support/keymaster_utils.cpp +++ b/keymaster/4.0/support/keymaster_utils.cpp | |||
@@ -19,8 +19,24 @@ | |||
19 | 19 | ||
20 | namespace android { | 20 | namespace android { |
21 | namespace hardware { | 21 | namespace hardware { |
22 | |||
23 | inline static bool operator<(const hidl_vec<uint8_t>& a, const hidl_vec<uint8_t>& b) { | ||
24 | return memcmp(a.data(), b.data(), std::min(a.size(), b.size())) == -1; | ||
25 | } | ||
26 | |||
27 | template <size_t SIZE> | ||
28 | inline static bool operator<(const hidl_array<uint8_t, SIZE>& a, | ||
29 | const hidl_array<uint8_t, SIZE>& b) { | ||
30 | return memcmp(a.data(), b.data(), SIZE) == -1; | ||
31 | } | ||
32 | |||
22 | namespace keymaster { | 33 | namespace keymaster { |
23 | namespace V4_0 { | 34 | namespace V4_0 { |
35 | |||
36 | bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b) { | ||
37 | return std::tie(a.seed, a.nonce) < std::tie(b.seed, b.nonce); | ||
38 | } | ||
39 | |||
24 | namespace support { | 40 | namespace support { |
25 | 41 | ||
26 | template <typename T, typename InIter> | 42 | template <typename T, typename InIter> |