Add the unit of slot duration to its name. am: 5363e6a547
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2443724
Change-Id: Idbb46f28bf8f87d77f95c0d5162590785ecb6ce4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/audio/README.md b/audio/README.md
index 3f40d72..1938ad4 100644
--- a/audio/README.md
+++ b/audio/README.md
@@ -2,29 +2,10 @@
Directory structure of the audio HAL related code.
-## Directory Structure for AIDL audio HAL
+Run `common/all-versions/copyHAL.sh` to create a new version of the audio HAL
+based on an existing one.
-The AIDL version is located inside `aidl` directory. The tree below explains
-the role of each subdirectory:
-
-* `aidl_api` — snapshots of the API created each Android release. Every
- release, the current version of the API becomes "frozen" and gets assigned
- the next version number. If the API needs further modifications, they are
- made on the "current" version. After making modifications, run
- `m <package name>-update-api` to update the snapshot of the "current"
- version.
-* `android/hardware/audio/common` — data structures and interfaces shared
- between various HALs: BT HAL, core and effects audio HALs.
-* `android/hardware/audio/core` — data structures and interfaces of the
- core audio HAL.
-* `default` — the default, reference implementation of the audio HAL service.
-* `vts` — VTS tests for the AIDL HAL.
-
-## Directory Structure for HIDL audio HAL
-
-Run `common/all-versions/copyHAL.sh` to create a new version of the HIDL audio
-HAL based on an existing one. Note that this isn't possible since Android T
-release. Android U and above uses AIDL audio HAL.
+## Directory Structure
* `2.0` — version 2.0 of the core HIDL API. Note that `.hal` files
can not be moved into the `core` directory because that would change
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
index a193102..c12ebb8 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -39,6 +39,8 @@
int roomHfLevelMb;
int decayTimeMs;
int decayHfRatioPm;
+ int reflectionsLevelMb;
+ int reflectionsDelayMs;
int levelMb;
int delayMs;
int diffusionPm;
diff --git a/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
index a158dca..95d1ff6 100644
--- a/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
+++ b/audio/aidl/android/hardware/audio/effect/EnvironmentalReverb.aidl
@@ -59,6 +59,14 @@
*/
int decayHfRatioPm;
/**
+ * Reverb reflections level in millibels.
+ */
+ int reflectionsLevelMb;
+ /**
+ * Reverb reflections delay in milliseconds.
+ */
+ int reflectionsDelayMs;
+ /**
* Reverb level in millibels.
*/
int levelMb;
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.cpp b/audio/aidl/default/envReverb/EnvReverbSw.cpp
index 46d9016..15373fe 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.cpp
+++ b/audio/aidl/default/envReverb/EnvReverbSw.cpp
@@ -66,6 +66,8 @@
MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, 7000),
MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+ MAKE_RANGE(EnvironmentalReverb, reflectionsLevelMb, -6000, 0),
+ MAKE_RANGE(EnvironmentalReverb, reflectionsDelayMs, 0, 65),
MAKE_RANGE(EnvironmentalReverb, levelMb, -6000, 0),
MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
@@ -125,6 +127,20 @@
EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
return ndk::ScopedAStatus::ok();
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ RETURN_IF(mContext->setErReflectionsLevel(
+ erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ RETURN_IF(mContext->setErReflectionsDelay(
+ erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+ return ndk::ScopedAStatus::ok();
+ }
case EnvironmentalReverb::levelMb: {
RETURN_IF(mContext->setErLevel(erParam.get<EnvironmentalReverb::levelMb>()) !=
RetCode::SUCCESS,
@@ -201,6 +217,14 @@
erParam.set<EnvironmentalReverb::decayHfRatioPm>(mContext->getErDecayHfRatio());
break;
}
+ case EnvironmentalReverb::reflectionsLevelMb: {
+ erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getErReflectionsLevel());
+ break;
+ }
+ case EnvironmentalReverb::reflectionsDelayMs: {
+ erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getErReflectionsDelay());
+ break;
+ }
case EnvironmentalReverb::levelMb: {
erParam.set<EnvironmentalReverb::levelMb>(mContext->getErLevel());
break;
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.h b/audio/aidl/default/envReverb/EnvReverbSw.h
index 4f11a5c..dd2cf5d 100644
--- a/audio/aidl/default/envReverb/EnvReverbSw.h
+++ b/audio/aidl/default/envReverb/EnvReverbSw.h
@@ -58,12 +58,23 @@
int getErDensity() const { return mDensity; }
RetCode setErBypass(bool bypass) {
- // TODO : Add implementation to apply new bypass
mBypass = bypass;
return RetCode::SUCCESS;
}
bool getErBypass() const { return mBypass; }
+ RetCode setErReflectionsDelay(int delay) {
+ mReflectionsDelayMs = delay;
+ return RetCode::SUCCESS;
+ }
+ bool getErReflectionsDelay() const { return mReflectionsDelayMs; }
+
+ RetCode setErReflectionsLevel(int level) {
+ mReflectionsLevelMb = level;
+ return RetCode::SUCCESS;
+ }
+ bool getErReflectionsLevel() const { return mReflectionsLevelMb; }
+
private:
int mRoomLevel = -6000; // Default room level
int mRoomHfLevel = 0; // Default room hf level
@@ -71,6 +82,8 @@
int mDecayHfRatio = 500; // Default decay hf ratio
int mLevel = -6000; // Default level
int mDelay = 40; // Default delay
+ int mReflectionsLevelMb = 0;
+ int mReflectionsDelayMs = 0;
int mDiffusion = 1000; // Default diffusion
int mDensity = 1000; // Default density
bool mBypass = false; // Default bypass
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
index 267f6af..bc61c0f 100644
--- a/audio/aidl/default/include/effect-impl/EffectUUID.h
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -273,12 +273,12 @@
0x4d34,
0xacaf,
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-// fa819f3e-588b-11ed-9b6a-0242ac120002
-static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
- 0x588b,
- 0x11ed,
- 0x9b6a,
- {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// e46b26a0-dddd-11db-8afd-0002a5d5c51b
+static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xe46b26a0),
+ 0xdddd,
+ 0x11db,
+ 0x8afd,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
// fa81a0f6-588b-11ed-9b6a-0242ac120002
static const AudioUuid kVisualizerSwImplUUID = {static_cast<int32_t>(0xfa81a0f6),
0x588b,
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index 9a93e1a..622846a 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -190,6 +190,40 @@
},
.initialValue = {.int32Values = {toInt(VehicleUnit::KILOWATT_HOUR)}}},
+ {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SELECT),
+ .access = VehiclePropertyAccess::WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3}}},
+ .initialValue = {.int32Values = {1}}},
+
+ {.config = {.prop = toInt(VehicleProperty::SEAT_MEMORY_SET),
+ .access = VehiclePropertyAccess::WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{.areaId = SEAT_1_LEFT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_1_RIGHT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_2_LEFT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3},
+ VehicleAreaConfig{.areaId = SEAT_2_RIGHT,
+ .minInt32Value = 0,
+ .maxInt32Value = 3}}},
+ .initialValue = {.int32Values = {1}}},
+
{.config = {.prop = toInt(VehicleProperty::SEAT_BELT_BUCKLED),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
index 5f0f716..cd2b727 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/RecurrentTimer.h
@@ -83,8 +83,9 @@
// each time we might introduce outdated elements to the top. We must make sure the heap is
// always valid from the top.
void removeInvalidCallbackLocked() REQUIRES(mLock);
- // Pops the next closest callback (must be valid) from the heap.
- std::unique_ptr<CallbackInfo> popNextCallbackLocked() REQUIRES(mLock);
+ // Gets the next calblack to run (must be valid) from the heap, update its nextTime and put
+ // it back to the heap.
+ std::shared_ptr<Callback> getNextCallbackLocked(int64_t now) REQUIRES(mLock);
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
index 2eca6b7..908564c 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/RecurrentTimer.cpp
@@ -101,68 +101,71 @@
}
}
-std::unique_ptr<RecurrentTimer::CallbackInfo> RecurrentTimer::popNextCallbackLocked() {
+std::shared_ptr<RecurrentTimer::Callback> RecurrentTimer::getNextCallbackLocked(int64_t now) {
std::pop_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
- std::unique_ptr<CallbackInfo> info = std::move(mCallbackQueue[mCallbackQueue.size() - 1]);
- mCallbackQueue.pop_back();
+ auto& callbackInfo = mCallbackQueue[mCallbackQueue.size() - 1];
+ auto nextCallback = callbackInfo->callback;
+ // intervalCount is the number of interval we have to advance until we pass now.
+ size_t intervalCount = (now - callbackInfo->nextTime) / callbackInfo->interval + 1;
+ callbackInfo->nextTime += intervalCount * callbackInfo->interval;
+ std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
+
// Make sure the first element is always valid.
removeInvalidCallbackLocked();
- return info;
+
+ return nextCallback;
}
void RecurrentTimer::loop() {
- std::unique_lock<std::mutex> uniqueLock(mLock);
-
+ std::vector<std::shared_ptr<Callback>> callbacksToRun;
while (true) {
- // Wait until the timer exits or we have at least one recurrent callback.
- mCond.wait(uniqueLock, [this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mStopRequested || mCallbackQueue.size() != 0;
- });
-
- int64_t interval;
{
+ std::unique_lock<std::mutex> uniqueLock(mLock);
ScopedLockAssertion lockAssertion(mLock);
+ // Wait until the timer exits or we have at least one recurrent callback.
+ mCond.wait(uniqueLock, [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mStopRequested || mCallbackQueue.size() != 0;
+ });
+
+ int64_t interval;
if (mStopRequested) {
return;
}
// The first element is the nearest next event.
int64_t nextTime = mCallbackQueue[0]->nextTime;
int64_t now = uptimeNanos();
+
if (nextTime > now) {
interval = nextTime - now;
} else {
interval = 0;
}
- }
- // Wait for the next event or the timer exits.
- if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mStopRequested;
- })) {
- return;
- }
+ // Wait for the next event or the timer exits.
+ if (mCond.wait_for(uniqueLock, std::chrono::nanoseconds(interval), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mStopRequested;
+ })) {
+ return;
+ }
- {
- ScopedLockAssertion lockAssertion(mLock);
- int64_t now = uptimeNanos();
+ now = uptimeNanos();
+ callbacksToRun.clear();
while (mCallbackQueue.size() > 0) {
int64_t nextTime = mCallbackQueue[0]->nextTime;
if (nextTime > now) {
break;
}
- std::unique_ptr<CallbackInfo> info = popNextCallbackLocked();
- info->nextTime += info->interval;
-
- auto callback = info->callback;
- mCallbackQueue.push_back(std::move(info));
- std::push_heap(mCallbackQueue.begin(), mCallbackQueue.end(), CallbackInfo::cmp);
-
- (*callback)();
+ callbacksToRun.push_back(getNextCallbackLocked(now));
}
}
+
+ // Do not execute the callback while holding the lock.
+ for (size_t i = 0; i < callbacksToRun.size(); i++) {
+ (*callbacksToRun[i])();
+ }
}
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
index a033a24..141efc1 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/RecurrentTimerTest.cpp
@@ -186,6 +186,33 @@
ASSERT_EQ(countTimerCallbackQueue(&timer), static_cast<size_t>(0));
}
+TEST_F(RecurrentTimerTest, testRegisterCallbackMultipleTimesNoDeadLock) {
+ // We want to avoid the following situation:
+ // Caller holds a lock while calling registerTimerCallback, registerTimerCallback will try
+ // to obtain an internal lock inside timer.
+ // Meanwhile an recurrent action happens with timer holding an internal lock. The action
+ // tries to obtain the lock currently hold by the caller.
+ // The solution is that while calling recurrent actions, timer must not hold the internal lock.
+
+ std::unique_ptr<RecurrentTimer> timer = std::make_unique<RecurrentTimer>();
+ std::mutex lock;
+ for (size_t i = 0; i < 1000; i++) {
+ std::scoped_lock<std::mutex> lockGuard(lock);
+ auto action = std::make_shared<RecurrentTimer::Callback>([&lock] {
+ // While calling this function, the timer must not hold lock in order not to dead
+ // lock.
+ std::scoped_lock<std::mutex> lockGuard(lock);
+ });
+ // 10ms
+ int64_t interval = 10'000'000;
+ timer->registerTimerCallback(interval, action);
+ // Sleep for a little while to let the recurrent actions begin.
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+ // Make sure we stop the timer before we destroy lock.
+ timer.reset();
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 12a26d2..573b8f1 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -2334,6 +2334,7 @@
request.fmqSettingsSize = 0;
request.settings.metadata =
std::vector(rawMetadata, rawMetadata + get_camera_metadata_size(releasedMetadata));
+ overrideRotateAndCrop(&request.settings);
request.outputBuffers = std::vector<StreamBuffer>(1);
StreamBuffer& outputBuffer = request.outputBuffers[0];
if (useHalBufManager) {
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index cf2c90d..2d6490c 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -68,7 +68,7 @@
IGnssCallback::GnssSystemInfo systemInfo = {
.yearOfHw = 2022,
- .name = "Google Mock GNSS Implementation AIDL v2",
+ .name = "Google, Cuttlefish, AIDL v2",
};
status = sGnssCallback->gnssSetSystemInfoCb(systemInfo);
if (!status.isOk()) {
diff --git a/graphics/mapper/3.0/utils/vts/MapperVts.cpp b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
index c470a4a..48e5736 100644
--- a/graphics/mapper/3.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/3.0/utils/vts/MapperVts.cpp
@@ -99,11 +99,7 @@
descriptor, count,
[&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
if (tmpError != Error::NONE) {
- if (base::GetIntProperty("ro.vendor.build.version.sdk", 0, 0, INT_MAX) < 33) {
- GTEST_SKIP() << "Old vendor grallocs may not support P010";
- } else {
- GTEST_FAIL() << "failed to allocate buffers";
- }
+ GTEST_FAIL() << "failed to allocate buffers";
}
ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
diff --git a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
index 3b1bfab..997af97 100644
--- a/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
+++ b/graphics/mapper/3.0/vts/functional/VtsHalGraphicsMapperV3_0TargetTest.cpp
@@ -21,6 +21,7 @@
#include <vector>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -330,6 +331,9 @@
* Test IMapper::lockYCbCr. This locks a YCbCr_P010 buffer and verifies that it's initialized.
*/
TEST_P(GraphicsMapperHidlTest, LockYCbCrP010) {
+ if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) < __ANDROID_API_T__) {
+ GTEST_SKIP() << "Old vendor grallocs may not support P010";
+ }
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YCBCR_P010;
diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
index c6c9834..d70c6ef 100644
--- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
@@ -111,11 +111,7 @@
}
if (error != Error::NONE) {
- if (base::GetIntProperty("ro.vendor.build.version.sdk", 0, 0, INT_MAX) < 33) {
- GTEST_SKIP() << "Old vendor grallocs may not support P010";
- } else {
- GTEST_FAIL() << "failed to allocate buffers";
- }
+ GTEST_FAIL() << "failed to allocate buffers";
}
ASSERT_EQ(count, buffers.size()) << "invalid buffer array";
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 5a450e3..2ec98d4 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -29,12 +29,14 @@
#include <aidlcommonsupport/NativeHandle.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <android/sync.h>
#include <gralloctypes/Gralloc4.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
+
#include <mapper-vts/4.0/MapperVts.h>
#include <system/graphics.h>
@@ -1000,6 +1002,9 @@
}
TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_P010) {
+ if (base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_FUTURE__) < __ANDROID_API_T__) {
+ GTEST_SKIP() << "Old vendor grallocs may not support P010";
+ }
auto info = mDummyDescriptorInfo;
info.format = PixelFormat::YCBCR_P010;
diff --git a/health/aidl/OWNERS b/health/aidl/OWNERS
index 9bbcef8..0f1bee2 100644
--- a/health/aidl/OWNERS
+++ b/health/aidl/OWNERS
@@ -2,3 +2,4 @@
elsk@google.com
smoreland@google.com
wjack@google.com
+apelosi@google.com
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index e46aeee..cdcaaf3 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -1014,6 +1014,14 @@
.Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
.Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
.Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
+
+ // TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ if (isSecondImeiIdAttestationRequired()) {
+ attestation_id_tags.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI,
+ "invalid-second-imei");
+ }
+ }
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -1042,6 +1050,178 @@
CheckedDeleteKey(&attest_key.keyBlob);
}
+TEST_P(AttestKeyTest, SecondIMEIAttestationIDSuccess) {
+ if (is_gsi_image()) {
+ // GSI sets up a standard set of device identifiers that may not match
+ // the device identifiers held by the device.
+ GTEST_SKIP() << "Test not applicable under GSI";
+ }
+
+ // TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable for SecurityLevel::STRONGBOX";
+ }
+
+ // Skip the test if there is no second IMEI exists.
+ string second_imei = get_imei(1);
+ if (second_imei.empty() || second_imei.compare("null") == 0) {
+ GTEST_SKIP() << "Test not applicable as there is no second IMEI";
+ }
+
+ if (!isSecondImeiIdAttestationRequired()) {
+ GTEST_SKIP() << "Test not applicable for KeyMint-Version < 3 or first-api-level < 34";
+ }
+
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateAttestKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Use attestation key to sign an ECDSA key, but include an attestation ID field.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ // b/264979486 - second imei doesn't depend on first imei.
+ // Add second IMEI as attestation id without adding first IMEI as
+ // attestation id.
+ builder.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(), second_imei.size());
+
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+
+ if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
+ GTEST_SKIP()
+ << "Test not applicable as device does not support SECOND-IMEI ID attestation.";
+ }
+
+ ASSERT_EQ(result, ErrorCode::OK);
+
+ device_id_attestation_vsr_check(result);
+
+ CheckedDeleteKey(&attested_key_blob);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
+ // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+ // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+ // attestation extension should contain them, so make sure the extra tag is added.
+ vector<uint8_t> imei_blob(second_imei.data(), second_imei.data() + second_imei.size());
+ KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, imei_blob);
+ hw_enforced.push_back(imei_tag);
+
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ hw_enforced, SecLevel(),
+ attested_key_cert_chain[0].encodedCertificate));
+
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
+TEST_P(AttestKeyTest, MultipleIMEIAttestationIDSuccess) {
+ if (is_gsi_image()) {
+ // GSI sets up a standard set of device identifiers that may not match
+ // the device identifiers held by the device.
+ GTEST_SKIP() << "Test not applicable under GSI";
+ }
+
+ // TODO(b/262255219): Remove this condition when StrongBox supports 2nd IMEI attestation.
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable for SecurityLevel::STRONGBOX";
+ }
+
+ // Skip the test if there is no first IMEI exists.
+ string imei = get_imei(0);
+ if (imei.empty() || imei.compare("null") == 0) {
+ GTEST_SKIP() << "Test not applicable as there is no first IMEI";
+ }
+
+ // Skip the test if there is no second IMEI exists.
+ string second_imei = get_imei(1);
+ if (second_imei.empty() || second_imei.compare("null") == 0) {
+ GTEST_SKIP() << "Test not applicable as there is no second IMEI";
+ }
+
+ if (!isSecondImeiIdAttestationRequired()) {
+ GTEST_SKIP() << "Test not applicable for KeyMint-Version < 3 or first-api-level < 34";
+ }
+
+ // Create attestation key.
+ AttestationKey attest_key;
+ vector<KeyCharacteristics> attest_key_characteristics;
+ vector<Certificate> attest_key_cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateAttestKey(AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .SetDefaultValidity(),
+ {} /* attestation signing key */, &attest_key.keyBlob,
+ &attest_key_characteristics, &attest_key_cert_chain));
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ EXPECT_EQ(attest_key_cert_chain.size(), 1);
+ EXPECT_TRUE(IsSelfSigned(attest_key_cert_chain));
+
+ // Use attestation key to sign an ECDSA key, but include both IMEI attestation ID fields.
+ AuthorizationSetBuilder builder = AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("foo")
+ .SetDefaultValidity();
+ builder.Authorization(TAG_ATTESTATION_ID_IMEI, imei.data(), imei.size());
+ builder.Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, second_imei.data(), second_imei.size());
+
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ auto result = GenerateKey(builder, attest_key, &attested_key_blob,
+ &attested_key_characteristics, &attested_key_cert_chain);
+
+ if (result == ErrorCode::CANNOT_ATTEST_IDS && !isDeviceIdAttestationRequired()) {
+ GTEST_SKIP() << "Test not applicable as device does not support IMEI ID attestation.";
+ }
+
+ ASSERT_EQ(result, ErrorCode::OK);
+
+ device_id_attestation_vsr_check(result);
+
+ CheckedDeleteKey(&attested_key_blob);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
+
+ // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+ // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+ // attestation extension should contain them, so make sure the extra tag is added.
+ vector<uint8_t> imei_blob(imei.data(), imei.data() + imei.size());
+ KeyParameter imei_tag = Authorization(TAG_ATTESTATION_ID_IMEI, imei_blob);
+ hw_enforced.push_back(imei_tag);
+ vector<uint8_t> sec_imei_blob(second_imei.data(), second_imei.data() + second_imei.size());
+ KeyParameter sec_imei_tag = Authorization(TAG_ATTESTATION_ID_SECOND_IMEI, sec_imei_blob);
+ hw_enforced.push_back(sec_imei_tag);
+
+ EXPECT_TRUE(verify_attestation_record(AidlVersion(), "challenge", "foo", sw_enforced,
+ hw_enforced, SecLevel(),
+ attested_key_cert_chain[0].encodedCertificate));
+
+ CheckedDeleteKey(&attest_key.keyBlob);
+}
+
INSTANTIATE_KEYMINT_AIDL_TEST(AttestKeyTest);
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 588a1d4..41d47ee 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -217,6 +217,14 @@
return AidlVersion() >= 2 || property_get_int32("ro.vendor.api_level", 0) >= 33;
}
+/**
+ * An API to determine second IMEI ID attestation is required or not,
+ * which is supported for KeyMint version 3 or first_api_level greater than 33.
+ */
+bool KeyMintAidlTestBase::isSecondImeiIdAttestationRequired() {
+ return AidlVersion() >= 3 && property_get_int32("ro.vendor.api_level", 0) > 33;
+}
+
bool KeyMintAidlTestBase::Curve25519Supported() {
// Strongbox never supports curve 25519.
if (SecLevel() == SecurityLevel::STRONGBOX) {
@@ -1743,38 +1751,33 @@
EXPECT_EQ(security_level, att_keymint_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
- // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
- // keymint implementation will report YYYYMM dates instead of YYYYMMDD
- // for the BOOT_PATCH_LEVEL.
- if (avb_verification_enabled()) {
- for (int i = 0; i < att_hw_enforced.size(); i++) {
- if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
- att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
- std::string date =
- std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
+ for (int i = 0; i < att_hw_enforced.size(); i++) {
+ if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
+ att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
+ std::string date =
+ std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
- // strptime seems to require delimiters, but the tag value will
- // be YYYYMMDD
- if (date.size() != 8) {
- ADD_FAILURE() << "Tag " << att_hw_enforced[i].tag
- << " with invalid format (not YYYYMMDD): " << date;
- return false;
- }
- date.insert(6, "-");
- date.insert(4, "-");
- struct tm time;
- strptime(date.c_str(), "%Y-%m-%d", &time);
-
- // Day of the month (0-31)
- EXPECT_GE(time.tm_mday, 0);
- EXPECT_LT(time.tm_mday, 32);
- // Months since Jan (0-11)
- EXPECT_GE(time.tm_mon, 0);
- EXPECT_LT(time.tm_mon, 12);
- // Years since 1900
- EXPECT_GT(time.tm_year, 110);
- EXPECT_LT(time.tm_year, 200);
+ // strptime seems to require delimiters, but the tag value will
+ // be YYYYMMDD
+ if (date.size() != 8) {
+ ADD_FAILURE() << "Tag " << att_hw_enforced[i].tag
+ << " with invalid format (not YYYYMMDD): " << date;
+ return false;
}
+ date.insert(6, "-");
+ date.insert(4, "-");
+ struct tm time;
+ strptime(date.c_str(), "%Y-%m-%d", &time);
+
+ // Day of the month (0-31)
+ EXPECT_GE(time.tm_mday, 0);
+ EXPECT_LT(time.tm_mday, 32);
+ // Months since Jan (0-11)
+ EXPECT_GE(time.tm_mon, 0);
+ EXPECT_LT(time.tm_mon, 12);
+ // Years since 1900
+ EXPECT_GT(time.tm_year, 110);
+ EXPECT_LT(time.tm_year, 200);
}
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index fae9459..7c11b95 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -85,6 +85,7 @@
uint32_t boot_patch_level(const vector<KeyCharacteristics>& key_characteristics);
uint32_t boot_patch_level();
bool isDeviceIdAttestationRequired();
+ bool isSecondImeiIdAttestationRequired();
bool Curve25519Supported();
diff --git a/security/keymint/support/attestation_record.cpp b/security/keymint/support/attestation_record.cpp
index 2462228..5a26611 100644
--- a/security/keymint/support/attestation_record.cpp
+++ b/security/keymint/support/attestation_record.cpp
@@ -105,6 +105,7 @@
ASN1_INTEGER* boot_patchlevel;
ASN1_NULL* device_unique_attestation;
ASN1_NULL* identity_credential;
+ ASN1_OCTET_STRING* attestation_id_second_imei;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
@@ -170,6 +171,8 @@
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, identity_credential, ASN1_NULL,
TAG_IDENTITY_CREDENTIAL_KEY.maskedTag()),
+ ASN1_EXP_OPT(KM_AUTH_LIST, attestation_id_second_imei, ASN1_OCTET_STRING,
+ TAG_ATTESTATION_ID_SECOND_IMEI.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
@@ -323,6 +326,7 @@
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
copyAuthTag(record->identity_credential, TAG_IDENTITY_CREDENTIAL_KEY, auth_list);
+ copyAuthTag(record->attestation_id_second_imei, TAG_ATTESTATION_ID_SECOND_IMEI, auth_list);
return ErrorCode::OK;
}
diff --git a/security/keymint/support/include/keymint_support/keymint_tags.h b/security/keymint/support/include/keymint_support/keymint_tags.h
index 5b2a6f3..823899a 100644
--- a/security/keymint/support/include/keymint_support/keymint_tags.h
+++ b/security/keymint/support/include/keymint_support/keymint_tags.h
@@ -77,6 +77,7 @@
DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
+DECLARE_TYPED_TAG(ATTESTATION_ID_SECOND_IMEI);
DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);