Merge "Revert "Add an explicit TWT register events call"" into main
diff --git a/audio/6.0/config/api/current.txt b/audio/6.0/config/api/current.txt
index 01db90e..1814b59 100644
--- a/audio/6.0/config/api/current.txt
+++ b/audio/6.0/config/api/current.txt
@@ -116,6 +116,7 @@
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_APTX_HD;
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_APTX_TWSP;
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_CELT;
+ enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_DEFAULT;
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_DOLBY_TRUEHD;
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_DSD;
enum_constant public static final audio.policy.configuration.V6_0.AudioFormat AUDIO_FORMAT_DTS;
diff --git a/audio/6.0/config/audio_policy_configuration.xsd b/audio/6.0/config/audio_policy_configuration.xsd
index c2b8c5d..177af16 100644
--- a/audio/6.0/config/audio_policy_configuration.xsd
+++ b/audio/6.0/config/audio_policy_configuration.xsd
@@ -302,6 +302,7 @@
TODO: generate from hidl to avoid manual sync. -->
<xs:simpleType name="audioFormat">
<xs:restriction base="xs:string">
+ <xs:enumeration value="AUDIO_FORMAT_DEFAULT" />
<xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
<xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
<xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 94aa4dc..6bbdb1a 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -1169,9 +1169,12 @@
if (in_requested.ext.getTag() != AudioPortExt::Tag::unspecified) {
if (in_requested.ext.getTag() == out_suggested->ext.getTag()) {
if (out_suggested->ext.getTag() == AudioPortExt::Tag::mix) {
- // 'AudioMixPortExt.handle' is set by the client, copy from in_requested
- out_suggested->ext.get<AudioPortExt::Tag::mix>().handle =
- in_requested.ext.get<AudioPortExt::Tag::mix>().handle;
+ // 'AudioMixPortExt.handle' and '.usecase' are set by the client,
+ // copy from in_requested.
+ const auto& src = in_requested.ext.get<AudioPortExt::Tag::mix>();
+ auto& dst = out_suggested->ext.get<AudioPortExt::Tag::mix>();
+ dst.handle = src.handle;
+ dst.usecase = src.usecase;
}
} else {
LOG(WARNING) << __func__ << ": requested ext tag "
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 807348f..697ff0d 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -21,6 +21,7 @@
#include <Utils.h>
#include <android-base/logging.h>
#include <android/binder_ibinder_platform.h>
+#include <cutils/properties.h>
#include <utils/SystemClock.h>
#include <utils/Trace.h>
@@ -652,16 +653,34 @@
isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::input>(),
AudioInputFlags::FAST)) ||
(flags.getTag() == AudioIoFlags::Tag::output &&
- isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
- AudioOutputFlags::FAST))) {
+ (isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::FAST) ||
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::SPATIALIZER)))) {
// FAST workers should be run with a SCHED_FIFO scheduler, however the host process
// might be lacking the capability to request it, thus a failure to set is not an error.
pid_t workerTid = mWorker->getTid();
if (workerTid > 0) {
- struct sched_param param;
- param.sched_priority = 3; // Must match SchedulingPolicyService.PRIORITY_MAX (Java).
+ constexpr int32_t kRTPriorityMin = 1; // SchedulingPolicyService.PRIORITY_MIN (Java).
+ constexpr int32_t kRTPriorityMax = 3; // SchedulingPolicyService.PRIORITY_MAX (Java).
+ int priorityBoost = kRTPriorityMax;
+ if (flags.getTag() == AudioIoFlags::Tag::output &&
+ isBitPositionFlagSet(flags.template get<AudioIoFlags::Tag::output>(),
+ AudioOutputFlags::SPATIALIZER)) {
+ const int32_t sptPrio =
+ property_get_int32("audio.spatializer.priority", kRTPriorityMin);
+ if (sptPrio >= kRTPriorityMin && sptPrio <= kRTPriorityMax) {
+ priorityBoost = sptPrio;
+ } else {
+ LOG(WARNING) << __func__ << ": invalid spatializer priority: " << sptPrio;
+ return ndk::ScopedAStatus::ok();
+ }
+ }
+ struct sched_param param = {
+ .sched_priority = priorityBoost,
+ };
if (sched_setscheduler(workerTid, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) {
- PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler for a fast thread";
+ PLOG(WARNING) << __func__ << ": failed to set FIFO scheduler and priority";
}
} else {
LOG(WARNING) << __func__ << ": invalid worker tid: " << workerTid;
diff --git a/audio/aidl/default/apex/com.android.hardware.audio/Android.bp b/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
index ee7e46e..ee92512 100644
--- a/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
+++ b/audio/aidl/default/apex/com.android.hardware.audio/Android.bp
@@ -46,5 +46,6 @@
prebuilts: [
"android.hardware.audio.service-aidl.example.rc",
"android.hardware.audio.service-aidl.xml",
+ "android.hardware.bluetooth.audio.xml",
],
}
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
index 77e48df..f22b7a9 100644
--- a/audio/aidl/default/bluetooth/StreamBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -16,16 +16,13 @@
#include <algorithm>
-#define ATRACE_TAG ATRACE_TAG_AUDIO
#define LOG_TAG "AHAL_StreamBluetooth"
#include <Utils.h>
#include <android-base/logging.h>
#include <audio_utils/clock.h>
-#include <utils/Trace.h>
#include "core-impl/StreamBluetooth.h"
-using aidl::android::hardware::audio::common::frameCountFromDurationUs;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::audio::core::VendorParameter;
@@ -67,8 +64,6 @@
: (mIsInput ? kBluetoothDefaultInputBufferMs
: kBluetoothDefaultOutputBufferMs) *
1000),
- mPreferredFrameCount(
- frameCountFromDurationUs(mPreferredDataIntervalUs, pcmConfig.sampleRateHz)),
mBtDeviceProxy(btDeviceProxy) {}
::android::status_t StreamBluetooth::init() {
@@ -77,6 +72,7 @@
// This is a normal situation in VTS tests.
LOG(INFO) << __func__ << ": no BT HAL proxy, stream is non-functional";
}
+ LOG(INFO) << __func__ << ": preferred data interval (us): " << mPreferredDataIntervalUs;
return ::android::OK;
}
@@ -108,12 +104,10 @@
LOG(ERROR) << __func__ << ": state= " << mBtDeviceProxy->getState() << " failed to start";
return -EIO;
}
- const size_t fc = std::min(frameCount, mPreferredFrameCount);
- const size_t bytesToTransfer = fc * mFrameSizeBytes;
+ const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
const size_t bytesTransferred = mIsInput ? mBtDeviceProxy->readData(buffer, bytesToTransfer)
: mBtDeviceProxy->writeData(buffer, bytesToTransfer);
*actualFrameCount = bytesTransferred / mFrameSizeBytes;
- ATRACE_INT("BTdropped", bytesToTransfer - bytesTransferred);
PresentationPosition presentation_position;
if (!mBtDeviceProxy->getPresentationPosition(presentation_position)) {
presentation_position.remoteDeviceAudioDelayNanos =
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index ce71d70..d6e8905 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -211,9 +211,12 @@
const int32_t rawSizeFrames =
aidl::android::hardware::audio::common::frameCountFromDurationMs(latencyMs,
sampleRateHz);
- if (latencyMs >= 5) return rawSizeFrames;
+ // Round up to nearest 16 frames since in the framework this is the size of a mixer burst.
+ const int32_t multipleOf16 = (rawSizeFrames + 15) & ~15;
+ if (multipleOf16 <= 512) return multipleOf16;
+ // Larger buffers should use powers of 2.
int32_t powerOf2 = 1;
- while (powerOf2 < rawSizeFrames) powerOf2 <<= 1;
+ while (powerOf2 < multipleOf16) powerOf2 <<= 1;
return powerOf2;
}
diff --git a/audio/aidl/default/include/core-impl/StreamBluetooth.h b/audio/aidl/default/include/core-impl/StreamBluetooth.h
index 35c3183..7f4239c 100644
--- a/audio/aidl/default/include/core-impl/StreamBluetooth.h
+++ b/audio/aidl/default/include/core-impl/StreamBluetooth.h
@@ -63,7 +63,6 @@
const std::weak_ptr<IBluetoothA2dp> mBluetoothA2dp;
const std::weak_ptr<IBluetoothLe> mBluetoothLe;
const size_t mPreferredDataIntervalUs;
- const size_t mPreferredFrameCount;
mutable std::mutex mLock;
// The lock is also used to serialize calls to the proxy.
std::shared_ptr<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl> mBtDeviceProxy
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index fa4135d..2376ed9 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -136,10 +136,12 @@
mCurrentRoute->exitStandby(mIsInput);
RETURN_STATUS_IF_ERROR(mIsInput ? inRead(buffer, frameCount, actualFrameCount)
: outWrite(buffer, frameCount, actualFrameCount));
+ mFramesSinceStart += *actualFrameCount;
+ if (!mIsInput) return ::android::OK;
+ // Only input streams need to block, for output this is implemented by MonoPipe.
const long bufferDurationUs =
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
- mFramesSinceStart += *actualFrameCount;
const long totalOffsetUs =
mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs;
LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
@@ -275,8 +277,9 @@
char* buff = (char*)buffer;
size_t actuallyRead = 0;
long remainingFrames = frameCount;
- const int64_t deadlineTimeNs = ::android::uptimeNanos() +
- getDelayInUsForFrameCount(frameCount) * NANOS_PER_MICROSECOND;
+ const int64_t deadlineTimeNs =
+ ::android::uptimeNanos() +
+ getDelayInUsForFrameCount(frameCount) * NANOS_PER_MICROSECOND / 2;
while (remainingFrames > 0) {
ssize_t framesRead = source->read(buff, remainingFrames);
LOG(VERBOSE) << __func__ << ": frames read " << framesRead;
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
index 7100431..54b82d3 100644
--- a/audio/aidl/vts/EffectFactoryHelper.h
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -23,6 +23,7 @@
#include <aidl/Vintf.h>
#include <android/binder_auto_utils.h>
+#include <system/audio_effects/aidl_effects_utils.h>
#include "AudioHalBinderServiceUtil.h"
#include "TestUtils.h"
@@ -35,21 +36,6 @@
class EffectFactoryHelper {
public:
- explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
-
- void ConnectToFactoryService() {
- mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
- ASSERT_NE(mEffectFactory, nullptr);
- }
-
- void RestartFactoryService() {
- ASSERT_NE(mEffectFactory, nullptr);
- mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
- ASSERT_NE(mEffectFactory, nullptr);
- }
-
- std::shared_ptr<IFactory> GetFactory() const { return mEffectFactory; }
-
static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor>> getAllEffectDescriptors(
std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
AudioHalBinderServiceUtil util;
@@ -74,8 +60,13 @@
return result;
}
- private:
- std::shared_ptr<IFactory> mEffectFactory;
- std::string mServiceName;
- AudioHalBinderServiceUtil binderUtil;
+ static int getHalVersion(const std::shared_ptr<IFactory>& factory) {
+ int version = 0;
+ return (factory && factory->getInterfaceVersion(&version).isOk()) ? version : 0;
+ }
+
+ static bool isReopenSupported(const std::shared_ptr<IFactory>& factory) {
+ return EffectFactoryHelper::getHalVersion(factory) >=
+ aidl::android::hardware::audio::effect::kReopenSupportedVersion;
+ }
};
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
index 4e86ec3..21df163 100644
--- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -56,10 +56,7 @@
/// Effect factory testing.
class EffectFactoryTest : public testing::TestWithParam<std::string> {
public:
- void SetUp() override {
- mFactoryHelper = std::make_unique<EffectFactoryHelper>(GetParam());
- connectAndGetFactory();
- }
+ void SetUp() override { connectAndGetFactory(); }
void TearDown() override {
for (auto& effect : mEffects) {
@@ -68,13 +65,14 @@
}
}
- std::unique_ptr<EffectFactoryHelper> mFactoryHelper;
+ std::string kServiceName = GetParam();
std::shared_ptr<IFactory> mEffectFactory;
std::vector<std::shared_ptr<IEffect>> mEffects;
const Descriptor::Identity kNullId = {.uuid = getEffectUuidNull()};
const Descriptor::Identity kZeroId = {.uuid = getEffectUuidZero()};
const Descriptor kNullDesc = {.common.id = kNullId};
const Descriptor kZeroDesc = {.common.id = kZeroId};
+ AudioHalBinderServiceUtil mBinderUtil;
template <typename Functor>
void ForEachId(const std::vector<Descriptor::Identity> ids, Functor functor) {
@@ -117,8 +115,7 @@
}
}
void connectAndGetFactory() {
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper->ConnectToFactoryService());
- mEffectFactory = mFactoryHelper->GetFactory();
+ mEffectFactory = IFactory::fromBinder(mBinderUtil.connectToService(kServiceName));
ASSERT_NE(mEffectFactory, nullptr);
}
};
@@ -128,7 +125,9 @@
}
TEST_P(EffectFactoryTest, CanBeRestarted) {
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
+ ASSERT_NE(mEffectFactory, nullptr);
+ mEffectFactory = IFactory::fromBinder(mBinderUtil.restartService());
+ ASSERT_NE(mEffectFactory, nullptr);
}
/**
@@ -250,7 +249,8 @@
EXPECT_NE(descs.size(), 0UL);
creatAndDestroyDescs(descs);
- mFactoryHelper->RestartFactoryService();
+ mEffectFactory = IFactory::fromBinder(mBinderUtil.restartService());
+ ASSERT_NE(mEffectFactory, nullptr);
connectAndGetFactory();
creatAndDestroyDescs(descs);
@@ -263,7 +263,8 @@
EXPECT_NE(descs.size(), 0UL);
std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
- ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
+ mEffectFactory = IFactory::fromBinder(mBinderUtil.restartService());
+ ASSERT_NE(mEffectFactory, nullptr);
connectAndGetFactory();
destroyEffects(effects, EX_ILLEGAL_ARGUMENT);
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 5479825..4693f10 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -42,6 +42,7 @@
using aidl::android::hardware::audio::effect::Flags;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioDeviceDescription;
@@ -613,6 +614,10 @@
* verify reopen sequence.
*/
TEST_P(AudioEffectDataPathTest, SetCommonParameterAndReopen) {
+ if (!EffectFactoryHelper::isReopenSupported(mFactory)) {
+ GTEST_SKIP() << "Skipping test as effect does not support reopen";
+ }
+
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
@@ -732,6 +737,10 @@
// Send data to effects and expect it to be consumed after effect reopen (IO AudioConfig change).
// Effects exposing bypass flags or operating in offload mode will be skipped.
TEST_P(AudioEffectDataPathTest, ConsumeDataAfterReopen) {
+ if (!EffectFactoryHelper::isReopenSupported(mFactory)) {
+ GTEST_SKIP() << "Skipping test as effect does not support reopen";
+ }
+
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
index 63324f3..e1ee320 100644
--- a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -33,6 +33,8 @@
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
+namespace {
+
using ::android::hardware::automotive::remoteaccess::BOOTUP_REASON_SYSTEM_ENTER_GARAGE_MODE;
using ::android::hardware::automotive::remoteaccess::BOOTUP_REASON_SYSTEM_REMOTE_ACCESS;
using ::android::hardware::automotive::remoteaccess::BOOTUP_REASON_USER_POWER_ON;
@@ -45,13 +47,18 @@
constexpr int SHUTDOWN_REQUEST = 289410889;
constexpr int VEHICLE_IN_USE = 287313738;
-const char* COMMAND_RUN_EMU = "source ~/.aae-toolbox/bin/bashrc && aae emulator run";
-const char* COMMAND_SET_VHAL_PROP =
+constexpr char COMMAND_RUN_EMU_LOCAL_IMAGE[] =
+ "source ~/.aae-toolbox/bin/bashrc && aae emulator run";
+constexpr char COMMAND_RUN_EMU[] = "./launch_emu.sh -v \"-writable-system -selinux permissive\"";
+constexpr char COMMAND_SET_VHAL_PROP[] =
"adb -s emulator-5554 wait-for-device && adb -s emulator-5554 root "
"&& sleep 1 && adb -s emulator-5554 wait-for-device && adb -s emulator-5554 shell "
"dumpsys android.hardware.automotive.vehicle.IVehicle/default --set %d -i %d";
pid_t emuPid = 0;
+const char* runEmuCommand = COMMAND_RUN_EMU;
+
+} // namespace
void RunServer(const std::string& serviceAddr, std::shared_ptr<ServiceImpl> service) {
ServerBuilder builder;
@@ -95,7 +102,7 @@
return false;
}
service->setBootupReason(bootupReason);
- emuPid = runCommand(COMMAND_RUN_EMU);
+ emuPid = runCommand(runEmuCommand);
printf("Emulator started in process: %d\n", emuPid);
return true;
}
@@ -247,10 +254,16 @@
};
};
+// Usage: TestWakeupClientServerHost [--local-image] [service_address_to_start]
int main(int argc, char** argv) {
std::string serviceAddr = GRPC_SERVICE_ADDRESS;
- if (argc > 1) {
- serviceAddr = argv[1];
+ for (int i = 1; i < argc; i++) {
+ char* arg = argv[1];
+ if (strcmp(arg, "--local-image") == 0) {
+ runEmuCommand = COMMAND_RUN_EMU_LOCAL_IMAGE;
+ continue;
+ }
+ serviceAddr = arg;
}
// Let the server thread run, we will force kill the server when we exit the program.
std::shared_ptr<ServiceImpl> service = std::make_shared<MyServiceImpl>();
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 072aafc..c4bcdb3 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -907,6 +907,7 @@
auto result = mValuePool->obtainBoolean(response.isvehicleinuse());
result->prop = toInt(VehicleProperty::VEHICLE_IN_USE);
result->areaId = 0;
+ result->status = VehiclePropertyStatus::AVAILABLE;
result->timestamp = elapsedRealtimeNano();
return result;
}
@@ -924,6 +925,7 @@
auto result = mValuePool->obtainInt32(response.bootupreason());
result->prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON);
result->areaId = 0;
+ result->status = VehiclePropertyStatus::AVAILABLE;
result->timestamp = elapsedRealtimeNano();
return result;
}
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index 6a2a695..97efdf6 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -153,10 +153,9 @@
propValue->status = oldStatus;
}
+ // areaId and propId must be the same between valueToUpdate and propValue.
valueUpdated = (valueToUpdate->value != propValue->value ||
- valueToUpdate->status != propValue->status ||
- valueToUpdate->prop != propValue->prop ||
- valueToUpdate->areaId != propValue->areaId);
+ valueToUpdate->status != propValue->status);
} else if (!updateStatus) {
propValue->status = VehiclePropertyStatus::AVAILABLE;
}
diff --git a/biometrics/common/config/Android.bp b/biometrics/common/config/Android.bp
new file mode 100644
index 0000000..d38ffe8
--- /dev/null
+++ b/biometrics/common/config/Android.bp
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ name: "android.hardware.biometrics.common.config",
+ export_include_dirs: ["include"],
+ vendor: true,
+ srcs: [
+ "Config.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ ],
+}
+
+cc_test_host {
+ name: "android.hardware.biometrics.common.ConfigTest",
+ local_include_dirs: ["include"],
+ srcs: [
+ "tests/ConfigTest.cpp",
+ "Config.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "liblog",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/biometrics/common/config/Config.cpp b/biometrics/common/config/Config.cpp
new file mode 100644
index 0000000..01ae864
--- /dev/null
+++ b/biometrics/common/config/Config.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VirtualHalConfig"
+
+#include "config/Config.h"
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include "../../util/include/util/Util.h"
+
+using ::android::base::ParseInt;
+
+namespace aidl::android::hardware::biometrics {
+
+Config::Config() : mSource(Config::ConfigSourceType::SOURCE_SYSPROP) {}
+
+ConfigValue Config::parseBool(const std::string& value) {
+ OptBool res;
+ if (value == "true")
+ res.emplace(true);
+ else if (value == "false")
+ res.emplace(false);
+ else
+ LOG(ERROR) << "ERROR: invalid bool " << value;
+ return res;
+}
+
+ConfigValue Config::parseString(const std::string& value) {
+ OptString res;
+ if (!value.empty()) res.emplace(value);
+ return res;
+}
+
+ConfigValue Config::parseInt32(const std::string& value) {
+ OptInt32 res;
+ if (!value.empty()) {
+ std::int32_t val;
+ if (ParseInt(value, &val)) res.emplace(val);
+ }
+ return res;
+}
+
+ConfigValue Config::parseInt64(const std::string& value) {
+ OptInt64 res;
+ if (!value.empty()) {
+ std::int64_t val = std::strtoull(value.c_str(), nullptr, 10);
+ if (val != 0LL or (val == 0LL && value == "0")) {
+ res.emplace(val);
+ }
+ }
+ return res;
+}
+
+ConfigValue Config::parseIntVec(const std::string& value) {
+ OptIntVec res;
+ for (auto& i : Util::parseIntSequence(value)) {
+ res.push_back(i);
+ }
+ return res;
+}
+
+void Config::init() {
+ LOG(INFO) << "calling init()";
+ int len = 0;
+ Config::Data* pd = getConfigData(&len);
+ for (int i = 0; i < len; i++) {
+ LOG(INFO) << "init():" << pd->name;
+ pd->value = (this->*(pd->parser))(pd->defaultValue);
+ setConfig(pd->name, *pd);
+ ++pd;
+ }
+}
+
+bool Config::setParam(const std::string& name, const std::string& value) {
+ auto it = mMap.find(name);
+ if (it == mMap.end()) {
+ LOG(ERROR) << "ERROR: setParam unknown config name " << name;
+ return false;
+ }
+ LOG(INFO) << "setParam name=" << name << "=" << value;
+
+ it->second.value = (this->*(it->second.parser))(value);
+
+ mSource = ConfigSourceType::SOURCE_AIDL;
+
+ return true;
+}
+
+ConfigValue Config::getInternal(const std::string& name) {
+ ConfigValue res;
+
+ auto data = mMap[name];
+ switch (mSource) {
+ case ConfigSourceType::SOURCE_SYSPROP:
+ res = data.getter();
+ break;
+ case ConfigSourceType::SOURCE_AIDL:
+ res = data.value;
+ break;
+ case ConfigSourceType::SOURCE_FILE:
+ LOG(WARNING) << "Unsupported";
+ break;
+ default:
+ LOG(ERROR) << " wrong srouce type " << (int)mSource;
+ break;
+ }
+
+ return res;
+}
+
+ConfigValue Config::getDefault(const std::string& name) {
+ return mMap[name].value;
+}
+
+bool Config::setInternal(const std::string& name, const ConfigValue& val) {
+ bool res = false;
+ auto data = mMap[name];
+
+ switch (mSource) {
+ case ConfigSourceType::SOURCE_SYSPROP:
+ res = data.setter(val);
+ break;
+ case ConfigSourceType::SOURCE_AIDL:
+ data.value = val;
+ res = true;
+ break;
+ case ConfigSourceType::SOURCE_FILE:
+ LOG(WARNING) << "Unsupported";
+ break;
+ default:
+ LOG(ERROR) << " wrong srouce type " << (int)mSource;
+ break;
+ }
+
+ return res;
+}
+} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/common/config/include/config/Config.h b/biometrics/common/config/include/config/Config.h
new file mode 100644
index 0000000..864e164
--- /dev/null
+++ b/biometrics/common/config/include/config/Config.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <cstdint>
+#include <iostream>
+#include <map>
+#include <optional>
+#include <sstream>
+#include <string>
+#include <variant>
+#include <vector>
+
+namespace aidl::android::hardware::biometrics {
+
+using OptBool = std::optional<bool>;
+using OptInt32 = std::optional<std::int32_t>;
+using OptInt64 = std::optional<std::int64_t>;
+using OptString = std::optional<std::string>;
+using OptIntVec = std::vector<std::optional<std::int32_t>>;
+
+using ConfigValue = std::variant<OptBool, OptInt32, OptInt64, OptString, OptIntVec>;
+
+class Config {
+ public:
+ struct Data {
+ std::string name;
+ ConfigValue (*getter)();
+ bool (*setter)(const ConfigValue&);
+ ConfigValue (Config::*parser)(const std::string&);
+ std::string defaultValue;
+ ConfigValue value;
+ };
+ enum class ConfigSourceType { SOURCE_SYSPROP, SOURCE_AIDL, SOURCE_FILE };
+
+ public:
+ Config();
+ virtual ~Config() = default;
+
+ template <typename T>
+ T get(const std::string& name) {
+ CHECK(mMap.count(name) > 0) << " biometric/config get invalid name: " << name;
+ std::optional<T> optval = std::get<std::optional<T>>(getInternal(name));
+ if (!optval) optval = std::get<std::optional<T>>(getDefault(name));
+ if (optval) return optval.value();
+ return T();
+ }
+ template <typename T>
+ bool set(const std::string& name, const T& val) {
+ CHECK(mMap.count(name) > 0) << " biometric/config set invalid name: " << name;
+ std::optional<T> aval(val);
+ ConfigValue cval(aval);
+ return setInternal(name, cval);
+ }
+ template <typename T>
+ T getopt(const std::string& name) {
+ CHECK(mMap.count(name) > 0) << " biometric/config get invalid name: " << name;
+ return std::get<T>(getInternal(name));
+ }
+ template <typename T>
+ bool setopt(const std::string& name, const T& val) {
+ CHECK(mMap.count(name) > 0) << " biometric/config set invalid name: " << name;
+ ConfigValue cval(val);
+ return setInternal(name, cval);
+ }
+
+ void init();
+
+ virtual Config::Data* getConfigData(int* size) = 0;
+ bool setParam(const std::string& name, const std::string& value);
+
+ ConfigValue parseBool(const std::string& value);
+ ConfigValue parseString(const std::string& name);
+ ConfigValue parseInt32(const std::string& value);
+ ConfigValue parseInt64(const std::string& value);
+ ConfigValue parseIntVec(const std::string& value);
+
+ protected:
+ void setConfig(const std::string& name, const Config::Data& value) { mMap[name] = value; }
+
+ private:
+ ConfigValue getInternal(const std::string& name);
+ bool setInternal(const std::string& name, const ConfigValue& val);
+ ConfigValue getDefault(const std::string& name);
+
+ Config::ConfigSourceType mSource;
+ std::map<std::string, Config::Data> mMap;
+};
+
+} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/common/config/tests/ConfigTest.cpp b/biometrics/common/config/tests/ConfigTest.cpp
new file mode 100644
index 0000000..d922040
--- /dev/null
+++ b/biometrics/common/config/tests/ConfigTest.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "config/Config.h"
+
+#define LOG_TAG "ConfigTest"
+#include <android-base/logging.h>
+
+// using namespace ::testing::Eq;
+using namespace testing;
+
+#define SP_DEFAULT_astring "astringSP"
+#define SP_DEFAULT_aint32 32
+#define SP_DEFAULT_aint64 64
+#define SP_DEFAULT_abool false
+#define SP_DEFAULT_avector \
+ { 1, 2, 3 }
+namespace aidl::android::hardware::biometrics {
+namespace TestHalProperties {
+OptString val_astring = SP_DEFAULT_astring;
+OptInt32 val_aint32 = SP_DEFAULT_aint32;
+OptInt64 val_aint64 = SP_DEFAULT_aint64;
+OptBool val_abool = SP_DEFAULT_abool;
+OptIntVec val_avector = SP_DEFAULT_avector;
+
+OptString astring() {
+ return val_astring;
+}
+bool astring(const OptString& v) {
+ val_astring = v;
+ return true;
+}
+OptInt32 aint32() {
+ return val_aint32;
+}
+bool aint32(const OptInt32& v) {
+ val_aint32 = v;
+ return true;
+}
+OptInt64 aint64() {
+ return val_aint64;
+}
+bool aint64(const OptInt64& v) {
+ val_aint64 = v;
+ return true;
+}
+OptBool abool() {
+ return val_abool;
+}
+bool abool(const OptBool& v) {
+ val_abool = v;
+ return true;
+}
+OptIntVec avector() {
+ return val_avector;
+}
+bool avector(const OptIntVec& v) {
+ val_avector = v;
+ return true;
+}
+} // namespace TestHalProperties
+using namespace TestHalProperties;
+#define AIDL_DEFAULT_astring "astringAIDL"
+#define AIDL_DEFAULT_aint32 "320"
+#define AIDL_DEFAULT_aint64 "640"
+#define AIDL_DEFAULT_abool "true"
+#define AIDL_DEFAULT_avector "10,20,30"
+#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_) \
+ ConfigValue _NAME_##Getter() { \
+ return TestHalProperties::_NAME_(); \
+ } \
+ bool _NAME_##Setter(const ConfigValue& v) { \
+ return TestHalProperties::_NAME_(std::get<_T_>(v)); \
+ }
+CREATE_GETTER_SETTER_WRAPPER(astring, OptString)
+CREATE_GETTER_SETTER_WRAPPER(aint32, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(aint64, OptInt64)
+CREATE_GETTER_SETTER_WRAPPER(abool, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(avector, std::vector<OptInt32>)
+
+// Name,Getter, Setter, Parser and default value
+#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
+static Config::Data configData[] = {
+ {NGS(astring), &Config::parseString, AIDL_DEFAULT_astring},
+ {NGS(aint32), &Config::parseInt32, AIDL_DEFAULT_aint32},
+ {NGS(aint64), &Config::parseInt64, AIDL_DEFAULT_aint64},
+ {NGS(abool), &Config::parseBool, AIDL_DEFAULT_abool},
+ {NGS(avector), &Config::parseIntVec, AIDL_DEFAULT_avector},
+};
+
+class TestConfig : public Config {
+ Config::Data* getConfigData(int* size) {
+ *size = sizeof(configData) / sizeof(configData[0]);
+ return configData;
+ }
+};
+
+class ConfigTest : public ::testing::Test {
+ protected:
+ void SetUp() override { cfg.init(); }
+ void TearDown() override {}
+
+ void switch2aidl() { cfg.setParam("astring", "astring"); }
+
+ TestConfig cfg;
+};
+
+TEST_F(ConfigTest, parseInt32) {
+ std::int32_t defval = 5678;
+ struct {
+ std::string strval;
+ std::int32_t expval;
+ } values[] = {
+ {"1234", 1234},
+ {"0", 0},
+ {"", defval},
+ {"xyz", defval},
+ };
+ for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
+ ASSERT_EQ((std::get<OptInt32>(cfg.parseInt32(values[i].strval))).value_or(defval),
+ values[i].expval);
+ }
+}
+
+TEST_F(ConfigTest, parseInt64) {
+ std::int64_t defval = 5678;
+ struct {
+ std::string strval;
+ std::int64_t expval;
+ } values[] = {
+ {"1234", 1234}, {"12345678909876", 12345678909876}, {"0", 0}, {"", defval},
+ {"xyz", defval},
+ };
+ for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
+ ASSERT_EQ((std::get<OptInt64>(cfg.parseInt64(values[i].strval))).value_or(defval),
+ values[i].expval);
+ }
+}
+
+TEST_F(ConfigTest, parseBool) {
+ bool defval = true;
+ struct {
+ std::string strval;
+ bool expval;
+ } values[] = {
+ {"false", false},
+ {"true", true},
+ {"", defval},
+ {"xyz", defval},
+ };
+ for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
+ ASSERT_EQ((std::get<OptBool>(cfg.parseBool(values[i].strval))).value_or(defval),
+ values[i].expval);
+ }
+}
+
+TEST_F(ConfigTest, parseIntVec) {
+ std::vector<std::optional<int>> defval = {};
+ struct {
+ std::string strval;
+ std::vector<std::optional<int>> expval;
+ } values[] = {
+ {"1", {1}}, {"1,2,3", {1, 2, 3}}, {"1,2,b", defval}, {"", defval}, {"xyz", defval},
+ };
+ for (int i = 0; i < sizeof(values) / sizeof(values[0]); i++) {
+ ASSERT_EQ(std::get<OptIntVec>(cfg.parseIntVec(values[i].strval)), values[i].expval);
+ }
+}
+
+TEST_F(ConfigTest, getters_sp) {
+ ASSERT_EQ(cfg.get<std::string>("astring"), val_astring);
+ ASSERT_EQ(cfg.get<std::int32_t>("aint32"), val_aint32);
+ ASSERT_EQ(cfg.get<std::int64_t>("aint64"), val_aint64);
+ ASSERT_EQ(cfg.get<bool>("abool"), val_abool);
+ OptIntVec exp{val_avector};
+ EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), exp);
+}
+
+TEST_F(ConfigTest, setters_sp) {
+ std::string val_astring_new("astringNew");
+ ASSERT_TRUE(cfg.set<std::string>("astring", val_astring_new));
+ ASSERT_EQ(cfg.get<std::string>("astring"), val_astring_new);
+
+ std::int32_t val_aint32_new = val_aint32.value() + 100;
+ ASSERT_TRUE(cfg.set<std::int32_t>("aint32", val_aint32_new));
+ ASSERT_EQ(cfg.get<std::int32_t>("aint32"), val_aint32_new);
+
+ std::int64_t val_aint64_new = val_aint64.value() + 200;
+ ASSERT_TRUE(cfg.set<std::int64_t>("aint64", val_aint64_new));
+ ASSERT_EQ(cfg.get<std::int64_t>("aint64"), val_aint64_new);
+
+ bool val_abool_new = !val_abool.value();
+ ASSERT_TRUE(cfg.set<bool>("abool", val_abool_new));
+ ASSERT_EQ(cfg.get<bool>("abool"), val_abool_new);
+
+ OptIntVec val_avector_new{100, 200};
+ ASSERT_TRUE(cfg.setopt<OptIntVec>("avector", val_avector_new));
+ EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), val_avector_new);
+}
+
+TEST_F(ConfigTest, setters_sp_null) {
+ val_astring = std::nullopt;
+ ASSERT_EQ(cfg.get<std::string>("astring"),
+ (std::get<OptString>(cfg.parseString(AIDL_DEFAULT_astring))).value());
+}
+
+TEST_F(ConfigTest, getters_aidl) {
+ cfg.setParam("astring", "astringAIDL");
+ ASSERT_EQ(cfg.get<std::string>("astring"),
+ (std::get<OptString>(cfg.parseString(AIDL_DEFAULT_astring))).value());
+ ASSERT_EQ(cfg.get<std::int32_t>("aint32"),
+ (std::get<OptInt32>(cfg.parseInt32(AIDL_DEFAULT_aint32))).value());
+ ASSERT_EQ(cfg.get<std::int64_t>("aint64"),
+ (std::get<OptInt64>(cfg.parseInt64(AIDL_DEFAULT_aint64))).value());
+ ASSERT_EQ(cfg.get<bool>("abool"),
+ (std::get<OptBool>(cfg.parseBool(AIDL_DEFAULT_abool))).value());
+ OptIntVec exp{std::get<OptIntVec>(cfg.parseIntVec(AIDL_DEFAULT_avector))};
+ EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), exp);
+}
+
+TEST_F(ConfigTest, setters_aidl) {
+ std::string val_astring_new("astringNewAidl");
+ ASSERT_TRUE(cfg.set<std::string>("astring", val_astring_new));
+ ASSERT_EQ(cfg.get<std::string>("astring"), val_astring_new);
+
+ std::int32_t val_aint32_new = val_aint32.value() + 1000;
+ ASSERT_TRUE(cfg.set<std::int32_t>("aint32", val_aint32_new));
+ ASSERT_EQ(cfg.get<std::int32_t>("aint32"), val_aint32_new);
+
+ std::int64_t val_aint64_new = val_aint64.value() + 2000;
+ ASSERT_TRUE(cfg.set<std::int64_t>("aint64", val_aint64_new));
+ ASSERT_EQ(cfg.get<std::int64_t>("aint64"), val_aint64_new);
+
+ bool val_abool_new = !val_abool.value();
+ ASSERT_TRUE(cfg.set<bool>("abool", val_abool_new));
+ ASSERT_EQ(cfg.get<bool>("abool"), val_abool_new);
+
+ OptIntVec val_avector_new{1000, 2000};
+ ASSERT_TRUE(cfg.setopt<OptIntVec>("avector", val_avector_new));
+ EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), val_avector_new);
+}
+
+TEST_F(ConfigTest, setParam) {
+ ASSERT_TRUE(cfg.setParam("aint32", "789"));
+ ASSERT_EQ(cfg.get<std::int32_t>("aint32"), 789);
+ ASSERT_TRUE(cfg.setParam("avector", "7,8,9,10"));
+ OptIntVec val_avector_new{7, 8, 9, 10};
+ EXPECT_EQ(cfg.getopt<OptIntVec>("avector"), val_avector_new);
+ ASSERT_FALSE(cfg.setParam("unknown", "any"));
+}
+} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/common/util/include/util/Util.h b/biometrics/common/util/include/util/Util.h
index efd66bc..078669d 100644
--- a/biometrics/common/util/include/util/Util.h
+++ b/biometrics/common/util/include/util/Util.h
@@ -80,7 +80,9 @@
if (ParseInt(seq, &val)) {
res.push_back(val);
} else {
- LOG(WARNING) << "Invalid int sequence:" + str + " seq:" + seq;
+ if (!str.empty()) {
+ LOG(WARNING) << "Invalid int sequence:" + str + " seq:" + seq;
+ }
res.clear();
break;
}
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index c3ec4d0..501af07 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -20,6 +20,7 @@
"FakeFingerprintEngineSide.cpp",
"Fingerprint.cpp",
"Session.cpp",
+ "FingerprintConfig.cpp",
"main.cpp",
],
stl: "c++_static",
@@ -34,9 +35,15 @@
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.biometrics.common.thread",
"android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.config",
"android.hardware.keymaster-V4-ndk",
],
installable: false, // install APEX instead
+ product_variables: {
+ debuggable: {
+ cflags: ["-DFPS_DEBUGGABLE"],
+ },
+ },
}
cc_test {
@@ -46,11 +53,11 @@
"tests/FakeFingerprintEngineTest.cpp",
"FakeFingerprintEngine.cpp",
"FakeLockoutTracker.cpp",
+ "FingerprintConfig.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.common.thread",
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
@@ -58,6 +65,8 @@
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.config",
+ "android.hardware.biometrics.common.thread",
],
vendor: true,
test_suites: ["general-tests"],
@@ -72,11 +81,11 @@
"FakeFingerprintEngineUdfps.cpp",
"FakeFingerprintEngine.cpp",
"FakeLockoutTracker.cpp",
+ "FingerprintConfig.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.common.thread",
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
@@ -84,6 +93,8 @@
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.config",
+ "android.hardware.biometrics.common.thread",
],
vendor: true,
test_suites: ["general-tests"],
@@ -96,11 +107,11 @@
srcs: [
"tests/FakeLockoutTrackerTest.cpp",
"FakeLockoutTracker.cpp",
+ "FingerprintConfig.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.common.thread",
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
@@ -108,6 +119,8 @@
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.thread",
+ "android.hardware.biometrics.common.config",
],
vendor: true,
test_suites: ["general-tests"],
@@ -122,11 +135,11 @@
"Session.cpp",
"FakeFingerprintEngine.cpp",
"FakeLockoutTracker.cpp",
+ "FingerprintConfig.cpp",
],
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.common.thread",
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
@@ -134,6 +147,8 @@
"android.hardware.biometrics.common-V4-ndk",
"android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
+ "android.hardware.biometrics.common.thread",
+ "android.hardware.biometrics.common.config",
],
vendor: true,
test_suites: ["general-tests"],
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index a7acf3d..8b8d046 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -40,13 +40,13 @@
BEGIN_OP(0);
std::uniform_int_distribution<int64_t> dist;
auto challenge = dist(mRandom);
- FingerprintHalProperties::challenge(challenge);
+ Fingerprint::cfg().set<std::int64_t>("challenge", challenge);
cb->onChallengeGenerated(challenge);
}
void FakeFingerprintEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
BEGIN_OP(0);
- FingerprintHalProperties::challenge({});
+ Fingerprint::cfg().setopt<OptInt64>("challenge", std::nullopt);
cb->onChallengeRevoked(challenge);
}
@@ -81,8 +81,7 @@
const std::future<void>& cancel) {
BEGIN_OP(0);
- auto detectInteractionSupported =
- FingerprintHalProperties::detect_interaction().value_or(false);
+ auto detectInteractionSupported = Fingerprint::cfg().get<bool>("detect_interaction");
if (!detectInteractionSupported) {
LOG(ERROR) << "Detect interaction is not supported";
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
@@ -131,10 +130,10 @@
bool FakeFingerprintEngine::onEnrollFingerDown(ISessionCallback* cb,
const keymaster::HardwareAuthToken&,
const std::future<void>& cancel) {
- BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
+ BEGIN_OP(getLatency(Fingerprint::cfg().getopt<OptIntVec>("operation_enroll_latency")));
// Force error-out
- auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
+ auto err = Fingerprint::cfg().get<std::int32_t>("operation_enroll_error");
if (err != 0) {
LOG(ERROR) << "Fail: operation_enroll_error";
auto ec = convertError(err);
@@ -143,7 +142,7 @@
}
// Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
- auto nextEnroll = FingerprintHalProperties::next_enrollment().value_or("");
+ auto nextEnroll = Fingerprint::cfg().get<std::string>("next_enrollment");
auto parts = Util::split(nextEnroll, ":");
if (parts.size() != 3) {
LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
@@ -172,19 +171,19 @@
if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
- FingerprintHalProperties::next_enrollment({});
+ Fingerprint::cfg().set<std::string>("next_enrollment", "");
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
} else { // progress and update props if last time
LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
if (left == 0) {
- auto enrollments = FingerprintHalProperties::enrollments();
+ auto enrollments = Fingerprint::cfg().getopt<OptIntVec>("enrollments");
enrollments.emplace_back(enrollmentId);
- FingerprintHalProperties::enrollments(enrollments);
- FingerprintHalProperties::next_enrollment({});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", enrollments);
+ Fingerprint::cfg().setopt<OptString>("next_enrollment", std::nullopt);
// change authenticatorId after new enrollment
- auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ auto id = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
auto newId = id + 1;
- FingerprintHalProperties::authenticator_id(newId);
+ Fingerprint::cfg().set<std::int64_t>("authenticator_id", newId);
LOG(INFO) << "Enrolled: " << enrollmentId;
}
cb->onEnrollmentProgress(enrollmentId, left);
@@ -197,11 +196,11 @@
bool FakeFingerprintEngine::onAuthenticateFingerDown(ISessionCallback* cb,
int64_t /* operationId */,
const std::future<void>& cancel) {
- BEGIN_OP(getLatency(FingerprintHalProperties::operation_authenticate_latency()));
+ BEGIN_OP(getLatency(Fingerprint::cfg().getopt<OptIntVec>("operation_authenticate_latency")));
int64_t now = Util::getSystemNanoTime();
- int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
- auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
+ int64_t duration = Fingerprint::cfg().get<std::int32_t>("operation_authenticate_duration");
+ auto acquired = Fingerprint::cfg().get<std::string>("operation_authenticate_acquired");
auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
@@ -218,14 +217,14 @@
int i = 0;
do {
- if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
+ if (Fingerprint::cfg().get<bool>("operation_authenticate_fails")) {
LOG(ERROR) << "Fail: operation_authenticate_fails";
mLockoutTracker.addFailedAttempt();
cb->onAuthenticationFailed();
return false;
}
- auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0);
+ auto err = Fingerprint::cfg().get<std::int32_t>("operation_authenticate_error");
if (err != 0) {
LOG(ERROR) << "Fail: operation_authenticate_error";
auto ec = convertError(err);
@@ -234,7 +233,7 @@
revisit if tests need*/
}
- if (FingerprintHalProperties::lockout().value_or(false)) {
+ if (Fingerprint::cfg().get<bool>("lockout")) {
LOG(ERROR) << "Fail: lockout";
cb->onLockoutPermanent();
cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
@@ -256,8 +255,8 @@
SLEEP_MS(duration / N);
} while (!Util::hasElapsed(now, duration));
- auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
- auto enrolls = FingerprintHalProperties::enrollments();
+ auto id = Fingerprint::cfg().get<std::int32_t>("enrollment_hit");
+ auto enrolls = Fingerprint::cfg().getopt<OptIntVec>("enrollments");
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
if (id > 0 && isEnrolled) {
cb->onAuthenticationSucceeded(id, {} /* hat */);
@@ -274,12 +273,13 @@
bool FakeFingerprintEngine::onDetectInteractFingerDown(ISessionCallback* cb,
const std::future<void>& cancel) {
- BEGIN_OP(getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
+ BEGIN_OP(getLatency(
+ Fingerprint::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
- int64_t duration =
- FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
+ int32_t duration =
+ Fingerprint::cfg().get<std::int32_t>("operation_detect_interaction_duration");
- auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
+ auto acquired = Fingerprint::cfg().get<std::string>("operation_detect_interaction_acquired");
auto acquiredInfos = Util::parseIntSequence(acquired);
int N = acquiredInfos.size();
int64_t now = Util::getSystemNanoTime();
@@ -292,7 +292,7 @@
int i = 0;
do {
- auto err = FingerprintHalProperties::operation_detect_interaction_error().value_or(0);
+ auto err = Fingerprint::cfg().get<std::int32_t>("operation_detect_interaction_error");
if (err != 0) {
LOG(ERROR) << "Fail: operation_detect_interaction_error";
auto ec = convertError(err);
@@ -323,7 +323,7 @@
BEGIN_OP(0);
std::vector<int32_t> ids;
- for (auto& enrollment : FingerprintHalProperties::enrollments()) {
+ for (auto& enrollment : Fingerprint::cfg().getopt<OptIntVec>("enrollments")) {
auto id = enrollment.value_or(0);
if (id > 0) {
ids.push_back(id);
@@ -339,7 +339,7 @@
std::vector<std::optional<int32_t>> newEnrollments;
std::vector<int32_t> removed;
- for (auto& enrollment : FingerprintHalProperties::enrollments()) {
+ for (auto& enrollment : Fingerprint::cfg().getopt<OptIntVec>("enrollments")) {
auto id = enrollment.value_or(0);
if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) != enrollmentIds.end()) {
removed.push_back(id);
@@ -347,7 +347,7 @@
newEnrollments.emplace_back(id);
}
}
- FingerprintHalProperties::enrollments(newEnrollments);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", newEnrollments);
cb->onEnrollmentsRemoved(enrollmentIds);
}
@@ -355,10 +355,10 @@
void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
int64_t authenticatorId;
- if (FingerprintHalProperties::enrollments().size() == 0) {
+ if (Fingerprint::cfg().getopt<OptIntVec>("enrollments").size() == 0) {
authenticatorId = 0;
} else {
- authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
+ authenticatorId = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
if (authenticatorId == 0) authenticatorId = 1;
}
cb->onAuthenticatorIdRetrieved(authenticatorId);
@@ -367,13 +367,13 @@
void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
int64_t newId;
- if (FingerprintHalProperties::enrollments().size() == 0) {
+ if (Fingerprint::cfg().getopt<OptIntVec>("enrollments").size() == 0) {
newId = 0;
} else {
- auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ auto id = Fingerprint::cfg().get<std::int64_t>("authenticator_id");
newId = id + 1;
}
- FingerprintHalProperties::authenticator_id(newId);
+ Fingerprint::cfg().set<std::int64_t>("authenticator_id", newId);
cb->onAuthenticatorIdInvalidated(newId);
}
@@ -390,7 +390,7 @@
}
void FakeFingerprintEngine::clearLockout(ISessionCallback* cb) {
- FingerprintHalProperties::lockout(false);
+ Fingerprint::cfg().set<bool>("lockout", false);
cb->onLockoutCleared();
mLockoutTracker.reset();
}
@@ -415,7 +415,7 @@
}
bool FakeFingerprintEngine::getSensorLocationConfig(SensorLocation& out) {
- auto loc = FingerprintHalProperties::sensor_location().value_or("");
+ auto loc = Fingerprint::cfg().get<std::string>("sensor_location");
auto isValidStr = false;
auto dim = Util::split(loc, ":");
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
index 68b0f0d..496b5e3 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
@@ -20,6 +20,7 @@
#include <fingerprint.sysprop.h>
+#include "Fingerprint.h"
#include "util/CancellationSignal.h"
#include "util/Util.h"
@@ -45,7 +46,7 @@
BEGIN_OP(0);
// verify whetehr touch coordinates/area matching sensor location ?
mPointerDownTime = Util::getSystemNanoTime();
- if (FingerprintHalProperties::control_illumination().value_or(false)) {
+ if (Fingerprint::cfg().get<bool>("control_illumination")) {
fingerDownAction();
}
return ndk::ScopedAStatus::ok();
diff --git a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
index b0163ee..a056db5 100644
--- a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
@@ -16,6 +16,7 @@
#include "FakeLockoutTracker.h"
#include <fingerprint.sysprop.h>
+#include "Fingerprint.h"
#include "util/Util.h"
using namespace ::android::fingerprint::virt;
@@ -29,16 +30,16 @@
}
void FakeLockoutTracker::addFailedAttempt() {
- bool enabled = FingerprintHalProperties::lockout_enable().value_or(false);
+ bool enabled = Fingerprint::cfg().get<bool>("lockout_enable");
if (enabled) {
mFailedCount++;
int32_t lockoutTimedThreshold =
- FingerprintHalProperties::lockout_timed_threshold().value_or(5);
+ Fingerprint::cfg().get<std::int32_t>("lockout_timed_threshold");
int32_t lockoutPermanetThreshold =
- FingerprintHalProperties::lockout_permanent_threshold().value_or(20);
+ Fingerprint::cfg().get<std::int32_t>("lockout_permanent_threshold");
if (mFailedCount >= lockoutPermanetThreshold) {
mCurrentMode = LockoutMode::kPermanent;
- FingerprintHalProperties::lockout(true);
+ Fingerprint::cfg().set<bool>("lockout", true);
} else if (mFailedCount >= lockoutTimedThreshold) {
if (mCurrentMode == LockoutMode::kNone) {
mCurrentMode = LockoutMode::kTimed;
@@ -53,7 +54,7 @@
FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
if (mCurrentMode == LockoutMode::kTimed) {
int32_t lockoutTimedDuration =
- FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100);
+ Fingerprint::cfg().get<std::int32_t>("lockout_timed_duration");
if (Util::hasElapsed(mLockoutTimedStart, lockoutTimedDuration)) {
mCurrentMode = LockoutMode::kNone;
mLockoutTimedStart = 0;
@@ -68,11 +69,11 @@
if (mLockoutTimedStart > 0) {
int32_t lockoutTimedDuration =
- FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100);
+ Fingerprint::cfg().get<std::int32_t>("lockout_timed_duration");
auto now = Util::getSystemNanoTime();
auto elapsed = (now - mLockoutTimedStart) / 1000000LL;
res = lockoutTimedDuration - elapsed;
- LOG(INFO) << "xxxxxx: elapsed=" << elapsed << " now = " << now
+ LOG(INFO) << "elapsed=" << elapsed << " now = " << now
<< " mLockoutTimedStart=" << mLockoutTimedStart << " res=" << res;
}
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 79b563e..dded54b 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -43,7 +43,7 @@
} // namespace
Fingerprint::Fingerprint() : mWorker(MAX_WORKER_QUEUE_SIZE) {
- std::string sensorTypeProp = FingerprintHalProperties::type().value_or("");
+ std::string sensorTypeProp = Fingerprint::cfg().get<std::string>("type");
if (sensorTypeProp == "" || sensorTypeProp == "default" || sensorTypeProp == "rear") {
mSensorType = FingerprintSensorType::REAR;
mEngine = std::make_unique<FakeFingerprintEngineRear>();
@@ -68,15 +68,13 @@
{HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */},
{SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
"" /* serialNumber */, SW_VERSION}};
- auto sensorId = FingerprintHalProperties::sensor_id().value_or(SENSOR_ID);
- auto sensorStrength =
- FingerprintHalProperties::sensor_strength().value_or((int)SENSOR_STRENGTH);
- auto maxEnrollments =
- FingerprintHalProperties::max_enrollments().value_or(MAX_ENROLLMENTS_PER_USER);
- auto navigationGuesture = FingerprintHalProperties::navigation_guesture().value_or(false);
- auto detectInteraction = FingerprintHalProperties::detect_interaction().value_or(false);
- auto displayTouch = FingerprintHalProperties::display_touch().value_or(true);
- auto controlIllumination = FingerprintHalProperties::control_illumination().value_or(false);
+ auto sensorId = Fingerprint::cfg().get<std::int32_t>("sensor_id");
+ auto sensorStrength = Fingerprint::cfg().get<std::int32_t>("sensor_strength");
+ auto maxEnrollments = Fingerprint::cfg().get<std::int32_t>("max_enrollments");
+ auto navigationGuesture = Fingerprint::cfg().get<bool>("navigation_guesture");
+ auto detectInteraction = Fingerprint::cfg().get<bool>("detect_interaction");
+ auto displayTouch = Fingerprint::cfg().get<bool>("display_touch");
+ auto controlIllumination = Fingerprint::cfg().get<bool>("control_illumination");
common::CommonProps commonProps = {sensorId, (common::SensorStrength)sensorStrength,
maxEnrollments, componentInfo};
@@ -166,6 +164,14 @@
void Fingerprint::resetConfigToDefault() {
LOG(INFO) << __func__ << ": reset virtual HAL configuration to default";
+ Fingerprint::cfg().init();
+#ifdef FPS_DEBUGGABLE
+ clearConfigSysprop();
+#endif
+}
+
+void Fingerprint::clearConfigSysprop() {
+ LOG(INFO) << __func__ << ": clear all systprop configuration";
#define RESET_CONFIG_O(__NAME__) \
if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt)
#define RESET_CONFIG_V(__NAME__) \
diff --git a/biometrics/fingerprint/aidl/default/FingerprintConfig.cpp b/biometrics/fingerprint/aidl/default/FingerprintConfig.cpp
new file mode 100644
index 0000000..82c5403
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/FingerprintConfig.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FingerprintConfig"
+
+#include "FingerprintConfig.h"
+
+#include <android-base/logging.h>
+
+#include <fingerprint.sysprop.h>
+
+using namespace ::android::fingerprint::virt;
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+// Wrapper to system property access functions
+#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_) \
+ ConfigValue _NAME_##Getter() { \
+ return FingerprintHalProperties::_NAME_(); \
+ } \
+ bool _NAME_##Setter(const ConfigValue& v) { \
+ return FingerprintHalProperties::_NAME_(std::get<_T_>(v)); \
+ }
+
+CREATE_GETTER_SETTER_WRAPPER(type, OptString)
+CREATE_GETTER_SETTER_WRAPPER(enrollments, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(enrollment_hit, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(next_enrollment, OptString)
+CREATE_GETTER_SETTER_WRAPPER(authenticator_id, OptInt64)
+CREATE_GETTER_SETTER_WRAPPER(challenge, OptInt64)
+CREATE_GETTER_SETTER_WRAPPER(sensor_id, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(sensor_location, OptString)
+CREATE_GETTER_SETTER_WRAPPER(sensor_strength, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_fails, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_duration, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_error, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_acquired, OptString)
+CREATE_GETTER_SETTER_WRAPPER(operation_enroll_error, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_enroll_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_error, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_latency, OptIntVec)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_duration, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_acquired, OptString)
+CREATE_GETTER_SETTER_WRAPPER(max_enrollments, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(navigation_guesture, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(detect_interaction, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(display_touch, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(control_illumination, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout_enable, OptBool)
+CREATE_GETTER_SETTER_WRAPPER(lockout_timed_threshold, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(lockout_timed_duration, OptInt32)
+CREATE_GETTER_SETTER_WRAPPER(lockout_permanent_threshold, OptInt32)
+
+// Name, Getter, Setter, Parser and default value
+#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
+static Config::Data configData[] = {
+ {NGS(type), &Config::parseString, "rear"},
+ {NGS(enrollments), &Config::parseIntVec, ""},
+ {NGS(enrollment_hit), &Config::parseInt32, "0"},
+ {NGS(next_enrollment), &Config::parseString, ""},
+ {NGS(authenticator_id), &Config::parseInt64, "0"},
+ {NGS(challenge), &Config::parseInt64, ""},
+ {NGS(sensor_id), &Config::parseInt32, "5"},
+ {NGS(sensor_location), &Config::parseString, ""},
+ {NGS(sensor_strength), &Config::parseInt32, "2"}, // STRONG
+ {NGS(operation_authenticate_fails), &Config::parseBool, "false"},
+ {NGS(operation_authenticate_latency), &Config::parseIntVec, ""},
+ {NGS(operation_authenticate_duration), &Config::parseInt32, "10"},
+ {NGS(operation_authenticate_error), &Config::parseInt32, "0"},
+ {NGS(operation_authenticate_acquired), &Config::parseString, "1"},
+ {NGS(operation_enroll_error), &Config::parseInt32, "0"},
+ {NGS(operation_enroll_latency), &Config::parseIntVec, ""},
+ {NGS(operation_detect_interaction_latency), &Config::parseIntVec, ""},
+ {NGS(operation_detect_interaction_error), &Config::parseInt32, "0"},
+ {NGS(operation_detect_interaction_duration), &Config::parseInt32, "10"},
+ {NGS(operation_detect_interaction_acquired), &Config::parseString, "1"},
+ {NGS(max_enrollments), &Config::parseInt32, "5"},
+ {NGS(navigation_guesture), &Config::parseBool, "false"},
+ {NGS(detect_interaction), &Config::parseBool, "false"},
+ {NGS(display_touch), &Config::parseBool, "true"},
+ {NGS(control_illumination), &Config::parseBool, "false"},
+ {NGS(lockout), &Config::parseBool, "false"},
+ {NGS(lockout_enable), &Config::parseBool, "false"},
+ {NGS(lockout_timed_threshold), &Config::parseInt32, "5"},
+ {NGS(lockout_timed_duration), &Config::parseInt32, "10000"},
+ {NGS(lockout_permanent_threshold), &Config::parseInt32, "20"},
+};
+
+Config::Data* FingerprintConfig::getConfigData(int* size) {
+ *size = sizeof(configData) / sizeof(configData[0]);
+ return configData;
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
index 2bd66d4..1576f07 100644
--- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
@@ -23,6 +23,7 @@
#include "FakeFingerprintEngineSide.h"
#include "FakeFingerprintEngineUdfps.h"
+#include "FingerprintConfig.h"
#include "Session.h"
#include "thread/WorkerThread.h"
@@ -40,10 +41,20 @@
binder_status_t dump(int fd, const char** args, uint32_t numArgs);
binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
+ static FingerprintConfig& cfg() {
+ static FingerprintConfig* cfg = nullptr;
+ if (cfg == nullptr) {
+ cfg = new FingerprintConfig();
+ cfg->init();
+ }
+ return *cfg;
+ }
+
private:
void resetConfigToDefault();
void onHelp(int);
void onSimFingerDown();
+ void clearConfigSysprop();
std::unique_ptr<FakeFingerprintEngine> mEngine;
WorkerThread mWorker;
diff --git a/biometrics/fingerprint/aidl/default/include/FingerprintConfig.h b/biometrics/fingerprint/aidl/default/include/FingerprintConfig.h
new file mode 100644
index 0000000..bd1ad4c
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/FingerprintConfig.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "config/Config.h"
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class FingerprintConfig : public Config {
+ Config::Data* getConfigData(int* size) override;
+};
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index 8b06c8e..039f25e 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -21,6 +21,7 @@
#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
#include "FakeFingerprintEngine.h"
+#include "Fingerprint.h"
#include "util/Util.h"
using namespace ::android::fingerprint::virt;
@@ -125,21 +126,20 @@
class FakeFingerprintEngineTest : public ::testing::Test {
protected:
void SetUp() override {
- FingerprintHalProperties::operation_enroll_latency({0});
- FingerprintHalProperties::operation_authenticate_latency({0});
- FingerprintHalProperties::operation_detect_interaction_latency({0});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_enroll_latency", {0});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_latency", {0});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {0});
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
}
void TearDown() override {
- FingerprintHalProperties::operation_authenticate_error(0);
- FingerprintHalProperties::operation_detect_interaction_error(0);
- FingerprintHalProperties::operation_authenticate_acquired("");
- FingerprintHalProperties::operation_enroll_latency({});
- FingerprintHalProperties::operation_authenticate_latency({});
- FingerprintHalProperties::operation_detect_interaction_latency({});
- FingerprintHalProperties::operation_authenticate_fails(false);
- FingerprintHalProperties::operation_detect_interaction_latency({});
+ Fingerprint::cfg().set<std::int32_t>("operation_authenticate_error", 0);
+ Fingerprint::cfg().set<std::int32_t>("operation_detect_interaction_error", 0);
+ Fingerprint::cfg().set<std::string>("operation_authenticate_acquired", "");
+ Fingerprint::cfg().setopt<OptIntVec>("operation_enroll_latency", {});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_authenticate_latency", {});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
+ Fingerprint::cfg().set<bool>("operation_authenticate_fails", false);
}
FakeFingerprintEngine mEngine;
@@ -149,58 +149,58 @@
TEST_F(FakeFingerprintEngineTest, GenerateChallenge) {
mEngine.generateChallengeImpl(mCallback.get());
- ASSERT_EQ(FingerprintHalProperties::challenge().value(), mCallback->mLastChallenge);
+ ASSERT_EQ(Fingerprint::cfg().get<std::int64_t>("challenge"), mCallback->mLastChallenge);
}
TEST_F(FakeFingerprintEngineTest, RevokeChallenge) {
- auto challenge = FingerprintHalProperties::challenge().value_or(10);
+ auto challenge = Fingerprint::cfg().get<std::int64_t>("challenge");
mEngine.revokeChallengeImpl(mCallback.get(), challenge);
- ASSERT_FALSE(FingerprintHalProperties::challenge().has_value());
+ ASSERT_FALSE((Fingerprint::cfg().getopt<OptInt64>("challenge")).has_value());
ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
}
TEST_F(FakeFingerprintEngineTest, ResetLockout) {
- FingerprintHalProperties::lockout(true);
+ Fingerprint::cfg().get<bool>("lockout");
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
mEngine.resetLockoutImpl(mCallback.get(), hat);
- ASSERT_FALSE(FingerprintHalProperties::lockout().value_or(true));
+ ASSERT_FALSE(Fingerprint::cfg().get<bool>("lockout"));
}
TEST_F(FakeFingerprintEngineTest, AuthenticatorId) {
- FingerprintHalProperties::enrollments({1});
- FingerprintHalProperties::authenticator_id(50);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1});
+ Fingerprint::cfg().set<std::int64_t>("authenticator_id", 50);
mEngine.getAuthenticatorIdImpl(mCallback.get());
ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
}
TEST_F(FakeFingerprintEngineTest, AuthenticatorIdInvalidate) {
- FingerprintHalProperties::authenticator_id(500);
+ Fingerprint::cfg().set<std::int64_t>("authenticator_id", 500);
mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
- ASSERT_NE(500, FingerprintHalProperties::authenticator_id().value());
+ ASSERT_NE(500, Fingerprint::cfg().get<std::int64_t>("authenticator_id"));
ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
}
TEST_F(FakeFingerprintEngineTest, Enroll) {
- FingerprintHalProperties::enrollments({});
- FingerprintHalProperties::next_enrollment("4:0,0:true");
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {});
+ Fingerprint::cfg().set<std::string>("next_enrollment", "4:0,0:true");
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
mEngine.notifyFingerdown();
mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kEnroll);
mEngine.fingerDownAction();
- ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
- ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
- ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
+ ASSERT_FALSE(Fingerprint::cfg().getopt<OptString>("next_enrollment").has_value());
+ ASSERT_EQ(1, Fingerprint::cfg().getopt<OptIntVec>("enrollments").size());
+ ASSERT_EQ(4, Fingerprint::cfg().getopt<OptIntVec>("enrollments")[0].value());
ASSERT_EQ(4, mCallback->mLastEnrolled);
ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kIdle);
}
TEST_F(FakeFingerprintEngineTest, EnrollCancel) {
- FingerprintHalProperties::enrollments({});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {});
auto next = "4:0,0:true";
- FingerprintHalProperties::next_enrollment(next);
+ Fingerprint::cfg().set<std::string>("next_enrollment", next);
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
mCancel.set_value();
mEngine.notifyFingerdown();
@@ -208,35 +208,35 @@
mEngine.fingerDownAction();
ASSERT_EQ(Error::CANCELED, mCallback->mError);
ASSERT_EQ(-1, mCallback->mLastEnrolled);
- ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
- ASSERT_EQ(next, FingerprintHalProperties::next_enrollment().value_or(""));
+ ASSERT_EQ(0, Fingerprint::cfg().getopt<OptIntVec>("enrollments").size());
+ ASSERT_EQ(next, Fingerprint::cfg().get<std::string>("next_enrollment"));
}
TEST_F(FakeFingerprintEngineTest, EnrollFail) {
- FingerprintHalProperties::enrollments({});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {});
auto next = "2:0,0:false";
- FingerprintHalProperties::next_enrollment(next);
+ Fingerprint::cfg().set<std::string>("next_enrollment", next);
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
mEngine.notifyFingerdown();
mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
mEngine.fingerDownAction();
ASSERT_EQ(Error::UNABLE_TO_PROCESS, mCallback->mError);
ASSERT_EQ(-1, mCallback->mLastEnrolled);
- ASSERT_EQ(0, FingerprintHalProperties::enrollments().size());
- ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
+ ASSERT_EQ(0, Fingerprint::cfg().getopt<OptIntVec>("enrollments").size());
+ ASSERT_FALSE(Fingerprint::cfg().getopt<OptString>("next_enrollment").has_value());
}
TEST_F(FakeFingerprintEngineTest, EnrollAcquired) {
- FingerprintHalProperties::enrollments({});
- FingerprintHalProperties::next_enrollment("4:0,5-[12,1013]:true");
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {});
+ Fingerprint::cfg().set<std::string>("next_enrollment", "4:0,5-[12,1013]:true");
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
int32_t prevCnt = mCallback->mLastAcquiredCount;
mEngine.notifyFingerdown();
mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
mEngine.fingerDownAction();
- ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
- ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
- ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
+ ASSERT_FALSE(Fingerprint::cfg().getopt<OptString>("next_enrollment").has_value());
+ ASSERT_EQ(1, Fingerprint::cfg().getopt<OptIntVec>("enrollments").size());
+ ASSERT_EQ(4, Fingerprint::cfg().getopt<OptIntVec>("enrollments")[0].value());
ASSERT_EQ(4, mCallback->mLastEnrolled);
ASSERT_EQ(prevCnt + 3, mCallback->mLastAcquiredCount);
ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
@@ -244,8 +244,8 @@
}
TEST_F(FakeFingerprintEngineTest, Authenticate) {
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kAuthenticate);
@@ -257,8 +257,8 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) {
- FingerprintHalProperties::enrollments({2});
- FingerprintHalProperties::enrollment_hit(2);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
mCancel.set_value();
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
@@ -268,8 +268,8 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateNotSet) {
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit({});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().setopt<OptInt32>("enrollment_hit", std::nullopt);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -277,8 +277,8 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateNotEnrolled) {
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(3);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 3);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -287,9 +287,9 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
- FingerprintHalProperties::enrollments({22, 2});
- FingerprintHalProperties::enrollment_hit(2);
- FingerprintHalProperties::lockout(true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {22, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
+ Fingerprint::cfg().set<bool>("lockout", true);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -298,7 +298,7 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateError8) {
- FingerprintHalProperties::operation_authenticate_error(8);
+ Fingerprint::cfg().set<std::int32_t>("operation_authenticate_error", 8);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -307,7 +307,7 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateError9) {
- FingerprintHalProperties::operation_authenticate_error(1009);
+ Fingerprint::cfg().set<std::int32_t>("operation_authenticate_error", 1009);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -316,7 +316,7 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateFails) {
- FingerprintHalProperties::operation_authenticate_fails(true);
+ Fingerprint::cfg().set<bool>("operation_authenticate_fails", true);
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
mEngine.fingerDownAction();
@@ -325,10 +325,10 @@
}
TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) {
- FingerprintHalProperties::lockout(false);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
- FingerprintHalProperties::operation_authenticate_acquired("4,1009");
+ Fingerprint::cfg().set<bool>("lockout", false);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
+ Fingerprint::cfg().set<std::string>("operation_authenticate_acquired", "4,1009");
int32_t prevCount = mCallback->mLastAcquiredCount;
mEngine.notifyFingerdown();
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
@@ -341,10 +341,10 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
- FingerprintHalProperties::operation_detect_interaction_acquired("");
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
+ Fingerprint::cfg().set<std::string>("operation_detect_interaction_acquired", "");
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
ASSERT_EQ(mEngine.getWorkMode(), FakeFingerprintEngine::WorkMode::kDetectInteract);
@@ -355,9 +355,9 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
mCancel.set_value();
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
@@ -367,9 +367,9 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit({});
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().setopt<OptInt32>("enrollment_hit", std::nullopt);
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
mEngine.fingerDownAction();
@@ -377,8 +377,8 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectNotEnrolled) {
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(25);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 25);
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
mEngine.fingerDownAction();
@@ -386,8 +386,8 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::operation_detect_interaction_error(8);
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().set<std::int32_t>("operation_detect_interaction_error", 8);
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
mEngine.fingerDownAction();
@@ -397,10 +397,10 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
- FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
+ Fingerprint::cfg().set<std::string>("operation_detect_interaction_acquired", "4,1013");
int32_t prevCount = mCallback->mLastAcquiredCount;
mEngine.notifyFingerdown();
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
@@ -412,10 +412,10 @@
}
TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) {
- FingerprintHalProperties::enrollments({2, 4, 8});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {2, 4, 8});
mEngine.enumerateEnrollmentsImpl(mCallback.get());
ASSERT_EQ(3, mCallback->mLastEnrollmentEnumerated.size());
- for (auto id : FingerprintHalProperties::enrollments()) {
+ for (auto id : Fingerprint::cfg().getopt<OptIntVec>("enrollments")) {
ASSERT_TRUE(std::find(mCallback->mLastEnrollmentEnumerated.begin(),
mCallback->mLastEnrollmentEnumerated.end(),
id) != mCallback->mLastEnrollmentEnumerated.end());
@@ -423,9 +423,9 @@
}
TEST_F(FakeFingerprintEngineTest, RemoveEnrolled) {
- FingerprintHalProperties::enrollments({2, 4, 8, 1});
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {2, 4, 8, 1});
mEngine.removeEnrollmentsImpl(mCallback.get(), {2, 8});
- auto enrolls = FingerprintHalProperties::enrollments();
+ auto enrolls = Fingerprint::cfg().getopt<OptIntVec>("enrollments");
ASSERT_EQ(2, mCallback->mLastEnrollmentRemoved.size());
for (auto id : {2, 8}) {
ASSERT_TRUE(std::find(mCallback->mLastEnrollmentRemoved.begin(),
@@ -509,17 +509,17 @@
}
TEST_F(FakeFingerprintEngineTest, randomLatency) {
- FingerprintHalProperties::operation_detect_interaction_latency({});
- ASSERT_EQ(DEFAULT_LATENCY,
- mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
- FingerprintHalProperties::operation_detect_interaction_latency({10});
- ASSERT_EQ(10,
- mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
- FingerprintHalProperties::operation_detect_interaction_latency({1, 1000});
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
+ ASSERT_EQ(DEFAULT_LATENCY, mEngine.getLatency(Fingerprint::cfg().getopt<OptIntVec>(
+ "operation_detect_interaction_latency")));
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {10});
+ ASSERT_EQ(10, mEngine.getLatency(Fingerprint::cfg().getopt<OptIntVec>(
+ "operation_detect_interaction_latency")));
+ Fingerprint::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {1, 1000});
std::set<int32_t> latencySet;
for (int i = 0; i < 100; i++) {
latencySet.insert(mEngine.getLatency(
- FingerprintHalProperties::operation_detect_interaction_latency()));
+ Fingerprint::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
}
ASSERT_TRUE(latencySet.size() > 95);
}
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
index 5a30db1..eb45f98 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
@@ -23,6 +23,7 @@
#include "FakeFingerprintEngine.h"
#include "FakeFingerprintEngineUdfps.h"
+#include "Fingerprint.h"
using namespace ::android::fingerprint::virt;
using namespace ::aidl::android::hardware::biometrics::fingerprint;
@@ -99,7 +100,7 @@
void TearDown() override {
// reset to default
- FingerprintHalProperties::sensor_location("");
+ Fingerprint::cfg().set<std::string>("sensor_location", "");
}
FakeFingerprintEngineUdfps mEngine;
@@ -113,14 +114,14 @@
TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationOk) {
auto loc = "100:200:30";
- FingerprintHalProperties::sensor_location(loc);
+ Fingerprint::cfg().set<std::string>("sensor_location", loc);
SensorLocation sc = mEngine.getSensorLocation();
ASSERT_TRUE(sc.sensorLocationX == 100);
ASSERT_TRUE(sc.sensorLocationY == 200);
ASSERT_TRUE(sc.sensorRadius == 30);
loc = "100:200:30:screen1";
- FingerprintHalProperties::sensor_location(loc);
+ Fingerprint::cfg().set<std::string>("sensor_location", loc);
sc = mEngine.getSensorLocation();
ASSERT_TRUE(sc.sensorLocationX == 100);
ASSERT_TRUE(sc.sensorLocationY == 200);
@@ -132,7 +133,7 @@
const std::vector<std::string> badStr{"", "100", "10:20", "10,20,5", "a:b:c"};
SensorLocation sc;
for (const auto& s : badStr) {
- FingerprintHalProperties::sensor_location(s);
+ Fingerprint::cfg().set<std::string>("sensor_location", s);
sc = mEngine.getSensorLocation();
ASSERT_TRUE(isDefaultLocation(sc));
}
@@ -158,7 +159,7 @@
std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
std::promise<void> cancel;
keymaster::HardwareAuthToken hat{.mac = {5, 6}};
- FingerprintHalProperties::next_enrollment("5:0,0:true");
+ Fingerprint::cfg().set<std::string>("next_enrollment", "5:0,0:true");
mEngine.notifyFingerdown();
mEngine.enrollImpl(cb.get(), hat, cancel.get_future());
ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kEnroll);
@@ -169,10 +170,10 @@
}
TEST_F(FakeFingerprintEngineUdfpsTest, detectInteraction) {
- FingerprintHalProperties::detect_interaction(true);
- FingerprintHalProperties::enrollments({1, 2});
- FingerprintHalProperties::enrollment_hit(2);
- FingerprintHalProperties::operation_detect_interaction_acquired("");
+ Fingerprint::cfg().set<bool>("detect_interaction", true);
+ Fingerprint::cfg().setopt<OptIntVec>("enrollments", {1, 2});
+ Fingerprint::cfg().set<std::int32_t>("enrollment_hit", 2);
+ Fingerprint::cfg().set<std::string>("operation_detect_interaction_acquired", "");
std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
std::promise<void> cancel;
mEngine.notifyFingerdown();
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
index 93c6f84..3c12b6d 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -21,6 +21,7 @@
#include <android-base/logging.h>
#include "FakeLockoutTracker.h"
+#include "Fingerprint.h"
#include "util/Util.h"
using namespace ::android::fingerprint::virt;
@@ -35,32 +36,33 @@
static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
void SetUp() override {
- FingerprintHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
- FingerprintHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
- FingerprintHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
+ Fingerprint::cfg().set<std::int32_t>("lockout_timed_threshold", LOCKOUT_TIMED_THRESHOLD);
+ Fingerprint::cfg().set<std::int32_t>("lockout_timed_duration", LOCKOUT_TIMED_DURATION);
+ Fingerprint::cfg().set<std::int32_t>("lockout_permanent_threshold",
+ LOCKOUT_PERMANENT_THRESHOLD);
}
void TearDown() override {
// reset to default
- FingerprintHalProperties::lockout_timed_threshold(5);
- FingerprintHalProperties::lockout_timed_duration(20);
- FingerprintHalProperties::lockout_permanent_threshold(10000);
- FingerprintHalProperties::lockout_enable(false);
- FingerprintHalProperties::lockout(false);
+ Fingerprint::cfg().set<std::int32_t>("lockout_timed_threshold", 5);
+ Fingerprint::cfg().set<std::int32_t>("lockout_timed_duration", 20);
+ Fingerprint::cfg().set<std::int32_t>("lockout_permanent_threshold", 10000);
+ Fingerprint::cfg().set<bool>("lockout_enable", false);
+ Fingerprint::cfg().set<bool>("lockout", false);
}
FakeLockoutTracker mLockoutTracker;
};
TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
- FingerprintHalProperties::lockout_enable(false);
+ Fingerprint::cfg().set<bool>("lockout_enable", false);
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++) mLockoutTracker.addFailedAttempt();
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
mLockoutTracker.reset();
}
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
- FingerprintHalProperties::lockout_enable(true);
+ Fingerprint::cfg().set<bool>("lockout_enable", true);
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++) mLockoutTracker.addFailedAttempt();
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
// time left
@@ -77,12 +79,12 @@
}
TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
- FingerprintHalProperties::lockout_enable(true);
+ Fingerprint::cfg().set<bool>("lockout_enable", true);
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++) mLockoutTracker.addFailedAttempt();
ASSERT_NE(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
mLockoutTracker.addFailedAttempt();
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
- ASSERT_TRUE(FingerprintHalProperties::lockout());
+ ASSERT_TRUE(Fingerprint::cfg().get<bool>("lockout"));
mLockoutTracker.reset();
}
diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp
index 69db1b3..af6bf86 100644
--- a/bluetooth/audio/aidl/default/Android.bp
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -40,3 +40,10 @@
"libbluetooth_audio_session_aidl",
],
}
+
+prebuilt_etc {
+ name: "android.hardware.bluetooth.audio.xml",
+ src: "bluetooth_audio.xml",
+ sub_dir: "vintf",
+ installable: false,
+}
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
index 4a95a41..4d29743 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/IdentifierType.aidl
@@ -174,7 +174,7 @@
* - 13 bit: Fractional bits of longitude
* - 8 bit: Integer bits of longitude
* - 1 bit: 0 for east and 1 for west for longitude
- * - 1 bit: 0, representing latitude
+ * - 1 bit: 0, representing longitude
* - 5 bit: pad of zeros separating longitude and latitude
* - 4 bit: Bits 4:7 of altitude
* - 13 bit: Fractional bits of latitude
diff --git a/broadcastradio/common/utilsaidl/src/Utils.cpp b/broadcastradio/common/utilsaidl/src/Utils.cpp
index ddc5b8d..4ab04d2 100644
--- a/broadcastradio/common/utilsaidl/src/Utils.cpp
+++ b/broadcastradio/common/utilsaidl/src/Utils.cpp
@@ -296,7 +296,12 @@
sel.primaryId.type > IdentifierType::VENDOR_END)) {
return false;
}
- return isValid(sel.primaryId);
+ for (auto it = begin(sel); it != end(sel); it++) {
+ if (!isValid(*it)) {
+ return false;
+ }
+ }
+ return true;
}
ProgramIdentifier makeIdentifier(IdentifierType type, int64_t value) {
diff --git a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
index 6c75759..56365c5 100644
--- a/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
+++ b/broadcastradio/common/utilsaidl/src/UtilsV2.cpp
@@ -102,15 +102,16 @@
expect(val < 1000u, "SXM channel < 1000");
break;
case IdentifierType::HD_STATION_LOCATION: {
+ val >>= 26;
uint64_t latitudeBit = val & 0x1;
- expect(latitudeBit == 1u, "Latitude comes first");
- val >>= 27;
+ expect(latitudeBit == 0u, "Longitude comes first");
+ val >>= 1;
uint64_t latitudePad = val & 0x1Fu;
- expect(latitudePad == 0u, "Latitude padding");
- val >>= 5;
+ expect(latitudePad == 0u, "Longitude padding");
+ val >>= 31;
uint64_t longitudeBit = val & 0x1;
- expect(longitudeBit == 1u, "Longitude comes next");
- val >>= 27;
+ expect(longitudeBit == 1u, "Latitude comes next");
+ val >>= 1;
uint64_t longitudePad = val & 0x1Fu;
expect(longitudePad == 0u, "Latitude padding");
break;
@@ -135,7 +136,12 @@
sel.primaryId.type > IdentifierType::VENDOR_END)) {
return false;
}
- return isValidV2(sel.primaryId);
+ for (auto it = begin(sel); it != end(sel); it++) {
+ if (!isValidV2(*it)) {
+ return false;
+ }
+ }
+ return true;
}
bool isValidMetadataV2(const Metadata& metadata) {
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 2b69442..951ca85 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -88,8 +88,7 @@
stem: "compatibility_matrix.202504.xml",
srcs: ["compatibility_matrix.202504.xml"],
kernel_configs: [
- "kernel_config_w_6.1",
- "kernel_config_w_6.6",
+ "kernel_config_w_6.next",
],
}
diff --git a/media/bufferpool/aidl/default/BufferPool.cpp b/media/bufferpool/aidl/default/BufferPool.cpp
index ed4574f..57716db 100644
--- a/media/bufferpool/aidl/default/BufferPool.cpp
+++ b/media/bufferpool/aidl/default/BufferPool.cpp
@@ -102,11 +102,11 @@
if (it->isInvalidated(bufferId)) {
uint32_t msgId = 0;
if (it->mNeedsAck) {
- msgId = ++mInvalidationId;
- if (msgId == 0) {
- // wrap happens
- msgId = ++mInvalidationId;
+ if (mInvalidationId == UINT_MAX) {
+ // wrap happens;
+ mInvalidationId = 0;
}
+ msgId = ++mInvalidationId;
}
channel.postInvalidation(msgId, it->mFrom, it->mTo);
it = mPendings.erase(it);
@@ -125,11 +125,11 @@
const std::shared_ptr<Accessor> &impl) {
uint32_t msgId = 0;
if (needsAck) {
- msgId = ++mInvalidationId;
- if (msgId == 0) {
- // wrap happens
- msgId = ++mInvalidationId;
+ if (mInvalidationId == UINT_MAX) {
+ //wrap happens
+ mInvalidationId = 0;
}
+ msgId = ++mInvalidationId;
}
ALOGV("bufferpool2 invalidation requested and queued");
if (left == 0) {
diff --git a/media/bufferpool/aidl/default/BufferStatus.cpp b/media/bufferpool/aidl/default/BufferStatus.cpp
index 19caa1e..fecbe3f 100644
--- a/media/bufferpool/aidl/default/BufferStatus.cpp
+++ b/media/bufferpool/aidl/default/BufferStatus.cpp
@@ -26,8 +26,17 @@
using aidl::android::hardware::media::bufferpool2::BufferStatus;
+uint32_t wrappedMinus(uint32_t a, uint32_t b) {
+ if (a >= b) {
+ return a - b;
+ } else {
+ return ~(b - a) + 1;
+ }
+}
+
bool isMessageLater(uint32_t curMsgId, uint32_t prevMsgId) {
- return curMsgId != prevMsgId && curMsgId - prevMsgId < prevMsgId - curMsgId;
+ return curMsgId != prevMsgId &&
+ wrappedMinus(curMsgId, prevMsgId) < wrappedMinus(prevMsgId, curMsgId);
}
bool isBufferInRange(BufferId from, BufferId to, BufferId bufferId) {
diff --git a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
index 01f7327..451eaa9 100644
--- a/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
+++ b/radio/aidl/android/hardware/radio/network/SecurityAlgorithm.aidl
@@ -62,7 +62,7 @@
// IMS and SIP layer security (See 3GPP TS 33.203)
// No IPsec config
SIP_NO_IPSEC_CONFIG = 66,
- IMS_NULL = 67,
+ IMS_NULL = 67, // Deprecated. Use SIP_NO_IPSEC_CONFIG and SIP_NULL instead.
// Has IPsec config
SIP_NULL = 68,
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 953630b..122a421 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -46,9 +46,74 @@
],
}
+rust_binary {
+ name: "android.hardware.security.keymint-service.nonsecure",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.security.keymint-service.rc"],
+ vintf_fragments: [
+ "android.hardware.security.keymint-service.xml",
+ "android.hardware.security.sharedsecret-service.xml",
+ "android.hardware.security.secureclock-service.xml",
+ ],
+ defaults: [
+ "keymint_use_latest_hal_aidl_rust",
+ ],
+ srcs: [
+ "main.rs",
+ ],
+ rustlibs: [
+ "libandroid_logger",
+ "libbinder_rs",
+ "liblog_rust",
+ "libkmr_hal",
+ "libkmr_hal_nonsecure",
+ "libkmr_ta_nonsecure",
+ ],
+ required: [
+ "android.hardware.hardware_keystore.xml",
+ ],
+}
+
prebuilt_etc {
name: "android.hardware.hardware_keystore.xml",
sub_dir: "permissions",
vendor: true,
src: "android.hardware.hardware_keystore.xml",
}
+
+rust_library {
+ name: "libkmr_hal_nonsecure",
+ crate_name: "kmr_hal_nonsecure",
+ vendor_available: true,
+ lints: "android",
+ rustlibs: [
+ "libbinder_rs",
+ "libhex",
+ "liblibc",
+ "liblog_rust",
+ "libkmr_hal",
+ "libkmr_wire",
+ ],
+ srcs: ["hal/lib.rs"],
+
+}
+
+rust_library {
+ name: "libkmr_ta_nonsecure",
+ crate_name: "kmr_ta_nonsecure",
+ vendor_available: true,
+ host_supported: true,
+ lints: "android",
+ rustlibs: [
+ "libhex",
+ "liblibc",
+ "liblog_rust",
+ "libkmr_common",
+ "libkmr_crypto_boring",
+ "libkmr_ta",
+ "libkmr_wire",
+ ],
+ srcs: ["ta/lib.rs"],
+
+}
diff --git a/security/keymint/aidl/default/hal/lib.rs b/security/keymint/aidl/default/hal/lib.rs
new file mode 100644
index 0000000..621f077
--- /dev/null
+++ b/security/keymint/aidl/default/hal/lib.rs
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! KeyMint helper functions that are only suitable for non-secure environments
+//! such as Cuttlefish.
+
+use kmr_hal::env::get_property;
+use log::error;
+
+/// Populate attestation ID information based on properties (where available).
+/// Retrieving the serial number requires SELinux permission.
+pub fn attestation_id_info() -> kmr_wire::AttestationIdInfo {
+ let prop = |name| {
+ get_property(name)
+ .unwrap_or_else(|_| format!("{} unavailable", name))
+ .as_bytes()
+ .to_vec()
+ };
+ kmr_wire::AttestationIdInfo {
+ brand: prop("ro.product.brand"),
+ device: prop("ro.product.device"),
+ product: prop("ro.product.name"),
+ serial: prop("ro.serialno"),
+ manufacturer: prop("ro.product.manufacturer"),
+ model: prop("ro.product.model"),
+ // Currently modem_simulator always returns one fixed value. See `handleGetIMEI` in
+ // device/google/cuttlefish/host/commands/modem_simulator/misc_service.cpp for more details.
+ // TODO(b/263188546): Use device-specific IMEI values when available.
+ imei: b"867400022047199".to_vec(),
+ imei2: b"867400022047199".to_vec(),
+ meid: vec![],
+ }
+}
+
+/// Get boot information based on system properties.
+pub fn get_boot_info() -> kmr_wire::SetBootInfoRequest {
+ // No access to a verified boot key.
+ let verified_boot_key = vec![0; 32];
+ let vbmeta_digest = get_property("ro.boot.vbmeta.digest").unwrap_or_else(|_| "00".repeat(32));
+ let verified_boot_hash = hex::decode(&vbmeta_digest).unwrap_or_else(|_e| {
+ error!("failed to parse hex data in '{}'", vbmeta_digest);
+ vec![0; 32]
+ });
+ let device_boot_locked = match get_property("ro.boot.vbmeta.device_state")
+ .unwrap_or_else(|_| "no-prop".to_string())
+ .as_str()
+ {
+ "locked" => true,
+ "unlocked" => false,
+ v => {
+ error!("Unknown device_state '{}', treating as unlocked", v);
+ false
+ }
+ };
+ let verified_boot_state = match get_property("ro.boot.verifiedbootstate")
+ .unwrap_or_else(|_| "no-prop".to_string())
+ .as_str()
+ {
+ "green" => 0, // Verified
+ "yellow" => 1, // SelfSigned
+ "orange" => 2, // Unverified,
+ "red" => 3, // Failed,
+ v => {
+ error!("Unknown boot state '{}', treating as Unverified", v);
+ 2
+ }
+ };
+
+ // Attempt to get the boot patchlevel from a system property. This requires an SELinux
+ // permission, so fall back to re-using the OS patchlevel if this can't be done.
+ let boot_patchlevel_prop = get_property("ro.vendor.boot_security_patch").unwrap_or_else(|e| {
+ error!("Failed to retrieve boot patchlevel: {:?}", e);
+ get_property(kmr_hal::env::OS_PATCHLEVEL_PROPERTY)
+ .unwrap_or_else(|_| "1970-09-19".to_string())
+ });
+ let boot_patchlevel =
+ kmr_hal::env::extract_patchlevel(&boot_patchlevel_prop).unwrap_or(19700919);
+
+ kmr_wire::SetBootInfoRequest {
+ verified_boot_key,
+ device_boot_locked,
+ verified_boot_state,
+ verified_boot_hash,
+ boot_patchlevel,
+ }
+}
diff --git a/security/keymint/aidl/default/main.rs b/security/keymint/aidl/default/main.rs
new file mode 100644
index 0000000..ea432d1
--- /dev/null
+++ b/security/keymint/aidl/default/main.rs
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! Default implementation of the KeyMint HAL and related HALs.
+//!
+//! This implementation of the HAL is only intended to allow testing and policy compliance. A real
+//! implementation **must be implemented in a secure environment**.
+
+use kmr_hal::SerializedChannel;
+use kmr_hal_nonsecure::{attestation_id_info, get_boot_info};
+use log::{debug, error, info};
+use std::ops::DerefMut;
+use std::sync::{mpsc, Arc, Mutex};
+
+/// Name of KeyMint binder device instance.
+static SERVICE_INSTANCE: &str = "default";
+
+static KM_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
+static RPC_SERVICE_NAME: &str = "android.hardware.security.keymint.IRemotelyProvisionedComponent";
+static CLOCK_SERVICE_NAME: &str = "android.hardware.security.secureclock.ISecureClock";
+static SECRET_SERVICE_NAME: &str = "android.hardware.security.sharedsecret.ISharedSecret";
+
+/// Local error type for failures in the HAL service.
+#[derive(Debug, Clone)]
+struct HalServiceError(String);
+
+impl From<String> for HalServiceError {
+ fn from(s: String) -> Self {
+ Self(s)
+ }
+}
+
+fn main() {
+ if let Err(e) = inner_main() {
+ panic!("HAL service failed: {:?}", e);
+ }
+}
+
+fn inner_main() -> Result<(), HalServiceError> {
+ // Initialize Android logging.
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("keymint-hal-nonsecure")
+ .with_max_level(log::LevelFilter::Info)
+ .with_log_buffer(android_logger::LogId::System),
+ );
+ // Redirect panic messages to logcat.
+ std::panic::set_hook(Box::new(|panic_info| {
+ error!("{}", panic_info);
+ }));
+
+ info!("Insecure KeyMint HAL service is starting.");
+
+ info!("Starting thread pool now.");
+ binder::ProcessState::start_thread_pool();
+
+ // Create a TA in-process, which acts as a local channel for communication.
+ let channel = Arc::new(Mutex::new(LocalTa::new()));
+
+ let km_service = kmr_hal::keymint::Device::new_as_binder(channel.clone());
+ let service_name = format!("{}/{}", KM_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&service_name, km_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ service_name, e
+ ))
+ })?;
+
+ let rpc_service = kmr_hal::rpc::Device::new_as_binder(channel.clone());
+ let service_name = format!("{}/{}", RPC_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&service_name, rpc_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ service_name, e
+ ))
+ })?;
+
+ let clock_service = kmr_hal::secureclock::Device::new_as_binder(channel.clone());
+ let service_name = format!("{}/{}", CLOCK_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&service_name, clock_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ service_name, e
+ ))
+ })?;
+
+ let secret_service = kmr_hal::sharedsecret::Device::new_as_binder(channel.clone());
+ let service_name = format!("{}/{}", SECRET_SERVICE_NAME, SERVICE_INSTANCE);
+ binder::add_service(&service_name, secret_service.as_binder()).map_err(|e| {
+ HalServiceError(format!(
+ "Failed to register service {} because of {:?}.",
+ service_name, e
+ ))
+ })?;
+
+ info!("Successfully registered KeyMint HAL services.");
+
+ // Let the TA know information about the boot environment. In a real device this
+ // is communicated directly from the bootloader to the TA, but here we retrieve
+ // the information from system properties and send from the HAL service.
+ let boot_req = get_boot_info();
+ debug!("boot/HAL->TA: boot info is {:?}", boot_req);
+ kmr_hal::send_boot_info(channel.lock().unwrap().deref_mut(), boot_req)
+ .map_err(|e| HalServiceError(format!("Failed to send boot info: {:?}", e)))?;
+
+ // Let the TA know information about the userspace environment.
+ if let Err(e) = kmr_hal::send_hal_info(channel.lock().unwrap().deref_mut()) {
+ error!("Failed to send HAL info: {:?}", e);
+ }
+
+ // Let the TA know about attestation IDs. (In a real device these would be pre-provisioned into
+ // the TA.)
+ let attest_ids = attestation_id_info();
+ if let Err(e) = kmr_hal::send_attest_ids(channel.lock().unwrap().deref_mut(), attest_ids) {
+ error!("Failed to send attestation ID info: {:?}", e);
+ }
+
+ info!("Successfully registered KeyMint HAL services.");
+ binder::ProcessState::join_thread_pool();
+ info!("KeyMint HAL service is terminating."); // should not reach here
+ Ok(())
+}
+
+/// Implementation of the KeyMint TA that runs locally in-process (and which is therefore
+/// insecure).
+#[derive(Debug)]
+pub struct LocalTa {
+ in_tx: mpsc::Sender<Vec<u8>>,
+ out_rx: mpsc::Receiver<Vec<u8>>,
+}
+
+impl LocalTa {
+ /// Create a new instance.
+ pub fn new() -> Self {
+ // Create a pair of channels to communicate with the TA thread.
+ let (in_tx, in_rx) = mpsc::channel();
+ let (out_tx, out_rx) = mpsc::channel();
+
+ // The TA code expects to run single threaded, so spawn a thread to run it in.
+ std::thread::spawn(move || {
+ let mut ta = kmr_ta_nonsecure::build_ta();
+ loop {
+ let req_data: Vec<u8> = in_rx.recv().expect("failed to receive next req");
+ let rsp_data = ta.process(&req_data);
+ out_tx.send(rsp_data).expect("failed to send out rsp");
+ }
+ });
+ Self { in_tx, out_rx }
+ }
+}
+
+impl SerializedChannel for LocalTa {
+ const MAX_SIZE: usize = usize::MAX;
+
+ fn execute(&mut self, req_data: &[u8]) -> binder::Result<Vec<u8>> {
+ self.in_tx
+ .send(req_data.to_vec())
+ .expect("failed to send in request");
+ Ok(self.out_rx.recv().expect("failed to receive response"))
+ }
+}
diff --git a/security/keymint/aidl/default/ta/attest.rs b/security/keymint/aidl/default/ta/attest.rs
new file mode 100644
index 0000000..1ce2066
--- /dev/null
+++ b/security/keymint/aidl/default/ta/attest.rs
@@ -0,0 +1,425 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Attestation keys and certificates.
+//!
+//! Hard-coded keys and certs copied from system/keymaster/context/soft_attestation_cert.cpp
+
+use kmr_common::{
+ crypto::ec, crypto::rsa, crypto::CurveType, crypto::KeyMaterial, wire::keymint,
+ wire::keymint::EcCurve, Error,
+};
+use kmr_ta::device::{RetrieveCertSigningInfo, SigningAlgorithm, SigningKeyType};
+
+/// RSA attestation private key in PKCS#1 format.
+///
+/// Decoded contents (using [der2ascii](https://github.com/google/der-ascii)):
+///
+/// ```
+/// SEQUENCE {
+/// INTEGER { 0 }
+/// INTEGER { `00c08323dc56881bb8302069f5b08561c6eebe7f05e2f5a842048abe8b47be76feaef25cf29b2afa3200141601429989a15fcfc6815eb363583c2fd2f20be4983283dd814b16d7e185417ae54abc296a3a6db5c004083b68c556c1f02339916419864d50b74d40aeca484c77356c895a0c275abfac499d5d7d2362f29c5e02e871` }
+/// INTEGER { 65537 }
+/// INTEGER { `00be860b0b99a802a6fb1a59438a7bb715065b09a36dc6e9cacc6bf3c02c34d7d79e94c6606428d88c7b7f6577c1cdea64074abe8e7286df1f0811dc9728260868de95d32efc96b6d084ff271a5f60defcc703e7a38e6e29ba9a3c5fc2c28076b6a896af1d34d78828ce9bddb1f34f9c9404430781298e201316725bbdbc993a41` }
+/// INTEGER { `00e1c6d927646c0916ec36826d594983740c21f1b074c4a1a59867c669795c85d3dc464c5b929e94bfb34e0dcc5014b10f13341ab7fdd5f60414d2a326cad41cc5` }
+/// INTEGER { `00da485997785cd5630fb0fd8c5254f98e538e18983aae9e6b7e6a5a7b5d343755b9218ebd40320d28387d789f76fa218bcc2d8b68a5f6418fbbeca5179ab3afbd` }
+/// INTEGER { `50fefc32649559616ed6534e154509329d93a3d810dbe5bdb982292cf78bd8badb8020ae8d57f4b71d05386ffe9e9db271ca3477a34999db76f8e5ece9c0d49d` }
+/// INTEGER { `15b74cf27cceff8bb36bf04d9d8346b09a2f70d2f4439b0f26ac7e03f7e9d1f77d4b915fd29b2823f03acb5d5200e0857ff2a803e93eee96d6235ce95442bc21` }
+/// INTEGER { `0090a745da8970b2cd649660324228c5f82856ffd665ba9a85c8d60f1b8bee717ecd2c72eae01dad86ba7654d4cf45adb5f1f2b31d9f8122cfa5f1a5570f9b2d25` }
+/// }
+/// ```
+const RSA_ATTEST_KEY: &str = concat!(
+ "3082025d02010002818100c08323dc56881bb8302069f5b08561c6eebe7f05e2",
+ "f5a842048abe8b47be76feaef25cf29b2afa3200141601429989a15fcfc6815e",
+ "b363583c2fd2f20be4983283dd814b16d7e185417ae54abc296a3a6db5c00408",
+ "3b68c556c1f02339916419864d50b74d40aeca484c77356c895a0c275abfac49",
+ "9d5d7d2362f29c5e02e871020301000102818100be860b0b99a802a6fb1a5943",
+ "8a7bb715065b09a36dc6e9cacc6bf3c02c34d7d79e94c6606428d88c7b7f6577",
+ "c1cdea64074abe8e7286df1f0811dc9728260868de95d32efc96b6d084ff271a",
+ "5f60defcc703e7a38e6e29ba9a3c5fc2c28076b6a896af1d34d78828ce9bddb1",
+ "f34f9c9404430781298e201316725bbdbc993a41024100e1c6d927646c0916ec",
+ "36826d594983740c21f1b074c4a1a59867c669795c85d3dc464c5b929e94bfb3",
+ "4e0dcc5014b10f13341ab7fdd5f60414d2a326cad41cc5024100da485997785c",
+ "d5630fb0fd8c5254f98e538e18983aae9e6b7e6a5a7b5d343755b9218ebd4032",
+ "0d28387d789f76fa218bcc2d8b68a5f6418fbbeca5179ab3afbd024050fefc32",
+ "649559616ed6534e154509329d93a3d810dbe5bdb982292cf78bd8badb8020ae",
+ "8d57f4b71d05386ffe9e9db271ca3477a34999db76f8e5ece9c0d49d024015b7",
+ "4cf27cceff8bb36bf04d9d8346b09a2f70d2f4439b0f26ac7e03f7e9d1f77d4b",
+ "915fd29b2823f03acb5d5200e0857ff2a803e93eee96d6235ce95442bc210241",
+ "0090a745da8970b2cd649660324228c5f82856ffd665ba9a85c8d60f1b8bee71",
+ "7ecd2c72eae01dad86ba7654d4cf45adb5f1f2b31d9f8122cfa5f1a5570f9b2d",
+ "25",
+);
+
+/// Attestation certificate corresponding to [`RSA_ATTEST_KEY`], signed by the key in
+/// [`RSA_ATTEST_ROOT_CERT`].
+///
+/// Decoded contents:
+///
+/// ```
+/// Certificate:
+/// Data:
+/// Version: 3 (0x2)
+/// Serial Number: 4096 (0x1000)
+/// Signature Algorithm: SHA256-RSA
+/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California
+/// Validity:
+/// Not Before: 2016-01-04 12:40:53 +0000 UTC
+/// Not After : 2035-12-30 12:40:53 +0000 UTC
+/// Subject: C=US, O=Google, Inc., OU=Android, ST=California, CN=Android Software Attestation Key
+/// Subject Public Key Info:
+/// Public Key Algorithm: rsaEncryption
+/// Public Key: (1024 bit)
+/// Modulus:
+/// c0:83:23:dc:56:88:1b:b8:30:20:69:f5:b0:85:61:
+/// c6:ee:be:7f:05:e2:f5:a8:42:04:8a:be:8b:47:be:
+/// 76:fe:ae:f2:5c:f2:9b:2a:fa:32:00:14:16:01:42:
+/// 99:89:a1:5f:cf:c6:81:5e:b3:63:58:3c:2f:d2:f2:
+/// 0b:e4:98:32:83:dd:81:4b:16:d7:e1:85:41:7a:e5:
+/// 4a:bc:29:6a:3a:6d:b5:c0:04:08:3b:68:c5:56:c1:
+/// f0:23:39:91:64:19:86:4d:50:b7:4d:40:ae:ca:48:
+/// 4c:77:35:6c:89:5a:0c:27:5a:bf:ac:49:9d:5d:7d:
+/// 23:62:f2:9c:5e:02:e8:71:
+/// Exponent: 65537 (0x10001)
+/// X509v3 extensions:
+/// X509v3 Authority Key Identifier:
+/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e
+/// X509v3 Subject Key Identifier:
+/// keyid:d40c101bf8cd63b9f73952b50e135ca6d7999386
+/// X509v3 Key Usage: critical
+/// Digital Signature, Certificate Signing
+/// X509v3 Basic Constraints: critical
+/// CA:true, pathlen:0
+/// Signature Algorithm: SHA256-RSA
+/// 9e:2d:48:5f:8c:67:33:dc:1a:85:ad:99:d7:50:23:ea:14:ec:
+/// 43:b0:e1:9d:ea:c2:23:46:1e:72:b5:19:dc:60:22:e4:a5:68:
+/// 31:6c:0b:55:c4:e6:9c:a2:2d:9f:3a:4f:93:6b:31:8b:16:78:
+/// 16:0d:88:cb:d9:8b:cc:80:9d:84:f0:c2:27:e3:6b:38:f1:fd:
+/// d1:e7:17:72:31:59:35:7d:96:f3:c5:7f:ab:9d:8f:96:61:26:
+/// 4f:b2:be:81:bb:0d:49:04:22:8a:ce:9f:f7:f5:42:2e:25:44:
+/// fa:21:07:12:5a:83:b5:55:ad:18:82:f8:40:14:9b:9c:20:63:
+/// 04:7f:
+/// ```
+const RSA_ATTEST_CERT: &str = concat!(
+ "308202b63082021fa00302010202021000300d06092a864886f70d01010b0500",
+ "3063310b30090603550406130255533113301106035504080c0a43616c69666f",
+ "726e69613116301406035504070c0d4d6f756e7461696e205669657731153013",
+ "060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e",
+ "64726f6964301e170d3136303130343132343035335a170d3335313233303132",
+ "343035335a3076310b30090603550406130255533113301106035504080c0a43",
+ "616c69666f726e696131153013060355040a0c0c476f6f676c652c20496e632e",
+ "3110300e060355040b0c07416e64726f69643129302706035504030c20416e64",
+ "726f696420536f667477617265204174746573746174696f6e204b657930819f",
+ "300d06092a864886f70d010101050003818d0030818902818100c08323dc5688",
+ "1bb8302069f5b08561c6eebe7f05e2f5a842048abe8b47be76feaef25cf29b2a",
+ "fa3200141601429989a15fcfc6815eb363583c2fd2f20be4983283dd814b16d7",
+ "e185417ae54abc296a3a6db5c004083b68c556c1f02339916419864d50b74d40",
+ "aeca484c77356c895a0c275abfac499d5d7d2362f29c5e02e8710203010001a3",
+ "663064301d0603551d0e04160414d40c101bf8cd63b9f73952b50e135ca6d799",
+ "9386301f0603551d2304183016801429faf1accc4dd24c96402775b6b0e932e5",
+ "07fe2e30120603551d130101ff040830060101ff020100300e0603551d0f0101",
+ "ff040403020284300d06092a864886f70d01010b0500038181009e2d485f8c67",
+ "33dc1a85ad99d75023ea14ec43b0e19deac223461e72b519dc6022e4a568316c",
+ "0b55c4e69ca22d9f3a4f936b318b1678160d88cbd98bcc809d84f0c227e36b38",
+ "f1fdd1e717723159357d96f3c57fab9d8f9661264fb2be81bb0d4904228ace9f",
+ "f7f5422e2544fa2107125a83b555ad1882f840149b9c2063047f",
+);
+
+/// Attestation self-signed root certificate holding the key that signed [`RSA_ATTEST_CERT`].
+///
+/// Decoded contents:
+///
+/// ```
+/// Certificate:
+/// Data:
+/// Version: 3 (0x2)
+/// Serial Number: 18416584322103887884 (0xff94d9dd9f07c80c)
+/// Signature Algorithm: SHA256-RSA
+/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California
+/// Validity:
+/// Not Before: 2016-01-04 12:31:08 +0000 UTC
+/// Not After : 2035-12-30 12:31:08 +0000 UTC
+/// Subject: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California
+/// Subject Public Key Info:
+/// Public Key Algorithm: rsaEncryption
+/// Public Key: (1024 bit)
+/// Modulus:
+/// a2:6b:ad:eb:6e:2e:44:61:ef:d5:0e:82:e6:b7:94:
+/// d1:75:23:1f:77:9b:63:91:63:ff:f7:aa:ff:0b:72:
+/// 47:4e:c0:2c:43:ec:33:7c:d7:ac:ed:40:3e:8c:28:
+/// a0:66:d5:f7:87:0b:33:97:de:0e:b8:4e:13:40:ab:
+/// af:a5:27:bf:95:69:a0:31:db:06:52:65:f8:44:59:
+/// 57:61:f0:bb:f2:17:4b:b7:41:80:64:c0:28:0e:8f:
+/// 52:77:8e:db:d2:47:b6:45:e9:19:c8:e9:8b:c3:db:
+/// c2:91:3f:d7:d7:50:c4:1d:35:66:f9:57:e4:97:96:
+/// 0b:09:ac:ce:92:35:85:9b:
+/// Exponent: 65537 (0x10001)
+/// X509v3 extensions:
+/// X509v3 Authority Key Identifier:
+/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e
+/// X509v3 Subject Key Identifier:
+/// keyid:29faf1accc4dd24c96402775b6b0e932e507fe2e
+/// X509v3 Key Usage: critical
+/// Digital Signature, Certificate Signing
+/// X509v3 Basic Constraints: critical
+/// CA:true
+/// Signature Algorithm: SHA256-RSA
+/// 4f:72:f3:36:59:8d:0e:c1:b9:74:5b:31:59:f6:f0:8d:25:49:
+/// 30:9e:a3:1c:1c:29:d2:45:2d:20:b9:4d:5f:64:b4:e8:80:c7:
+/// 78:7a:9c:39:de:a8:b3:f5:bf:2f:70:5f:47:10:5c:c5:e6:eb:
+/// 4d:06:99:61:d2:ae:9a:07:ff:f7:7c:b8:ab:eb:9c:0f:24:07:
+/// 5e:b1:7f:ba:79:71:fd:4d:5b:9e:df:14:a9:fe:df:ed:7c:c0:
+/// 88:5d:f8:dd:9b:64:32:56:d5:35:9a:e2:13:f9:8f:ce:c1:7c:
+/// dc:ef:a4:aa:b2:55:c3:83:a9:2e:fb:5c:f6:62:f5:27:52:17:
+/// be:63:
+/// ```
+const RSA_ATTEST_ROOT_CERT: &str = concat!(
+ "308202a730820210a003020102020900ff94d9dd9f07c80c300d06092a864886",
+ "f70d01010b05003063310b30090603550406130255533113301106035504080c",
+ "0a43616c69666f726e69613116301406035504070c0d4d6f756e7461696e2056",
+ "69657731153013060355040a0c0c476f6f676c652c20496e632e3110300e0603",
+ "55040b0c07416e64726f6964301e170d3136303130343132333130385a170d33",
+ "35313233303132333130385a3063310b30090603550406130255533113301106",
+ "035504080c0a43616c69666f726e69613116301406035504070c0d4d6f756e74",
+ "61696e205669657731153013060355040a0c0c476f6f676c652c20496e632e31",
+ "10300e060355040b0c07416e64726f696430819f300d06092a864886f70d0101",
+ "01050003818d0030818902818100a26badeb6e2e4461efd50e82e6b794d17523",
+ "1f779b639163fff7aaff0b72474ec02c43ec337cd7aced403e8c28a066d5f787",
+ "0b3397de0eb84e1340abafa527bf9569a031db065265f844595761f0bbf2174b",
+ "b7418064c0280e8f52778edbd247b645e919c8e98bc3dbc2913fd7d750c41d35",
+ "66f957e497960b09acce9235859b0203010001a3633061301d0603551d0e0416",
+ "041429faf1accc4dd24c96402775b6b0e932e507fe2e301f0603551d23041830",
+ "16801429faf1accc4dd24c96402775b6b0e932e507fe2e300f0603551d130101",
+ "ff040530030101ff300e0603551d0f0101ff040403020284300d06092a864886",
+ "f70d01010b0500038181004f72f336598d0ec1b9745b3159f6f08d2549309ea3",
+ "1c1c29d2452d20b94d5f64b4e880c7787a9c39dea8b3f5bf2f705f47105cc5e6",
+ "eb4d069961d2ae9a07fff77cb8abeb9c0f24075eb17fba7971fd4d5b9edf14a9",
+ "fedfed7cc0885df8dd9b643256d5359ae213f98fcec17cdcefa4aab255c383a9",
+ "2efb5cf662f5275217be63",
+);
+
+/// EC attestation private key in `ECPrivateKey` format.
+///
+/// Decoded contents (using [der2ascii](https://github.com/google/der-ascii)):
+///
+/// ```
+/// SEQUENCE {
+/// INTEGER { 1 }
+/// OCTET_STRING { `21e086432a15198459cf363a50fc14c9daadf935f527c2dfd71e4d6dbc42e544` }
+/// [0] {
+/// # secp256r1
+/// OBJECT_IDENTIFIER { 1.2.840.10045.3.1.7 }
+/// }
+/// [1] {
+/// BIT_STRING { `00` `04eb9e79f8426359accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174974a2afea5b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014` }
+/// }
+/// }
+/// ```
+const EC_ATTEST_KEY: &str = concat!(
+ "3077020101042021e086432a15198459cf363a50fc14c9daadf935f527c2dfd7",
+ "1e4d6dbc42e544a00a06082a8648ce3d030107a14403420004eb9e79f8426359",
+ "accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174974a2afea5",
+ "b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014",
+);
+
+/// Attestation certificate corresponding to [`EC_ATTEST_KEY`], signed by the key in
+/// [`EC_ATTEST_ROOT_CERT`].
+///
+/// Decoded contents:
+///
+/// ```
+/// Certificate:
+/// Data:
+/// Version: 3 (0x2)
+/// Serial Number: 4097 (0x1001)
+/// Signature Algorithm: ECDSA-SHA256
+/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root
+/// Validity:
+/// Not Before: 2016-01-11 00:46:09 +0000 UTC
+/// Not After : 2026-01-08 00:46:09 +0000 UTC
+/// Subject: C=US, O=Google, Inc., OU=Android, ST=California, CN=Android Keystore Software Attestation Intermediate
+/// Subject Public Key Info:
+/// Public Key Algorithm: id-ecPublicKey
+/// Public Key: (256 bit)
+/// pub:
+/// 04:eb:9e:79:f8:42:63:59:ac:cb:2a:91:4c:89:86:
+/// cc:70:ad:90:66:93:82:a9:73:26:13:fe:ac:cb:f8:
+/// 21:27:4c:21:74:97:4a:2a:fe:a5:b9:4d:7f:66:d4:
+/// e0:65:10:66:35:bc:53:b7:a0:a3:a6:71:58:3e:db:
+/// 3e:11:ae:10:14:
+/// ASN1 OID: prime256v1
+/// X509v3 extensions:
+/// X509v3 Authority Key Identifier:
+/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf
+/// X509v3 Subject Key Identifier:
+/// keyid:3ffcacd61ab13a9e8120b8d5251cc565bb1e91a9
+/// X509v3 Key Usage: critical
+/// Digital Signature, Certificate Signing
+/// X509v3 Basic Constraints: critical
+/// CA:true, pathlen:0
+/// Signature Algorithm: ECDSA-SHA256
+/// 30:45:02:20:4b:8a:9b:7b:ee:82:bc:c0:33:87:ae:2f:c0:89:
+/// 98:b4:dd:c3:8d:ab:27:2a:45:9f:69:0c:c7:c3:92:d4:0f:8e:
+/// 02:21:00:ee:da:01:5d:b6:f4:32:e9:d4:84:3b:62:4c:94:04:
+/// ef:3a:7c:cc:bd:5e:fb:22:bb:e7:fe:b9:77:3f:59:3f:fb:
+/// ```
+const EC_ATTEST_CERT: &str = concat!(
+ "308202783082021ea00302010202021001300a06082a8648ce3d040302308198",
+ "310b30090603550406130255533113301106035504080c0a43616c69666f726e",
+ "69613116301406035504070c0d4d6f756e7461696e2056696577311530130603",
+ "55040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e6472",
+ "6f69643133303106035504030c2a416e64726f6964204b657973746f72652053",
+ "6f667477617265204174746573746174696f6e20526f6f74301e170d31363031",
+ "31313030343630395a170d3236303130383030343630395a308188310b300906",
+ "03550406130255533113301106035504080c0a43616c69666f726e6961311530",
+ "13060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c0741",
+ "6e64726f6964313b303906035504030c32416e64726f6964204b657973746f72",
+ "6520536f667477617265204174746573746174696f6e20496e7465726d656469",
+ "6174653059301306072a8648ce3d020106082a8648ce3d03010703420004eb9e",
+ "79f8426359accb2a914c8986cc70ad90669382a9732613feaccbf821274c2174",
+ "974a2afea5b94d7f66d4e065106635bc53b7a0a3a671583edb3e11ae1014a366",
+ "3064301d0603551d0e041604143ffcacd61ab13a9e8120b8d5251cc565bb1e91",
+ "a9301f0603551d23041830168014c8ade9774c45c3a3cf0d1610e479433a215a",
+ "30cf30120603551d130101ff040830060101ff020100300e0603551d0f0101ff",
+ "040403020284300a06082a8648ce3d040302034800304502204b8a9b7bee82bc",
+ "c03387ae2fc08998b4ddc38dab272a459f690cc7c392d40f8e022100eeda015d",
+ "b6f432e9d4843b624c9404ef3a7cccbd5efb22bbe7feb9773f593ffb",
+);
+
+/// Attestation self-signed root certificate holding the key that signed [`EC_ATTEST_CERT`].
+///
+/// Decoded contents:
+///
+/// ```
+/// Certificate:
+/// Data:
+/// Version: 3 (0x2)
+/// Serial Number: 11674912229752527703 (0xa2059ed10e435b57)
+/// Signature Algorithm: ECDSA-SHA256
+/// Issuer: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root
+/// Validity:
+/// Not Before: 2016-01-11 00:43:50 +0000 UTC
+/// Not After : 2036-01-06 00:43:50 +0000 UTC
+/// Subject: C=US, O=Google, Inc., OU=Android, L=Mountain View, ST=California, CN=Android Keystore Software Attestation Root
+/// Subject Public Key Info:
+/// Public Key Algorithm: id-ecPublicKey
+/// Public Key: (256 bit)
+/// pub:
+/// 04:ee:5d:5e:c7:e1:c0:db:6d:03:a6:7e:e6:b6:1b:
+/// ec:4d:6a:5d:6a:68:2e:0f:ff:7f:49:0e:7d:77:1f:
+/// 44:22:6d:bd:b1:af:fa:16:cb:c7:ad:c5:77:d2:56:
+/// 9c:aa:b7:b0:2d:54:01:5d:3e:43:2b:2a:8e:d7:4e:
+/// ec:48:75:41:a4:
+/// ASN1 OID: prime256v1
+/// X509v3 extensions:
+/// X509v3 Authority Key Identifier:
+/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf
+/// X509v3 Subject Key Identifier:
+/// keyid:c8ade9774c45c3a3cf0d1610e479433a215a30cf
+/// X509v3 Key Usage: critical
+/// Digital Signature, Certificate Signing
+/// X509v3 Basic Constraints: critical
+/// CA:true
+/// Signature Algorithm: ECDSA-SHA256
+/// 30:44:02:20:35:21:a3:ef:8b:34:46:1e:9c:d5:60:f3:1d:58:
+/// 89:20:6a:dc:a3:65:41:f6:0d:9e:ce:8a:19:8c:66:48:60:7b:
+/// 02:20:4d:0b:f3:51:d9:30:7c:7d:5b:da:35:34:1d:a8:47:1b:
+/// 63:a5:85:65:3c:ad:4f:24:a7:e7:4d:af:41:7d:f1:bf:
+/// ```
+const EC_ATTEST_ROOT_CERT: &str = concat!(
+ "3082028b30820232a003020102020900a2059ed10e435b57300a06082a8648ce",
+ "3d040302308198310b30090603550406130255533113301106035504080c0a43",
+ "616c69666f726e69613116301406035504070c0d4d6f756e7461696e20566965",
+ "7731153013060355040a0c0c476f6f676c652c20496e632e3110300e06035504",
+ "0b0c07416e64726f69643133303106035504030c2a416e64726f6964204b6579",
+ "73746f726520536f667477617265204174746573746174696f6e20526f6f7430",
+ "1e170d3136303131313030343335305a170d3336303130363030343335305a30",
+ "8198310b30090603550406130255533113301106035504080c0a43616c69666f",
+ "726e69613116301406035504070c0d4d6f756e7461696e205669657731153013",
+ "060355040a0c0c476f6f676c652c20496e632e3110300e060355040b0c07416e",
+ "64726f69643133303106035504030c2a416e64726f6964204b657973746f7265",
+ "20536f667477617265204174746573746174696f6e20526f6f74305930130607",
+ "2a8648ce3d020106082a8648ce3d03010703420004ee5d5ec7e1c0db6d03a67e",
+ "e6b61bec4d6a5d6a682e0fff7f490e7d771f44226dbdb1affa16cbc7adc577d2",
+ "569caab7b02d54015d3e432b2a8ed74eec487541a4a3633061301d0603551d0e",
+ "04160414c8ade9774c45c3a3cf0d1610e479433a215a30cf301f0603551d2304",
+ "1830168014c8ade9774c45c3a3cf0d1610e479433a215a30cf300f0603551d13",
+ "0101ff040530030101ff300e0603551d0f0101ff040403020284300a06082a86",
+ "48ce3d040302034700304402203521a3ef8b34461e9cd560f31d5889206adca3",
+ "6541f60d9ece8a198c6648607b02204d0bf351d9307c7d5bda35341da8471b63",
+ "a585653cad4f24a7e74daf417df1bf",
+);
+
+/// Per-algorithm attestation certificate signing information.
+pub struct CertSignAlgoInfo {
+ key: KeyMaterial,
+ chain: Vec<keymint::Certificate>,
+}
+
+/// Certificate signing information for all asymmetric key types.
+pub struct CertSignInfo {
+ rsa_info: CertSignAlgoInfo,
+ ec_info: CertSignAlgoInfo,
+}
+
+impl CertSignInfo {
+ /// Create a new cert signing impl.
+ pub fn new() -> Self {
+ CertSignInfo {
+ rsa_info: CertSignAlgoInfo {
+ key: KeyMaterial::Rsa(rsa::Key(hex::decode(RSA_ATTEST_KEY).unwrap()).into()),
+ chain: vec![
+ keymint::Certificate {
+ encoded_certificate: hex::decode(RSA_ATTEST_CERT).unwrap(),
+ },
+ keymint::Certificate {
+ encoded_certificate: hex::decode(RSA_ATTEST_ROOT_CERT).unwrap(),
+ },
+ ],
+ },
+ ec_info: CertSignAlgoInfo {
+ key: KeyMaterial::Ec(
+ EcCurve::P256,
+ CurveType::Nist,
+ ec::Key::P256(ec::NistKey(hex::decode(EC_ATTEST_KEY).unwrap())).into(),
+ ),
+ chain: vec![
+ keymint::Certificate {
+ encoded_certificate: hex::decode(EC_ATTEST_CERT).unwrap(),
+ },
+ keymint::Certificate {
+ encoded_certificate: hex::decode(EC_ATTEST_ROOT_CERT).unwrap(),
+ },
+ ],
+ },
+ }
+ }
+}
+
+impl RetrieveCertSigningInfo for CertSignInfo {
+ fn signing_key(&self, key_type: SigningKeyType) -> Result<KeyMaterial, Error> {
+ Ok(match key_type.algo_hint {
+ SigningAlgorithm::Rsa => self.rsa_info.key.clone(),
+ SigningAlgorithm::Ec => self.ec_info.key.clone(),
+ })
+ }
+
+ fn cert_chain(&self, key_type: SigningKeyType) -> Result<Vec<keymint::Certificate>, Error> {
+ Ok(match key_type.algo_hint {
+ SigningAlgorithm::Rsa => self.rsa_info.chain.clone(),
+ SigningAlgorithm::Ec => self.ec_info.chain.clone(),
+ })
+ }
+}
diff --git a/security/keymint/aidl/default/ta/clock.rs b/security/keymint/aidl/default/ta/clock.rs
new file mode 100644
index 0000000..ad8509a
--- /dev/null
+++ b/security/keymint/aidl/default/ta/clock.rs
@@ -0,0 +1,40 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Monotonic clock implementation.
+
+use kmr_common::crypto;
+use std::time::Instant;
+
+/// Monotonic clock.
+pub struct StdClock {
+ start: Instant,
+}
+
+impl StdClock {
+ /// Create new clock instance, holding time since construction.
+ pub fn new() -> Self {
+ Self {
+ start: Instant::now(),
+ }
+ }
+}
+
+impl crypto::MonotonicClock for StdClock {
+ fn now(&self) -> crypto::MillisecondsSinceEpoch {
+ let duration = self.start.elapsed();
+ crypto::MillisecondsSinceEpoch(duration.as_millis().try_into().unwrap())
+ }
+}
diff --git a/security/keymint/aidl/default/ta/lib.rs b/security/keymint/aidl/default/ta/lib.rs
new file mode 100644
index 0000000..fe8ad95
--- /dev/null
+++ b/security/keymint/aidl/default/ta/lib.rs
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! Local in-process implementation of the KeyMint TA. This is insecure and should
+//! only be used for testing purposes.
+
+// This crate is `std` using, but some of the code uses macros from a `no_std` world.
+extern crate alloc;
+
+use kmr_common::crypto;
+use kmr_crypto_boring::{
+ aes::BoringAes, aes_cmac::BoringAesCmac, des::BoringDes, ec::BoringEc, eq::BoringEq,
+ hmac::BoringHmac, rng::BoringRng, rsa::BoringRsa, sha256::BoringSha256,
+};
+use kmr_ta::device::{
+ BootloaderDone, CsrSigningAlgorithm, Implementation, TrustedPresenceUnsupported,
+};
+use kmr_ta::{HardwareInfo, KeyMintTa, RpcInfo, RpcInfoV3};
+use kmr_wire::keymint::SecurityLevel;
+use kmr_wire::rpc::MINIMUM_SUPPORTED_KEYS_IN_CSR;
+use log::info;
+
+pub mod attest;
+pub mod clock;
+pub mod rpc;
+pub mod soft;
+
+/// Build a set of crypto trait implementations based around BoringSSL and the standard library
+/// clock.
+pub fn boringssl_crypto_impls() -> crypto::Implementation {
+ let rng = BoringRng;
+ let clock = clock::StdClock::new();
+ let rsa = BoringRsa::default();
+ let ec = BoringEc::default();
+ crypto::Implementation {
+ rng: Box::new(rng),
+ clock: Some(Box::new(clock)),
+ compare: Box::new(BoringEq),
+ aes: Box::new(BoringAes),
+ des: Box::new(BoringDes),
+ hmac: Box::new(BoringHmac),
+ rsa: Box::new(rsa),
+ ec: Box::new(ec),
+ ckdf: Box::new(BoringAesCmac),
+ hkdf: Box::new(BoringHmac),
+ sha256: Box::new(BoringSha256),
+ }
+}
+
+/// Build a [`kmr_ta::KeyMintTa`] instance for nonsecure use.
+pub fn build_ta() -> kmr_ta::KeyMintTa {
+ info!("Building NON-SECURE KeyMint Rust TA");
+ let hw_info = HardwareInfo {
+ version_number: 1,
+ security_level: SecurityLevel::TrustedEnvironment,
+ impl_name: "Rust reference implementation",
+ author_name: "Google",
+ unique_id: "NON-SECURE KeyMint TA",
+ };
+ let rpc_sign_algo = CsrSigningAlgorithm::EdDSA;
+ let rpc_info_v3 = RpcInfoV3 {
+ author_name: "Google",
+ unique_id: "NON-SECURE KeyMint TA",
+ fused: false,
+ supported_num_of_keys_in_csr: MINIMUM_SUPPORTED_KEYS_IN_CSR,
+ };
+
+ let sign_info = attest::CertSignInfo::new();
+ let keys: Box<dyn kmr_ta::device::RetrieveKeyMaterial> = Box::new(soft::Keys);
+ let rpc: Box<dyn kmr_ta::device::RetrieveRpcArtifacts> = Box::new(soft::RpcArtifacts::new(
+ soft::Derive::default(),
+ rpc_sign_algo,
+ ));
+ let dev = Implementation {
+ keys,
+ sign_info: Box::new(sign_info),
+ // HAL populates attestation IDs from properties.
+ attest_ids: None,
+ sdd_mgr: None,
+ // `BOOTLOADER_ONLY` keys not supported.
+ bootloader: Box::new(BootloaderDone),
+ // `STORAGE_KEY` keys not supported.
+ sk_wrapper: None,
+ // `TRUSTED_USER_PRESENCE_REQUIRED` keys not supported
+ tup: Box::new(TrustedPresenceUnsupported),
+ // No support for converting previous implementation's keyblobs.
+ legacy_key: None,
+ rpc,
+ };
+ KeyMintTa::new(
+ hw_info,
+ RpcInfo::V3(rpc_info_v3),
+ boringssl_crypto_impls(),
+ dev,
+ )
+}
diff --git a/security/keymint/aidl/default/ta/rpc.rs b/security/keymint/aidl/default/ta/rpc.rs
new file mode 100644
index 0000000..39da50e
--- /dev/null
+++ b/security/keymint/aidl/default/ta/rpc.rs
@@ -0,0 +1,234 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Emulated implementation of device traits for `IRemotelyProvisionedComponent`.
+
+use core::cell::RefCell;
+use kmr_common::crypto::{ec, ec::CoseKeyPurpose, Ec, KeyMaterial};
+use kmr_common::{crypto, explicit, rpc_err, vec_try, Error};
+use kmr_crypto_boring::{ec::BoringEc, hmac::BoringHmac, rng::BoringRng};
+use kmr_ta::device::{
+ CsrSigningAlgorithm, DiceInfo, PubDiceArtifacts, RetrieveRpcArtifacts, RpcV2Req,
+};
+use kmr_wire::coset::{iana, CoseSign1Builder, HeaderBuilder};
+use kmr_wire::keymint::{Digest, EcCurve};
+use kmr_wire::{cbor::value::Value, coset::AsCborValue, rpc, CborError};
+
+/// Trait to encapsulate deterministic derivation of secret data.
+pub trait DeriveBytes {
+ /// Derive `output_len` bytes of data from `context`, deterministically.
+ fn derive_bytes(&self, context: &[u8], output_len: usize) -> Result<Vec<u8>, Error>;
+}
+
+/// Common emulated implementation of RPC artifact retrieval.
+pub struct Artifacts<T: DeriveBytes> {
+ derive: T,
+ sign_algo: CsrSigningAlgorithm,
+ // Invariant once populated: `self.dice_info.signing_algorithm` == `self.sign_algo`
+ dice_info: RefCell<Option<DiceInfo>>,
+ // Invariant once populated: `self.bcc_signing_key` is a variant that matches `self.sign_algo`
+ bcc_signing_key: RefCell<Option<ec::Key>>,
+}
+
+impl<T: DeriveBytes> RetrieveRpcArtifacts for Artifacts<T> {
+ fn derive_bytes_from_hbk(
+ &self,
+ _hkdf: &dyn crypto::Hkdf,
+ context: &[u8],
+ output_len: usize,
+ ) -> Result<Vec<u8>, Error> {
+ self.derive.derive_bytes(context, output_len)
+ }
+
+ fn get_dice_info(&self, _test_mode: rpc::TestMode) -> Result<DiceInfo, Error> {
+ if self.dice_info.borrow().is_none() {
+ let (dice_info, priv_key) = self.generate_dice_artifacts(rpc::TestMode(false))?;
+ *self.dice_info.borrow_mut() = Some(dice_info);
+ *self.bcc_signing_key.borrow_mut() = Some(priv_key);
+ }
+
+ Ok(self
+ .dice_info
+ .borrow()
+ .as_ref()
+ .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))?
+ .clone())
+ }
+
+ fn sign_data(
+ &self,
+ ec: &dyn crypto::Ec,
+ data: &[u8],
+ _rpc_v2: Option<RpcV2Req>,
+ ) -> Result<Vec<u8>, Error> {
+ // DICE artifacts should have been initialized via `get_dice_info()` by the time this
+ // method is called.
+ let private_key = self
+ .bcc_signing_key
+ .borrow()
+ .as_ref()
+ .ok_or_else(|| rpc_err!(Failed, "DICE artifacts are not initialized."))?
+ .clone();
+
+ let mut op = ec.begin_sign(private_key.into(), self.signing_digest())?;
+ op.update(data)?;
+ let sig = op.finish()?;
+ crypto::ec::to_cose_signature(self.signing_curve(), sig)
+ }
+}
+
+impl<T: DeriveBytes> Artifacts<T> {
+ /// Constructor.
+ pub fn new(derive: T, sign_algo: CsrSigningAlgorithm) -> Self {
+ Self {
+ derive,
+ sign_algo,
+ dice_info: RefCell::new(None),
+ bcc_signing_key: RefCell::new(None),
+ }
+ }
+
+ /// Indicate the curve used in signing.
+ fn signing_curve(&self) -> EcCurve {
+ match self.sign_algo {
+ CsrSigningAlgorithm::ES256 => EcCurve::P256,
+ CsrSigningAlgorithm::ES384 => EcCurve::P384,
+ CsrSigningAlgorithm::EdDSA => EcCurve::Curve25519,
+ }
+ }
+
+ /// Indicate the digest used in signing.
+ fn signing_digest(&self) -> Digest {
+ match self.sign_algo {
+ CsrSigningAlgorithm::ES256 => Digest::Sha256,
+ CsrSigningAlgorithm::ES384 => Digest::Sha384,
+ CsrSigningAlgorithm::EdDSA => Digest::None,
+ }
+ }
+
+ /// Indicate the COSE algorithm value associated with signing.
+ fn signing_cose_algo(&self) -> iana::Algorithm {
+ match self.sign_algo {
+ CsrSigningAlgorithm::ES256 => iana::Algorithm::ES256,
+ CsrSigningAlgorithm::ES384 => iana::Algorithm::ES384,
+ CsrSigningAlgorithm::EdDSA => iana::Algorithm::EdDSA,
+ }
+ }
+
+ fn generate_dice_artifacts(
+ &self,
+ _test_mode: rpc::TestMode,
+ ) -> Result<(DiceInfo, ec::Key), Error> {
+ let ec = BoringEc::default();
+
+ let key_material = match self.sign_algo {
+ CsrSigningAlgorithm::EdDSA => {
+ let secret = self.derive_bytes_from_hbk(&BoringHmac, b"Device Key Seed", 32)?;
+ ec::import_raw_ed25519_key(&secret)
+ }
+ // TODO: generate the *same* key after reboot, by use of the TPM.
+ CsrSigningAlgorithm::ES256 => {
+ ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P256, &[])
+ }
+ CsrSigningAlgorithm::ES384 => {
+ ec.generate_nist_key(&mut BoringRng, ec::NistCurve::P384, &[])
+ }
+ }?;
+ let (pub_cose_key, private_key) = match key_material {
+ KeyMaterial::Ec(curve, curve_type, key) => (
+ key.public_cose_key(
+ &ec,
+ curve,
+ curve_type,
+ CoseKeyPurpose::Sign,
+ None, /* no key ID */
+ rpc::TestMode(false),
+ )?,
+ key,
+ ),
+ _ => {
+ return Err(rpc_err!(
+ Failed,
+ "expected the Ec variant of KeyMaterial for the cdi leaf key."
+ ))
+ }
+ };
+
+ let cose_key_cbor = pub_cose_key.to_cbor_value().map_err(CborError::from)?;
+ let cose_key_cbor_data = kmr_ta::rkp::serialize_cbor(&cose_key_cbor)?;
+
+ // Construct `DiceChainEntryPayload`
+ let dice_chain_entry_payload = Value::Map(vec_try![
+ // Issuer
+ (
+ Value::Integer(1.into()),
+ Value::Text(String::from("Issuer"))
+ ),
+ // Subject
+ (
+ Value::Integer(2.into()),
+ Value::Text(String::from("Subject"))
+ ),
+ // Subject public key
+ (
+ Value::Integer((-4670552).into()),
+ Value::Bytes(cose_key_cbor_data)
+ ),
+ // Key Usage field contains a CBOR byte string of the bits which correspond
+ // to `keyCertSign` as per RFC 5280 Section 4.2.1.3 (in little-endian byte order)
+ (
+ Value::Integer((-4670553).into()),
+ Value::Bytes(vec_try![0x20]?)
+ ),
+ ]?);
+ let dice_chain_entry_payload_data = kmr_ta::rkp::serialize_cbor(&dice_chain_entry_payload)?;
+
+ // Construct `DiceChainEntry`
+ let protected = HeaderBuilder::new()
+ .algorithm(self.signing_cose_algo())
+ .build();
+ let dice_chain_entry = CoseSign1Builder::new()
+ .protected(protected)
+ .payload(dice_chain_entry_payload_data)
+ .try_create_signature(&[], |input| {
+ let mut op = ec.begin_sign(private_key.clone(), self.signing_digest())?;
+ op.update(input)?;
+ let sig = op.finish()?;
+ crypto::ec::to_cose_signature(self.signing_curve(), sig)
+ })?
+ .build();
+ let dice_chain_entry_cbor = dice_chain_entry.to_cbor_value().map_err(CborError::from)?;
+
+ // Construct `DiceCertChain`
+ let dice_cert_chain = Value::Array(vec_try![cose_key_cbor, dice_chain_entry_cbor]?);
+ let dice_cert_chain_data = kmr_ta::rkp::serialize_cbor(&dice_cert_chain)?;
+
+ // Construct `UdsCerts` as an empty CBOR map
+ let uds_certs_data = kmr_ta::rkp::serialize_cbor(&Value::Map(Vec::new()))?;
+
+ let pub_dice_artifacts = PubDiceArtifacts {
+ dice_cert_chain: dice_cert_chain_data,
+ uds_certs: uds_certs_data,
+ };
+
+ let dice_info = DiceInfo {
+ pub_dice_artifacts,
+ signing_algorithm: self.sign_algo,
+ rpc_v2_test_cdi_priv: None,
+ };
+
+ Ok((dice_info, explicit!(private_key)?))
+ }
+}
diff --git a/security/keymint/aidl/default/ta/soft.rs b/security/keymint/aidl/default/ta/soft.rs
new file mode 100644
index 0000000..5bbe060
--- /dev/null
+++ b/security/keymint/aidl/default/ta/soft.rs
@@ -0,0 +1,67 @@
+//
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Software-only trait implementations using fake keys.
+
+use kmr_common::{
+ crypto,
+ crypto::{Hkdf, Rng},
+ Error,
+};
+use kmr_crypto_boring::{hmac::BoringHmac, rng::BoringRng};
+use kmr_ta::device::RetrieveKeyMaterial;
+
+/// Root key retrieval using hard-coded fake keys.
+pub struct Keys;
+
+impl RetrieveKeyMaterial for Keys {
+ fn root_kek(&self, _context: &[u8]) -> Result<crypto::OpaqueOr<crypto::hmac::Key>, Error> {
+ // Matches `MASTER_KEY` in system/keymaster/key_blob_utils/software_keyblobs.cpp
+ Ok(crypto::hmac::Key::new([0; 16].to_vec()).into())
+ }
+ fn kak(&self) -> Result<crypto::OpaqueOr<crypto::aes::Key>, Error> {
+ // Matches `kFakeKeyAgreementKey` in
+ // system/keymaster/km_openssl/soft_keymaster_enforcement.cpp.
+ Ok(crypto::aes::Key::Aes256([0; 32]).into())
+ }
+ fn unique_id_hbk(&self, _ckdf: &dyn crypto::Ckdf) -> Result<crypto::hmac::Key, Error> {
+ // Matches value used in system/keymaster/contexts/pure_soft_keymaster_context.cpp.
+ crypto::hmac::Key::new_from(b"MustBeRandomBits")
+ }
+}
+
+/// Implementation of key derivation using a random fake key.
+pub struct Derive {
+ hbk: Vec<u8>,
+}
+
+impl Default for Derive {
+ fn default() -> Self {
+ // Use random data as an emulation of a hardware-backed key.
+ let mut hbk = vec![0; 32];
+ let mut rng = BoringRng;
+ rng.fill_bytes(&mut hbk);
+ Self { hbk }
+ }
+}
+
+impl crate::rpc::DeriveBytes for Derive {
+ fn derive_bytes(&self, context: &[u8], output_len: usize) -> Result<Vec<u8>, Error> {
+ BoringHmac.hkdf(&[], &self.hbk, context, output_len)
+ }
+}
+
+/// RPC artifact retrieval using software fake key.
+pub type RpcArtifacts = crate::rpc::Artifacts<Derive>;
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 087f763..c121d31 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -2024,7 +2024,7 @@
}
}
- if (KeyMintAidlTestBase::dump_Attestations) std::cout << cert_data.str();
+ if (KeyMintAidlTestBase::dump_Attestations) std::cout << "cert chain:\n" << cert_data.str();
return AssertionSuccess();
}
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
index 3e4afd0..73ea088 100644
--- a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -188,6 +188,7 @@
populateStubFor(&hal_fn->wifi_twt_session_resume);
populateStubFor(&hal_fn->wifi_twt_session_teardown);
populateStubFor(&hal_fn->wifi_twt_session_get_stats);
+ populateStubFor(&hal_fn->wifi_virtual_interface_create_with_vendor_data);
return true;
}
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
index 51b7301..b426cdb 100644
--- a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -317,6 +317,21 @@
}
/*
+ * RoamingModeControl
+ */
+TEST_P(WifiStaIfaceAidlTest, RoamingModeControl) {
+ if (interface_version_ < 2) {
+ GTEST_SKIP() << "Roaming mode control is available as of sta_iface V2";
+ }
+ if (!isFeatureSupported(IWifiStaIface::FeatureSetMask::ROAMING_MODE_CONTROL)) {
+ GTEST_SKIP() << "Roaming mode control is not supported.";
+ }
+
+ // Enable aggressive roaming.
+ EXPECT_TRUE(wifi_sta_iface_->setRoamingState(StaRoamingState::AGGRESSIVE).isOk());
+}
+
+/*
* EnableNDOffload
*/
TEST_P(WifiStaIfaceAidlTest, EnableNDOffload) {