Merge "Move libimapper_stablec ABI dumps from prebuilts/abi-dumps" into main
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index e859a0e..9547865 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -78,7 +78,6 @@
<effect name="haptic_generator" library="haptic_generator" uuid="97c4acd1-8b82-4f2f-832e-c2fe5d7a9931"/>
<effect name="loudness_enhancer" library="loudness_enhancer" uuid="fa415329-2034-4bea-b5dc-5b381c8d1e2c"/>
<effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
- <effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
<effect name="reverb_env_aux" library="reverb" uuid="4a387fc0-8ab3-11df-8bad-0002a5d5c51b"/>
<effect name="reverb_env_ins" library="reverb" uuid="c7a511a0-a3bb-11df-860e-0002a5d5c51b"/>
<effect name="reverb_pre_aux" library="reverb" uuid="f29a1400-a3bb-11df-8ddc-0002a5d5c51b"/>
diff --git a/audio/aidl/default/bluetooth/StreamBluetooth.cpp b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
index f22b7a9..efab470 100644
--- a/audio/aidl/default/bluetooth/StreamBluetooth.cpp
+++ b/audio/aidl/default/bluetooth/StreamBluetooth.cpp
@@ -93,17 +93,18 @@
::android::status_t StreamBluetooth::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
std::lock_guard guard(mLock);
+ *actualFrameCount = 0;
+ *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
if (mBtDeviceProxy == nullptr || mBtDeviceProxy->getState() == BluetoothStreamState::DISABLED) {
- *actualFrameCount = 0;
- *latencyMs = StreamDescriptor::LATENCY_UNKNOWN;
+ // The BT session is turned down, silently ignore write.
return ::android::OK;
}
- *actualFrameCount = 0;
- *latencyMs = 0;
if (!mBtDeviceProxy->start()) {
- LOG(ERROR) << __func__ << ": state= " << mBtDeviceProxy->getState() << " failed to start";
- return -EIO;
+ LOG(WARNING) << __func__ << ": state= " << mBtDeviceProxy->getState()
+ << " failed to start, will retry";
+ return ::android::OK;
}
+ *latencyMs = 0;
const size_t bytesToTransfer = frameCount * mFrameSizeBytes;
const size_t bytesTransferred = mIsInput ? mBtDeviceProxy->readData(buffer, bytesToTransfer)
: mBtDeviceProxy->writeData(buffer, bytesToTransfer);
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 337089d..b236831 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -145,6 +145,9 @@
name: "VtsHalPresetReverbTargetTest",
defaults: ["VtsHalAudioEffectTargetTestDefaults"],
srcs: ["VtsHalPresetReverbTargetTest.cpp"],
+ shared_libs: [
+ "libaudioutils",
+ ],
}
cc_test {
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
index 82a07fd..0d1e0dc 100644
--- a/audio/aidl/vts/EffectHelper.h
+++ b/audio/aidl/vts/EffectHelper.h
@@ -70,6 +70,8 @@
static inline std::string getPrefix(Descriptor& descriptor) {
std::string prefix = "Implementor_" + descriptor.common.implementor + "_name_" +
descriptor.common.name + "_UUID_" + toString(descriptor.common.id.uuid);
+ std::replace_if(
+ prefix.begin(), prefix.end(), [](const char c) { return !std::isalnum(c); }, '_');
return prefix;
}
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 4a7bfbd..8b08945 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -1740,6 +1740,11 @@
}
TEST_P(AudioCoreModule, TryConnectMissingDevice) {
+ // Limit checks to connection types that are known to be detectable by HAL implementations.
+ static const std::set<std::string> kCheckedConnectionTypes{
+ AudioDeviceDescription::CONNECTION_HDMI, AudioDeviceDescription::CONNECTION_HDMI_ARC,
+ AudioDeviceDescription::CONNECTION_HDMI_EARC, AudioDeviceDescription::CONNECTION_IP_V4,
+ AudioDeviceDescription::CONNECTION_USB};
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
std::vector<AudioPort> ports = moduleConfig->getExternalDevicePorts();
if (ports.empty()) {
@@ -1748,14 +1753,10 @@
WithDebugFlags doNotSimulateConnections = WithDebugFlags::createNested(*debug);
doNotSimulateConnections.flags().simulateDeviceConnections = false;
ASSERT_NO_FATAL_FAILURE(doNotSimulateConnections.SetUp(module.get()));
+ bool hasAtLeastOneCheckedConnection = false;
for (const auto& port : ports) {
- // Virtual devices may not require external hardware and thus can always be connected.
- if (port.ext.get<AudioPortExt::device>().device.type.connection ==
- AudioDeviceDescription::CONNECTION_VIRTUAL ||
- // SCO devices are handled at low level by DSP, may not be able to check actual
- // connection.
- port.ext.get<AudioPortExt::device>().device.type.connection ==
- AudioDeviceDescription::CONNECTION_BT_SCO) {
+ if (kCheckedConnectionTypes.count(
+ port.ext.get<AudioPortExt::device>().device.type.connection) == 0) {
continue;
}
AudioPort portWithData = GenerateUniqueDeviceAddress(port), connectedPort;
@@ -1768,6 +1769,10 @@
EXPECT_IS_OK(module->disconnectExternalDevice(connectedPort.id))
<< "when disconnecting device port ID " << connectedPort.id;
}
+ hasAtLeastOneCheckedConnection = true;
+ }
+ if (!hasAtLeastOneCheckedConnection) {
+ GTEST_SKIP() << "No external devices with connection types that can be checked.";
}
}
diff --git a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
index 1453495..300939e 100644
--- a/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalPresetReverbTargetTest.cpp
@@ -17,11 +17,14 @@
#define LOG_TAG "VtsHalPresetReverbTargetTest"
#include <android-base/logging.h>
#include <android/binder_enums.h>
+#include <audio_utils/power.h>
+#include <system/audio.h>
#include "EffectHelper.h"
using namespace android;
+using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb;
using aidl::android::hardware::audio::effect::IEffect;
@@ -30,6 +33,68 @@
using aidl::android::hardware::audio::effect::PresetReverb;
using android::hardware::audio::common::testing::detail::TestExecutionTracer;
+class PresetReverbHelper : public EffectHelper {
+ public:
+ void SetUpPresetReverb() {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, kSamplingFrequency /* iSampleRate */,
+ kSamplingFrequency /* oSampleRate */, mFrameCount /* iFrameCount */,
+ mFrameCount /* oFrameCount */);
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &mOpenEffectReturn, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+
+ void TearDownPresetReverb() {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ mOpenEffectReturn = IEffect::OpenEffectReturn{};
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ PresetReverb pr = PresetReverb::make<PresetReverb::preset>(kDefaultPreset);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::presetReverb>(pr);
+ return specific;
+ }
+
+ Parameter createPresetReverbParam(const PresetReverb::Presets& param) {
+ return Parameter::make<Parameter::specific>(
+ Parameter::Specific::make<Parameter::Specific::presetReverb>(
+ PresetReverb::make<PresetReverb::preset>(param)));
+ }
+
+ void setAndVerifyPreset(const PresetReverb::Presets& param) {
+ auto expectedParam = createPresetReverbParam(param);
+ EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectedParam)) << expectedParam.toString();
+
+ PresetReverb::Id revId =
+ PresetReverb::Id::make<PresetReverb::Id::commonTag>(PresetReverb::preset);
+
+ auto id = Parameter::Id::make<Parameter::Id::presetReverbTag>(revId);
+ // get parameter
+ Parameter getParam;
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+ EXPECT_EQ(expectedParam, getParam) << "\nexpectedParam:" << expectedParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+
+ static constexpr int kSamplingFrequency = 44100;
+ static constexpr int kDurationMilliSec = 2000;
+ static constexpr int kBufferSize = kSamplingFrequency * kDurationMilliSec / 1000;
+ int mStereoChannelCount =
+ getChannelCount(AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO));
+ PresetReverb::Presets kDefaultPreset = PresetReverb::Presets::NONE;
+ int mFrameCount = kBufferSize / mStereoChannelCount;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ IEffect::OpenEffectReturn mOpenEffectReturn;
+ Descriptor mDescriptor;
+};
+
/**
* Here we focus on specific parameter checking, general IEffect interfaces testing performed in
* VtsAudioEffectTargetTest.
@@ -44,88 +109,116 @@
ndk::enum_range<PresetReverb::Presets>().end()};
class PresetReverbParamTest : public ::testing::TestWithParam<PresetReverbParamTestParam>,
- public EffectHelper {
+ public PresetReverbHelper {
public:
- PresetReverbParamTest() : mParamPresets(std::get<PARAM_PRESETS>(GetParam())) {
+ PresetReverbParamTest() : mParamPreset(std::get<PARAM_PRESETS>(GetParam())) {
std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
}
- void SetUp() override {
- ASSERT_NE(nullptr, mFactory);
- ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb()); }
- Parameter::Specific specific = getDefaultParamSpecific();
- Parameter::Common common = EffectHelper::createParamCommon(
- 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
- kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
- IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
- ASSERT_NE(nullptr, mEffect);
- }
+ void TearDown() override { TearDownPresetReverb(); }
- void TearDown() override {
- ASSERT_NO_FATAL_FAILURE(close(mEffect));
- ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
- }
-
- static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
- std::shared_ptr<IFactory> mFactory;
- std::shared_ptr<IEffect> mEffect;
- Descriptor mDescriptor;
- PresetReverb::Presets mParamPresets = PresetReverb::Presets::NONE;
-
- void SetAndGetPresetReverbParameters() {
- for (auto& it : mTags) {
- auto& tag = it.first;
- auto& pr = it.second;
-
- // validate parameter
- Descriptor desc;
- ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
- const bool valid = isParameterValid<PresetReverb, Range::presetReverb>(it.second, desc);
- const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
-
- // set parameter
- Parameter expectParam;
- Parameter::Specific specific;
- specific.set<Parameter::Specific::presetReverb>(pr);
- expectParam.set<Parameter::specific>(specific);
- // All values are valid, set parameter should succeed
- EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString();
-
- // get parameter
- Parameter getParam;
- Parameter::Id id;
- PresetReverb::Id prId;
- prId.set<PresetReverb::Id::commonTag>(tag);
- id.set<Parameter::Id::presetReverbTag>(prId);
- EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
-
- EXPECT_EQ(expectParam, getParam);
- }
- }
-
- void addPresetsParam(PresetReverb::Presets preset) {
- PresetReverb pr;
- pr.set<PresetReverb::preset>(preset);
- mTags.push_back({PresetReverb::preset, pr});
- }
-
- Parameter::Specific getDefaultParamSpecific() {
- PresetReverb pr = PresetReverb::make<PresetReverb::preset>(PresetReverb::Presets::NONE);
- Parameter::Specific specific =
- Parameter::Specific::make<Parameter::Specific::presetReverb>(pr);
- return specific;
- }
-
- private:
- std::vector<std::pair<PresetReverb::Tag, PresetReverb>> mTags;
- void CleanUp() { mTags.clear(); }
+ const PresetReverb::Presets mParamPreset;
};
TEST_P(PresetReverbParamTest, SetAndGetPresets) {
- EXPECT_NO_FATAL_FAILURE(addPresetsParam(mParamPresets));
- SetAndGetPresetReverbParameters();
+ ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(mParamPreset));
+}
+
+using PresetReverbProcessTestParam = std::pair<std::shared_ptr<IFactory>, Descriptor>;
+
+class PresetReverbProcessTest : public ::testing::TestWithParam<PresetReverbProcessTestParam>,
+ public PresetReverbHelper {
+ public:
+ PresetReverbProcessTest() {
+ std::tie(mFactory, mDescriptor) = GetParam();
+ generateSineWaveInput();
+ }
+
+ void SetUp() override {
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(SetUpPresetReverb());
+ }
+ void TearDown() override {
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(TearDownPresetReverb());
+ }
+
+ void generateSineWaveInput() {
+ int frequency = 1000;
+ for (size_t i = 0; i < kBufferSize; i++) {
+ mInput.push_back(sin(2 * M_PI * frequency * i / kSamplingFrequency));
+ }
+ }
+
+ bool isAuxiliary() {
+ return mDescriptor.common.flags.type ==
+ aidl::android::hardware::audio::effect::Flags::Type::AUXILIARY;
+ }
+
+ float computeReverbOutputEnergy(std::vector<float> output) {
+ if (!isAuxiliary()) {
+ // Extract auxiliary output
+ for (size_t i = 0; i < output.size(); i++) {
+ output[i] -= mInput[i];
+ }
+ }
+ return (audio_utils_compute_energy_mono(output.data(), AUDIO_FORMAT_PCM_FLOAT,
+ output.size()));
+ }
+
+ void setPresetAndProcess(const PresetReverb::Presets& preset, std::vector<float>& output) {
+ ASSERT_NO_FATAL_FAILURE(setAndVerifyPreset(preset));
+ ASSERT_NO_FATAL_FAILURE(
+ processAndWriteToOutput(mInput, output, mEffect, &mOpenEffectReturn));
+ }
+
+ void validateIncreasingEnergy(const std::vector<PresetReverb::Presets>& presets) {
+ float baseOutputEnergy = 0;
+
+ for (PresetReverb::Presets preset : presets) {
+ std::vector<float> output(kBufferSize);
+ setPresetAndProcess(preset, output);
+ float outputEnergy = computeReverbOutputEnergy(output);
+
+ ASSERT_GT(outputEnergy, baseOutputEnergy);
+ baseOutputEnergy = outputEnergy;
+ }
+ }
+
+ std::vector<float> mInput;
+};
+
+TEST_P(PresetReverbProcessTest, DecreasingRoomSize) {
+ std::vector<PresetReverb::Presets> roomPresets = {PresetReverb::Presets::LARGEROOM,
+ PresetReverb::Presets::MEDIUMROOM,
+ PresetReverb::Presets::SMALLROOM};
+ validateIncreasingEnergy(roomPresets);
+}
+
+TEST_P(PresetReverbProcessTest, DecreasingHallSize) {
+ std::vector<PresetReverb::Presets> hallPresets = {PresetReverb::Presets::LARGEHALL,
+ PresetReverb::Presets::MEDIUMHALL};
+ validateIncreasingEnergy(hallPresets);
+}
+
+TEST_P(PresetReverbProcessTest, PresetPlate) {
+ std::vector<float> output(kBufferSize);
+
+ setPresetAndProcess(PresetReverb::Presets::PLATE, output);
+ float outputEnergy = computeReverbOutputEnergy(output);
+ // Since there is no comparator preset, validating it is greater than zero
+ ASSERT_GT(outputEnergy, 0);
+}
+
+TEST_P(PresetReverbProcessTest, PresetNone) {
+ std::vector<float> output(kBufferSize);
+
+ setPresetAndProcess(kDefaultPreset, output);
+ float outputEnergy = computeReverbOutputEnergy(output);
+ // NONE type doesn't create reverb effect
+ ASSERT_EQ(outputEnergy, 0);
}
INSTANTIATE_TEST_SUITE_P(
@@ -145,6 +238,17 @@
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbParamTest);
+INSTANTIATE_TEST_SUITE_P(
+ PresetReverbTest, PresetReverbProcessTest,
+ testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, getEffectTypeUuidPresetReverb())),
+ [](const testing::TestParamInfo<PresetReverbProcessTest::ParamType>& info) {
+ auto descriptor = info.param;
+ return getPrefix(descriptor.second);
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PresetReverbProcessTest);
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
::testing::UnitTest::GetInstance()->listeners().Append(new TestExecutionTracer());
diff --git a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
index b4a2f41..2f6af08 100644
--- a/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVirtualizerTargetTest.cpp
@@ -150,8 +150,15 @@
std::tie(mFactory, mDescriptor) = std::get<PROCESS_INSTANCE_NAME>(GetParam());
}
- void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpVirtualizer()); }
- void TearDown() override { TearDownVirtualizer(); }
+ void SetUp() override {
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(SetUpVirtualizer());
+ }
+
+ void TearDown() override {
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
+ ASSERT_NO_FATAL_FAILURE(TearDownVirtualizer());
+ }
void generateInput(std::vector<float>& buffer) {
if (mZeroInput) {
diff --git a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
index 608fde1..140b956 100644
--- a/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
+++ b/bluetooth/aidl/vts/VtsHalBluetoothTargetTest.cpp
@@ -75,7 +75,7 @@
static constexpr size_t kNumHciCommandsBandwidth = 100;
static constexpr size_t kNumScoPacketsBandwidth = 100;
static constexpr size_t kNumAclPacketsBandwidth = 100;
-static constexpr std::chrono::milliseconds kWaitForInitTimeout(1000);
+static constexpr std::chrono::milliseconds kWaitForInitTimeout(2000);
static constexpr std::chrono::milliseconds kWaitForHciEventTimeout(2000);
static constexpr std::chrono::milliseconds kWaitForScoDataTimeout(1000);
static constexpr std::chrono::milliseconds kWaitForAclDataTimeout(1000);
diff --git a/compatibility_matrices/compatibility_matrix.202404.xml b/compatibility_matrices/compatibility_matrix.202404.xml
index f6f70e0..a5e40dd 100644
--- a/compatibility_matrices/compatibility_matrix.202404.xml
+++ b/compatibility_matrices/compatibility_matrix.202404.xml
@@ -538,6 +538,7 @@
<name>ISharedSecret</name>
<instance>default</instance>
<instance>strongbox</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="aidl">
diff --git a/compatibility_matrices/compatibility_matrix.202504.xml b/compatibility_matrices/compatibility_matrix.202504.xml
index 62756bd..4b438ce 100644
--- a/compatibility_matrices/compatibility_matrix.202504.xml
+++ b/compatibility_matrices/compatibility_matrix.202504.xml
@@ -529,6 +529,7 @@
<name>ISharedSecret</name>
<instance>default</instance>
<instance>strongbox</instance>
+ <regex-instance>.*</regex-instance>
</interface>
</hal>
<hal format="aidl">
diff --git a/gatekeeper/aidl/software/Android.bp b/gatekeeper/aidl/software/Android.bp
new file mode 100644
index 0000000..d244461
--- /dev/null
+++ b/gatekeeper/aidl/software/Android.bp
@@ -0,0 +1,71 @@
+package {
+ // 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
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_binary {
+ name: "android.hardware.gatekeeper-service.nonsecure",
+ cflags: [
+ "-fvisibility=hidden",
+ "-Wall",
+ "-Werror",
+ ],
+ installable: false, // installed in APEX
+ relative_install_path: "hw",
+ shared_libs: [
+ "android.hardware.gatekeeper-V1-ndk",
+ "android.hardware.security.sharedsecret-V1-ndk",
+ "lib_android_keymaster_keymint_utils",
+ "libbase",
+ "libbinder_ndk",
+ "libcrypto",
+ "libcutils",
+ "libgatekeeper",
+ "libhardware",
+ "libkeymaster_portable",
+ "liblog",
+ "libutils",
+ ],
+ srcs: [
+ "GateKeeper.cpp",
+ "SharedSecret.cpp",
+ "service.cpp",
+ ],
+ static_libs: ["libscrypt_static"],
+ vendor: true,
+}
+
+prebuilt_etc {
+ name: "gatekeeper_nonsecure_vintf",
+ srcs: [
+ "android.hardware.gatekeeper-service.nonsecure.xml",
+ "android.hardware.security.sharedsecret-gatekeeper.xml",
+ ],
+ sub_dir: "vintf",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "android.hardware.gatekeeper-service.nonsecure.rc",
+ src: "android.hardware.gatekeeper-service.nonsecure.rc",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.gatekeeper.nonsecure",
+ binaries: ["android.hardware.gatekeeper-service.nonsecure"],
+ certificate: ":com.google.cf.apex.certificate",
+ file_contexts: "file_contexts",
+ key: "com.google.cf.apex.key",
+ manifest: "manifest.json",
+ prebuilts: [
+ "gatekeeper_nonsecure_vintf",
+ "android.hardware.gatekeeper-service.nonsecure.rc",
+ ],
+ updatable: false,
+ vendor: true,
+}
diff --git a/gatekeeper/aidl/software/GateKeeper.cpp b/gatekeeper/aidl/software/GateKeeper.cpp
new file mode 100644
index 0000000..1fc3682
--- /dev/null
+++ b/gatekeeper/aidl/software/GateKeeper.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.gatekeeper-service.nonsecure"
+
+#include <endian.h>
+
+#include <android-base/logging.h>
+
+#include "GateKeeper.h"
+
+using ::gatekeeper::EnrollRequest;
+using ::gatekeeper::EnrollResponse;
+using ::gatekeeper::ERROR_NONE;
+using ::gatekeeper::ERROR_RETRY;
+using ::gatekeeper::SizedBuffer;
+using ::gatekeeper::VerifyRequest;
+using ::gatekeeper::VerifyResponse;
+
+namespace aidl::android::hardware::gatekeeper {
+
+SizedBuffer vec2sized_buffer(const std::vector<uint8_t>& vec) {
+ if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) {
+ return {};
+ }
+ auto unused = new uint8_t[vec.size()];
+ std::copy(vec.begin(), vec.end(), unused);
+ return {unused, static_cast<uint32_t>(vec.size())};
+}
+
+void sizedBuffer2AidlHWToken(SizedBuffer& buffer,
+ android::hardware::security::keymint::HardwareAuthToken* aidlToken) {
+ const hw_auth_token_t* authToken =
+ reinterpret_cast<const hw_auth_token_t*>(buffer.Data<uint8_t>());
+ aidlToken->challenge = authToken->challenge;
+ aidlToken->userId = authToken->user_id;
+ aidlToken->authenticatorId = authToken->authenticator_id;
+ // these are in network order: translate to host
+ aidlToken->authenticatorType =
+ static_cast<android::hardware::security::keymint::HardwareAuthenticatorType>(
+ be32toh(authToken->authenticator_type));
+ aidlToken->timestamp.milliSeconds = be64toh(authToken->timestamp);
+ aidlToken->mac.insert(aidlToken->mac.begin(), std::begin(authToken->hmac),
+ std::end(authToken->hmac));
+}
+
+SoftGateKeeperDevice::SoftGateKeeperDevice(::gatekeeper::SoftGateKeeper& impl) : impl_(impl) {}
+
+::ndk::ScopedAStatus SoftGateKeeperDevice::enroll(int32_t uid,
+ const std::vector<uint8_t>& currentPasswordHandle,
+ const std::vector<uint8_t>& currentPassword,
+ const std::vector<uint8_t>& desiredPassword,
+ GatekeeperEnrollResponse* rsp) {
+ if (desiredPassword.size() == 0) {
+ LOG(ERROR) << "Desired password size is 0";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ }
+
+ if (currentPasswordHandle.size() > 0) {
+ if (currentPasswordHandle.size() != sizeof(::gatekeeper::password_handle_t)) {
+ LOG(ERROR) << "Password handle has wrong length";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ }
+ }
+
+ EnrollRequest request(uid, vec2sized_buffer(currentPasswordHandle),
+ vec2sized_buffer(desiredPassword), vec2sized_buffer(currentPassword));
+ EnrollResponse response;
+ impl_.Enroll(request, &response);
+ if (response.error == ERROR_RETRY) {
+ LOG(ERROR) << "Enroll response has a retry error";
+ *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), 0, {}};
+ return ndk::ScopedAStatus::ok();
+ } else if (response.error != ERROR_NONE) {
+ LOG(ERROR) << "Enroll response has an error: " << response.error;
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ } else {
+ const ::gatekeeper::password_handle_t* password_handle =
+ response.enrolled_password_handle.Data<::gatekeeper::password_handle_t>();
+ *rsp = {STATUS_OK,
+ 0,
+ static_cast<int64_t>(password_handle->user_id),
+ {response.enrolled_password_handle.Data<uint8_t>(),
+ (response.enrolled_password_handle.Data<uint8_t>() +
+ response.enrolled_password_handle.size())}};
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SoftGateKeeperDevice::verify(
+ int32_t uid, int64_t challenge, const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword, GatekeeperVerifyResponse* rsp) {
+ if (enrolledPasswordHandle.size() == 0) {
+ LOG(ERROR) << "Enrolled password size is 0";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ }
+
+ if (enrolledPasswordHandle.size() > 0) {
+ if (enrolledPasswordHandle.size() != sizeof(::gatekeeper::password_handle_t)) {
+ LOG(ERROR) << "Password handle has wrong length";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ }
+ }
+
+ VerifyRequest request(uid, challenge, vec2sized_buffer(enrolledPasswordHandle),
+ vec2sized_buffer(providedPassword));
+ VerifyResponse response;
+ impl_.Verify(request, &response);
+
+ if (response.error == ERROR_RETRY) {
+ LOG(ERROR) << "Verify request response gave retry error";
+ *rsp = {ERROR_RETRY_TIMEOUT, static_cast<int32_t>(response.retry_timeout), {}};
+ return ndk::ScopedAStatus::ok();
+ } else if (response.error != ERROR_NONE) {
+ LOG(ERROR) << "Verify request response gave error: " << response.error;
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_GENERAL_FAILURE));
+ } else {
+ // On Success, return GatekeeperVerifyResponse with Success Status, timeout{0} and
+ // valid HardwareAuthToken.
+ *rsp = {response.request_reenroll ? STATUS_REENROLL : STATUS_OK, 0, {}};
+ // Convert the hw_auth_token_t to HardwareAuthToken in the response.
+ sizedBuffer2AidlHWToken(response.auth_token, &rsp->hardwareAuthToken);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SoftGateKeeperDevice::deleteUser(int32_t /*uid*/) {
+ LOG(ERROR) << "deleteUser is unimplemented";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
+}
+
+::ndk::ScopedAStatus SoftGateKeeperDevice::deleteAllUsers() {
+ LOG(ERROR) << "deleteAllUsers is unimplemented";
+ return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(ERROR_NOT_IMPLEMENTED));
+}
+
+} // namespace aidl::android::hardware::gatekeeper
diff --git a/gatekeeper/aidl/software/GateKeeper.h b/gatekeeper/aidl/software/GateKeeper.h
new file mode 100644
index 0000000..1327fad
--- /dev/null
+++ b/gatekeeper/aidl/software/GateKeeper.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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 <aidl/android/hardware/gatekeeper/BnGatekeeper.h>
+#include <gatekeeper/gatekeeper_messages.h>
+
+#include "SoftGateKeeper.h"
+
+namespace aidl::android::hardware::gatekeeper {
+
+class SoftGateKeeperDevice : public BnGatekeeper {
+ public:
+ SoftGateKeeperDevice(::gatekeeper::SoftGateKeeper&);
+ /**
+ * Enrolls password_payload, which should be derived from a user selected pin
+ * or password, with the authentication factor private key used only for
+ * enrolling authentication factor data.
+ *
+ * Returns: 0 on success or an error code less than 0 on error.
+ * On error, enrolled_password_handle will not be allocated.
+ */
+ ::ndk::ScopedAStatus enroll(int32_t uid, const std::vector<uint8_t>& currentPasswordHandle,
+ const std::vector<uint8_t>& currentPassword,
+ const std::vector<uint8_t>& desiredPassword,
+ GatekeeperEnrollResponse* _aidl_return) override;
+ /**
+ * Verifies provided_password matches enrolled_password_handle.
+ *
+ * Implementations of this module may retain the result of this call
+ * to attest to the recency of authentication.
+ *
+ * On success, writes the address of a verification token to auth_token,
+ * usable to attest password verification to other trusted services. Clients
+ * may pass NULL for this value.
+ *
+ * Returns: 0 on success or an error code less than 0 on error
+ * On error, verification token will not be allocated
+ */
+ ::ndk::ScopedAStatus verify(int32_t uid, int64_t challenge,
+ const std::vector<uint8_t>& enrolledPasswordHandle,
+ const std::vector<uint8_t>& providedPassword,
+ GatekeeperVerifyResponse* _aidl_return) override;
+
+ ::ndk::ScopedAStatus deleteAllUsers() override;
+
+ ::ndk::ScopedAStatus deleteUser(int32_t uid) override;
+
+ private:
+ ::gatekeeper::SoftGateKeeper& impl_;
+};
+
+} // namespace aidl::android::hardware::gatekeeper
diff --git a/gatekeeper/aidl/software/SharedSecret.cpp b/gatekeeper/aidl/software/SharedSecret.cpp
new file mode 100644
index 0000000..f693700
--- /dev/null
+++ b/gatekeeper/aidl/software/SharedSecret.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright 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 "SharedSecret.h"
+
+#include <algorithm>
+#include <cstring>
+#include <mutex>
+#include <vector>
+
+#include <openssl/rand.h>
+
+#include <KeyMintUtils.h>
+#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
+#include <aidl/android/hardware/security/sharedsecret/SharedSecretParameters.h>
+#include <android-base/logging.h>
+#include <keymaster/android_keymaster_messages.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/km_openssl/ckdf.h>
+#include <keymaster/km_openssl/hmac.h>
+
+namespace aidl::android::hardware::security::sharedsecret {
+
+::ndk::ScopedAStatus SoftSharedSecret::getSharedSecretParameters(
+ SharedSecretParameters* out_params) {
+ std::lock_guard lock(mutex_);
+ if (seed_.empty()) {
+ seed_.resize(32, 0);
+ }
+ out_params->seed = seed_;
+ if (nonce_.empty()) {
+ nonce_.resize(32, 0);
+ RAND_bytes(nonce_.data(), 32);
+ }
+ out_params->nonce = nonce_;
+ LOG(INFO) << "Presented shared secret parameters with seed size " << out_params->seed.size()
+ << " and nonce size " << out_params->nonce.size();
+ return ::ndk::ScopedAStatus::ok();
+}
+
+::ndk::ScopedAStatus SoftSharedSecret::computeSharedSecret(
+ const std::vector<SharedSecretParameters>& params, std::vector<uint8_t>* sharing_check) {
+ std::lock_guard lock(mutex_);
+ LOG(INFO) << "Computing shared secret";
+ // Reimplemented based on SoftKeymasterEnforcement, which does not expose
+ // enough functionality to satisfy the GateKeeper interface
+ keymaster::KeymasterKeyBlob key_agreement_key;
+ if (key_agreement_key.Reset(32) == nullptr) {
+ LOG(ERROR) << "key agreement key memory allocation failed";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED);
+ }
+ // Matching:
+ // - kFakeAgreementKey in system/keymaster/km_openssl/soft_keymaster_enforcement.cpp
+ // - Keys::kak in hardware/interfaces/security/keymint/aidl/default/ta/soft.rs
+ std::memset(key_agreement_key.writable_data(), 0, 32);
+ keymaster::KeymasterBlob label((uint8_t*)KEY_AGREEMENT_LABEL, strlen(KEY_AGREEMENT_LABEL));
+ if (label.data == nullptr) {
+ LOG(ERROR) << "label memory allocation failed";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED);
+ }
+
+ static_assert(sizeof(keymaster_blob_t) == sizeof(keymaster::KeymasterBlob));
+
+ bool found_mine = false;
+ std::vector<keymaster::KeymasterBlob> context_blobs;
+ for (const auto& param : params) {
+ auto& seed_blob = context_blobs.emplace_back();
+ if (seed_blob.Reset(param.seed.size()) == nullptr) {
+ LOG(ERROR) << "seed memory allocation failed";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED);
+ }
+ std::copy(param.seed.begin(), param.seed.end(), seed_blob.writable_data());
+ auto& nonce_blob = context_blobs.emplace_back();
+ if (nonce_blob.Reset(param.nonce.size()) == nullptr) {
+ LOG(ERROR) << "Nonce memory allocation failed";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED);
+ }
+ std::copy(param.nonce.begin(), param.nonce.end(), nonce_blob.writable_data());
+ if (param.seed == seed_ && param.nonce == nonce_) {
+ found_mine = true;
+ }
+ }
+ if (!found_mine) {
+ LOG(ERROR) << "Did not receive my own shared secret parameter back";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_INVALID_ARGUMENT);
+ }
+ auto context_blobs_ptr = reinterpret_cast<keymaster_blob_t*>(context_blobs.data());
+ if (hmac_key_.Reset(32) == nullptr) {
+ LOG(ERROR) << "hmac key allocation failed";
+ return keymint::km_utils::kmError2ScopedAStatus(KM_ERROR_MEMORY_ALLOCATION_FAILED);
+ }
+ auto error = keymaster::ckdf(key_agreement_key, label, context_blobs_ptr, context_blobs.size(),
+ &hmac_key_);
+ if (error != KM_ERROR_OK) {
+ LOG(ERROR) << "CKDF failed";
+ return keymint::km_utils::kmError2ScopedAStatus(error);
+ }
+
+ keymaster::HmacSha256 hmac_impl;
+ if (!hmac_impl.Init(hmac_key_.key_material, hmac_key_.key_material_size)) {
+ LOG(ERROR) << "hmac initialization failed";
+ return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ sharing_check->clear();
+ sharing_check->resize(32, 0);
+ if (!hmac_impl.Sign((const uint8_t*)KEY_CHECK_LABEL, strlen(KEY_CHECK_LABEL),
+ sharing_check->data(), sharing_check->size())) {
+ return ::ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return ::ndk::ScopedAStatus::ok();
+}
+
+keymaster::KeymasterKeyBlob SoftSharedSecret::HmacKey() const {
+ std::lock_guard lock(mutex_);
+ return hmac_key_;
+}
+
+} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/gatekeeper/aidl/software/SharedSecret.h b/gatekeeper/aidl/software/SharedSecret.h
new file mode 100644
index 0000000..1b804e7
--- /dev/null
+++ b/gatekeeper/aidl/software/SharedSecret.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020, 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 <cstdint>
+#include <mutex>
+
+#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
+#include <aidl/android/hardware/security/sharedsecret/SharedSecretParameters.h>
+#include <keymaster/km_openssl/soft_keymaster_enforcement.h>
+
+namespace aidl::android::hardware::security::sharedsecret {
+
+class SoftSharedSecret : public BnSharedSecret {
+ public:
+ ::ndk::ScopedAStatus getSharedSecretParameters(SharedSecretParameters* params) override;
+ ::ndk::ScopedAStatus computeSharedSecret(const std::vector<SharedSecretParameters>& params,
+ std::vector<uint8_t>* sharingCheck) override;
+
+ keymaster::KeymasterKeyBlob HmacKey() const;
+
+ private:
+ mutable std::mutex mutex_;
+ std::vector<std::uint8_t> seed_;
+ std::vector<std::uint8_t> nonce_;
+ keymaster::KeymasterKeyBlob hmac_key_;
+};
+
+} // namespace aidl::android::hardware::security::sharedsecret
diff --git a/gatekeeper/aidl/software/SoftGateKeeper.h b/gatekeeper/aidl/software/SoftGateKeeper.h
new file mode 100644
index 0000000..305d997
--- /dev/null
+++ b/gatekeeper/aidl/software/SoftGateKeeper.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef SOFT_GATEKEEPER_H_
+#define SOFT_GATEKEEPER_H_
+
+extern "C" {
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <crypto_scrypt.h>
+}
+
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/memory.h>
+#include <gatekeeper/gatekeeper.h>
+#include <keymaster/km_openssl/hmac.h>
+
+#include "SharedSecret.h"
+
+namespace gatekeeper {
+
+struct fast_hash_t {
+ uint64_t salt;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+};
+
+class SoftGateKeeper : public GateKeeper {
+ public:
+ static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
+
+ // scrypt params
+ static const uint64_t N = 16384;
+ static const uint32_t r = 8;
+ static const uint32_t p = 1;
+
+ static const int MAX_UINT_32_CHARS = 11;
+
+ SoftGateKeeper(const ::aidl::android::hardware::security::sharedsecret::SoftSharedSecret&
+ shared_secret)
+ : shared_secret_(shared_secret) {
+ key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
+ memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
+ }
+
+ virtual ~SoftGateKeeper() {}
+
+ virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const {
+ if (auth_token_key == NULL || length == NULL) return false;
+ if (hmac_key_.key_material == nullptr) {
+ hmac_key_ = shared_secret_.HmacKey();
+ }
+ *auth_token_key = hmac_key_.key_material;
+ *length = hmac_key_.key_material_size;
+ return true;
+ }
+
+ virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) {
+ if (password_key == NULL || length == NULL) return;
+ *password_key = key_.get();
+ *length = SIGNATURE_LENGTH_BYTES;
+ }
+
+ virtual void ComputePasswordSignature(uint8_t* signature, uint32_t signature_length,
+ const uint8_t*, uint32_t, const uint8_t* password,
+ uint32_t password_length, salt_t salt) const {
+ if (signature == NULL) return;
+ crypto_scrypt(password, password_length, reinterpret_cast<uint8_t*>(&salt), sizeof(salt), N,
+ r, p, signature, signature_length);
+ }
+
+ virtual void GetRandom(void* random, uint32_t requested_length) const {
+ if (random == NULL) return;
+ RAND_pseudo_bytes((uint8_t*)random, requested_length);
+ }
+
+ virtual void ComputeSignature(uint8_t* signature, uint32_t signature_length, const uint8_t* key,
+ uint32_t key_length, const uint8_t* message,
+ const uint32_t message_length) const {
+ if (signature == NULL) return;
+ keymaster::HmacSha256 hmac_calculator;
+ if (!hmac_calculator.Init(key, key_length)) {
+ LOG(ERROR) << "ComputeSignature: Failed to initialize hmac calculator";
+ return;
+ }
+ if (!hmac_calculator.Sign(message, message_length, signature, signature_length)) {
+ LOG(ERROR) << "ComputeSignature: failed to create hmac";
+ }
+ }
+
+ virtual uint64_t GetMillisecondsSinceBoot() const {
+ struct timespec time;
+ int res = clock_gettime(CLOCK_BOOTTIME, &time);
+ if (res < 0) return 0;
+ return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+ }
+
+ virtual bool IsHardwareBacked() const { return false; }
+
+ virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t* record,
+ bool /* secure */) {
+ failure_record_t* stored = &failure_map_[uid];
+ if (user_id != stored->secure_user_id) {
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ }
+ memcpy(record, stored, sizeof(*record));
+ return true;
+ }
+
+ virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
+ failure_record_t* stored = &failure_map_[uid];
+ stored->secure_user_id = user_id;
+ stored->last_checked_timestamp = 0;
+ stored->failure_counter = 0;
+ return true;
+ }
+
+ virtual bool WriteFailureRecord(uint32_t uid, failure_record_t* record, bool /* secure */) {
+ failure_map_[uid] = *record;
+ return true;
+ }
+
+ fast_hash_t ComputeFastHash(const SizedBuffer& password, uint64_t salt) {
+ fast_hash_t fast_hash;
+ size_t digest_size = password.size() + sizeof(salt);
+ std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
+ memcpy(digest.get(), &salt, sizeof(salt));
+ memcpy(digest.get() + sizeof(salt), password.Data<uint8_t>(), password.size());
+
+ SHA256(digest.get(), digest_size, (uint8_t*)&fast_hash.digest);
+
+ fast_hash.salt = salt;
+ return fast_hash;
+ }
+
+ bool VerifyFast(const fast_hash_t& fast_hash, const SizedBuffer& password) {
+ fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
+ return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
+ }
+
+ bool DoVerify(const password_handle_t* expected_handle, const SizedBuffer& password) {
+ uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
+ FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
+ if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
+ return true;
+ } else {
+ if (GateKeeper::DoVerify(expected_handle, password)) {
+ uint64_t salt;
+ GetRandom(&salt, sizeof(salt));
+ fast_hash_map_[user_id] = ComputeFastHash(password, salt);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private:
+ typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
+ typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
+
+ const ::aidl::android::hardware::security::sharedsecret::SoftSharedSecret& shared_secret_;
+ std::unique_ptr<uint8_t[]> key_;
+ FailureRecordMap failure_map_;
+ FastHashMap fast_hash_map_;
+ mutable ::keymaster::KeymasterKeyBlob hmac_key_;
+};
+} // namespace gatekeeper
+
+#endif // SOFT_GATEKEEPER_H_
diff --git a/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.rc b/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.rc
new file mode 100644
index 0000000..d361730
--- /dev/null
+++ b/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.rc
@@ -0,0 +1,4 @@
+service vendor.gatekeeper_nonsecure /apex/com.android.hardware.gatekeeper/bin/hw/android.hardware.gatekeeper-service.nonsecure
+ class early_hal
+ user system
+ group system
diff --git a/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.xml b/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.xml
new file mode 100644
index 0000000..c35421e
--- /dev/null
+++ b/gatekeeper/aidl/software/android.hardware.gatekeeper-service.nonsecure.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.gatekeeper</name>
+ <version>1</version>
+ <interface>
+ <name>IGatekeeper</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/gatekeeper/aidl/software/android.hardware.security.sharedsecret-gatekeeper.xml b/gatekeeper/aidl/software/android.hardware.security.sharedsecret-gatekeeper.xml
new file mode 100644
index 0000000..5d94985
--- /dev/null
+++ b/gatekeeper/aidl/software/android.hardware.security.sharedsecret-gatekeeper.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.security.sharedsecret</name>
+ <fqname>ISharedSecret/gatekeeper</fqname>
+ </hal>
+</manifest>
diff --git a/gatekeeper/aidl/software/file_contexts b/gatekeeper/aidl/software/file_contexts
new file mode 100644
index 0000000..23a62ea
--- /dev/null
+++ b/gatekeeper/aidl/software/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/etc(/.*)? u:object_r:vendor_configs_file:s0
+/bin/hw/android\.hardware\.gatekeeper-service\.nonsecure u:object_r:hal_gatekeeper_remote_exec:s0
diff --git a/gatekeeper/aidl/software/manifest.json b/gatekeeper/aidl/software/manifest.json
new file mode 100644
index 0000000..d0def36
--- /dev/null
+++ b/gatekeeper/aidl/software/manifest.json
@@ -0,0 +1,5 @@
+{
+ "name": "com.android.hardware.gatekeeper",
+ "version": 1,
+ "vendorBootstrap": true
+}
diff --git a/gatekeeper/aidl/software/service.cpp b/gatekeeper/aidl/software/service.cpp
new file mode 100644
index 0000000..beef8c4
--- /dev/null
+++ b/gatekeeper/aidl/software/service.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.gatekeeper-service.nonsecure"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <cutils/properties.h>
+
+#include "GateKeeper.h"
+#include "SharedSecret.h"
+#include "SoftGateKeeper.h"
+
+using aidl::android::hardware::gatekeeper::SoftGateKeeperDevice;
+using aidl::android::hardware::security::sharedsecret::SoftSharedSecret;
+
+int main(int, char** argv) {
+ ::android::base::InitLogging(argv, ::android::base::KernelLogger);
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ auto secret = ndk::SharedRefBase::make<SoftSharedSecret>();
+ std::string secret_instance = SoftSharedSecret::descriptor + std::string("/gatekeeper");
+ auto status = AServiceManager_addService(secret->asBinder().get(), secret_instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ::gatekeeper::SoftGateKeeper implementation(*secret);
+ auto gatekeeper = ndk::SharedRefBase::make<SoftGateKeeperDevice>(implementation);
+ const std::string instance = SoftGateKeeperDevice::descriptor + std::string("/default");
+ status = AServiceManager_addService(gatekeeper->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return -1; // Should never get here.
+}
diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
index 9360789..45a1e40 100644
--- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -312,7 +312,8 @@
return true;
}
-/*
+/* @VsrTest = 3.2.015
+ *
* Tests the values returned by getBatteryHealthData() from interface IHealth.
*/
TEST_P(HealthAidl, getBatteryHealthData) {
diff --git a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
index 8210ff0..2fc9e65 100644
--- a/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
+++ b/nfc/1.0/vts/functional/VtsHalNfcV1_0TargetTest.cpp
@@ -562,7 +562,18 @@
*/
TEST_P(NfcHidlTest, OpenAfterOpen) {
EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
EXPECT_EQ(NfcStatus::OK, nfc_->open(nfc_cb_));
+ // Wait for OPEN_CPLT event
+ res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+ EXPECT_TRUE(res.no_timeout);
+ EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+ EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcHidlTest);
diff --git a/security/keymint/aidl/default/ta/clock.rs b/security/keymint/aidl/default/ta/clock.rs
index ad8509a..03e04ec 100644
--- a/security/keymint/aidl/default/ta/clock.rs
+++ b/security/keymint/aidl/default/ta/clock.rs
@@ -16,25 +16,29 @@
//! Monotonic clock implementation.
use kmr_common::crypto;
-use std::time::Instant;
/// Monotonic clock.
-pub struct StdClock {
- start: Instant,
-}
+pub struct StdClock;
impl StdClock {
/// Create new clock instance, holding time since construction.
pub fn new() -> Self {
- Self {
- start: Instant::now(),
- }
+ Self {}
}
}
impl crypto::MonotonicClock for StdClock {
fn now(&self) -> crypto::MillisecondsSinceEpoch {
- let duration = self.start.elapsed();
- crypto::MillisecondsSinceEpoch(duration.as_millis().try_into().unwrap())
+ let mut time = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+ // Use `CLOCK_BOOTTIME` for consistency with the times used by the Cuttlefish
+ // C++ implementation of Gatekeeper.
+ let rc =
+ // Safety: `time` is a valid structure.
+ unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut time as *mut libc::timespec) };
+ if rc < 0 {
+ log::warn!("failed to get time!");
+ return crypto::MillisecondsSinceEpoch(0);
+ }
+ crypto::MillisecondsSinceEpoch(((time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000)).into())
}
}
diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp
index 7bdf39a..0544502 100644
--- a/threadnetwork/aidl/default/socket_interface.cpp
+++ b/threadnetwork/aidl/default/socket_interface.cpp
@@ -23,6 +23,7 @@
#include "socket_interface.hpp"
#include <errno.h>
+#include <linux/limits.h>
#include <openthread/logging.h>
#include <sys/inotify.h>
#include <sys/socket.h>
@@ -273,7 +274,7 @@
}
if (FD_ISSET(inotifyFd, &fds)) {
- char buffer[sizeof(struct inotify_event)];
+ char buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
ssize_t bytesRead = read(inotifyFd, buffer, sizeof(buffer));
VerifyOrDie(bytesRead >= 0, OT_EXIT_ERROR_ERRNO);
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
index 5d00485..4768005 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -407,7 +407,7 @@
* SetCountryCode
*/
TEST_P(SupplicantStaIfaceAidlTest, SetCountryCode) {
- const std::vector<uint8_t> countryCode = {'M', 'X'};
+ const std::vector<uint8_t> countryCode = {'U', 'S'};
EXPECT_TRUE(sta_iface_->setCountryCode(countryCode).isOk());
}