Merge changes from topic "duration-unit" into udc-dev
* changes:
[automerge] Change the unit of slot duration from ms to rstu. 2p: 40bc040455
Change the unit of slot duration from ms to rstu.
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index 10aead2..5440b8d 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -895,6 +895,21 @@
out_suggested->gain = in_requested.gain.value();
}
+ 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;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": requested ext tag "
+ << toString(in_requested.ext.getTag()) << " do not match port's tag "
+ << toString(out_suggested->ext.getTag());
+ requestedIsValid = false;
+ }
+ }
+
if (existing == configs.end() && requestedIsValid && requestedIsFullySpecified) {
out_suggested->id = getConfig().nextPortId++;
configs.push_back(*out_suggested);
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index 88c4459..0d1731f 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -40,6 +40,7 @@
<library name="loudness_enhancer" path="libloudnessenhanceraidl.so"/>
<library name="nssw" path="libnssw.so"/>
<library name="env_reverbsw" path="libenvreverbsw.so"/>
+ <library name="pre_processing" path="libpreprocessingaidl.so"/>
<library name="preset_reverbsw" path="libpresetreverbsw.so"/>
<library name="reverb" path="libreverbaidl.so"/>
<library name="virtualizersw" path="libvirtualizersw.so"/>
@@ -68,9 +69,9 @@
-->
<effects>
- <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
- <effect name="automatic_gain_control_v1" library="agc1sw" uuid="aa8130e0-66fc-11e0-bad0-0002a5d5c51b"/>
- <effect name="automatic_gain_control_v2" library="agc2sw" uuid="89f38e65-d4d2-4d64-ad0e-2b3e799ea886"/>
+ <effect name="acoustic_echo_canceler" library="pre_processing" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+ <effect name="automatic_gain_control_v1" library="pre_processing" uuid="aa8130e0-66fc-11e0-bad0-0002a5d5c51b"/>
+ <effect name="automatic_gain_control_v2" library="pre_processing" uuid="89f38e65-d4d2-4d64-ad0e-2b3e799ea886"/>
<effectProxy name="bassboost" uuid="14804144-a5ee-4d24-aa88-0002a5d5c51b">
<libsw library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
<libsw library="bundle" uuid="8631f300-72e2-11df-b57e-0002a5d5c51b"/>
@@ -80,7 +81,7 @@
<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="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
+ <effect name="noise_suppression" library="pre_processing" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
<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"/>
diff --git a/audio/aidl/default/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp
index 2814322..8cfe82e 100644
--- a/audio/aidl/default/equalizer/EqualizerSw.cpp
+++ b/audio/aidl/default/equalizer/EqualizerSw.cpp
@@ -76,11 +76,10 @@
const std::vector<Range::EqualizerRange> EqualizerSw::kRanges = {
MAKE_RANGE(Equalizer, preset, 0, EqualizerSw::kPresets.size() - 1),
MAKE_RANGE(Equalizer, bandLevels,
- std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
- {.index = 0, .levelMb = std::numeric_limits<int>::min()})},
std::vector<Equalizer::BandLevel>{
- Equalizer::BandLevel({.index = EqualizerSwContext::kMaxBandNumber - 1,
- .levelMb = std::numeric_limits<int>::max()})}),
+ Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+ std::vector<Equalizer::BandLevel>{Equalizer::BandLevel(
+ {.index = EqualizerSwContext::kMaxBandNumber - 1, .levelMb = 15})}),
/* capability definition */
MAKE_RANGE(Equalizer, bandFrequencies, EqualizerSw::kBandFrequency,
EqualizerSw::kBandFrequency),
@@ -171,6 +170,14 @@
eqParam.set<Equalizer::centerFreqMh>(mContext->getCenterFreqs());
break;
}
+ case Equalizer::bandFrequencies: {
+ eqParam.set<Equalizer::bandFrequencies>(kBandFrequency);
+ break;
+ }
+ case Equalizer::presets: {
+ eqParam.set<Equalizer::presets>(kPresets);
+ break;
+ }
default: {
LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
index 5e99cba2..d75e4e0 100644
--- a/audio/aidl/default/virtualizer/VirtualizerSw.cpp
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
@@ -68,11 +68,7 @@
MAKE_RANGE(Virtualizer, strengthPm, 0, 1000),
/* speakerAngle is get-only, set min > max */
MAKE_RANGE(Virtualizer, speakerAngles, {Virtualizer::ChannelAngle({.channel = 1})},
- {Virtualizer::ChannelAngle({.channel = 0})}),
- /* device is get-only */
- MAKE_RANGE(Virtualizer, device,
- AudioDeviceDescription({.type = AudioDeviceType::IN_DEFAULT}),
- AudioDeviceDescription({.type = AudioDeviceType::NONE}))};
+ {Virtualizer::ChannelAngle({.channel = 0})})};
const Capability VirtualizerSw::kCapability = {
.range = Range::make<Range::virtualizer>(VirtualizerSw::kRanges)};
@@ -174,17 +170,21 @@
ndk::ScopedAStatus VirtualizerSw::getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload,
Parameter::Specific* specific) {
std::vector<Virtualizer::ChannelAngle> angles;
- if (::android::hardware::audio::common::getChannelCount(payload.layout) == 1) {
+ const auto chNum = ::android::hardware::audio::common::getChannelCount(payload.layout);
+ if (chNum == 1) {
angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
.azimuthDegree = 0,
.elevationDegree = 0}};
- } else {
+ } else if (chNum == 2) {
angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
.azimuthDegree = -90,
.elevationDegree = 0},
{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
.azimuthDegree = 90,
.elevationDegree = 0}};
+ } else {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "supportUpTo2Ch");
}
Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 1222fd5..b6015ff 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -88,6 +88,7 @@
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioUsage;
using aidl::android::media::audio::common::Boolean;
@@ -1524,6 +1525,8 @@
AudioPortConfig portConfig;
AudioPortConfig suggestedConfig;
portConfig.portId = srcMixPort.value().id;
+ const int32_t kIoHandle = 42;
+ portConfig.ext = AudioPortMixExt{.handle = kIoHandle};
{
bool applied = true;
ASSERT_IS_OK(module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
@@ -1535,18 +1538,22 @@
EXPECT_TRUE(suggestedConfig.channelMask.has_value());
EXPECT_TRUE(suggestedConfig.format.has_value());
EXPECT_TRUE(suggestedConfig.flags.has_value());
+ ASSERT_EQ(AudioPortExt::Tag::mix, suggestedConfig.ext.getTag());
+ EXPECT_EQ(kIoHandle, suggestedConfig.ext.get<AudioPortExt::Tag::mix>().handle);
WithAudioPortConfig applied(suggestedConfig);
ASSERT_NO_FATAL_FAILURE(applied.SetUp(module.get()));
const AudioPortConfig& appliedConfig = applied.get();
EXPECT_NE(0, appliedConfig.id);
- EXPECT_TRUE(appliedConfig.sampleRate.has_value());
+ ASSERT_TRUE(appliedConfig.sampleRate.has_value());
EXPECT_EQ(suggestedConfig.sampleRate.value(), appliedConfig.sampleRate.value());
- EXPECT_TRUE(appliedConfig.channelMask.has_value());
+ ASSERT_TRUE(appliedConfig.channelMask.has_value());
EXPECT_EQ(suggestedConfig.channelMask.value(), appliedConfig.channelMask.value());
- EXPECT_TRUE(appliedConfig.format.has_value());
+ ASSERT_TRUE(appliedConfig.format.has_value());
EXPECT_EQ(suggestedConfig.format.value(), appliedConfig.format.value());
- EXPECT_TRUE(appliedConfig.flags.has_value());
+ ASSERT_TRUE(appliedConfig.flags.has_value());
EXPECT_EQ(suggestedConfig.flags.value(), appliedConfig.flags.value());
+ ASSERT_EQ(AudioPortExt::Tag::mix, appliedConfig.ext.getTag());
+ EXPECT_EQ(kIoHandle, appliedConfig.ext.get<AudioPortExt::Tag::mix>().handle);
}
TEST_P(AudioCoreModule, SetAllAttachedDevicePortConfigs) {
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index 98e49a2..478482d 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -1698,26 +1698,6 @@
ASSERT_EQ(0U, framesLost);
}
-TEST_P(InputStreamTest, getCapturePosition) {
- doc::test(
- "The capture position of a non prepared stream should not be "
- "retrievable or 0");
- uint64_t frames;
- uint64_t time;
- ASSERT_OK(stream->getCapturePosition(returnIn(res, frames, time)));
- // Although 'getCapturePosition' is mandatory in V7, legacy implementations
- // may return -ENOSYS (which is translated to NOT_SUPPORTED) in cases when
- // the capture position can't be retrieved, e.g. when the stream isn't
- // running. Because of this, we don't fail when getting NOT_SUPPORTED
- // in this test. Behavior of 'getCapturePosition' for running streams is
- // tested in 'PcmOnlyConfigInputStreamTest' for V7.
- ASSERT_RESULT(okOrInvalidStateOrNotSupported, res);
- if (res == Result::OK) {
- ASSERT_EQ(0U, frames);
- ASSERT_LE(0U, time);
- }
-}
-
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////// StreamOut //////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/AuthenticateReason.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/AuthenticateReason.aidl
new file mode 100644
index 0000000..f639ead
--- /dev/null
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/AuthenticateReason.aidl
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.common;
+/* @hide */
+@VintfStability
+union AuthenticateReason {
+ android.hardware.biometrics.common.AuthenticateReason.Vendor vendorAuthenticateReason;
+ android.hardware.biometrics.common.AuthenticateReason.Face faceAuthenticateReason;
+ android.hardware.biometrics.common.AuthenticateReason.Fingerprint fingerprintAuthenticateReason;
+ @VintfStability
+ parcelable Vendor {
+ ParcelableHolder extension;
+ }
+ @Backing(type="int") @VintfStability
+ enum Fingerprint {
+ UNKNOWN,
+ }
+ @Backing(type="int") @VintfStability
+ enum Face {
+ UNKNOWN,
+ STARTED_WAKING_UP,
+ PRIMARY_BOUNCER_SHOWN,
+ ASSISTANT_VISIBLE,
+ ALTERNATE_BIOMETRIC_BOUNCER_SHOWN,
+ NOTIFICATION_PANEL_CLICKED,
+ OCCLUDING_APP_REQUESTED,
+ PICK_UP_GESTURE_TRIGGERED,
+ QS_EXPANDED,
+ SWIPE_UP_ON_BOUNCER,
+ UDFPS_POINTER_DOWN,
+ }
+}
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/DisplayState.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/DisplayState.aidl
new file mode 100644
index 0000000..176e8d6
--- /dev/null
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/DisplayState.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.biometrics.common;
+/* @hide */
+@Backing(type="int") @VintfStability
+enum DisplayState {
+ UNKNOWN,
+ LOCKSCREEN,
+ NO_UI,
+ SCREENSAVER,
+ AOD,
+}
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
index 305e422..378017e 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
@@ -37,7 +37,12 @@
parcelable OperationContext {
int id = 0;
android.hardware.biometrics.common.OperationReason reason = android.hardware.biometrics.common.OperationReason.UNKNOWN;
+ /**
+ * @deprecated use displayState instead.
+ */
boolean isAod = false;
boolean isCrypto = false;
android.hardware.biometrics.common.WakeReason wakeReason = android.hardware.biometrics.common.WakeReason.UNKNOWN;
+ android.hardware.biometrics.common.DisplayState displayState = android.hardware.biometrics.common.DisplayState.UNKNOWN;
+ @nullable android.hardware.biometrics.common.AuthenticateReason authenticateReason;
}
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/AuthenticateReason.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/AuthenticateReason.aidl
new file mode 100644
index 0000000..fcf5294
--- /dev/null
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/AuthenticateReason.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.common;
+
+/**
+ * Reason for an authenticate operation.
+ *
+ * @hide
+ */
+@VintfStability
+union AuthenticateReason {
+ /** Vendor reason for invoking an authenticate operation. */
+ @VintfStability
+ parcelable Vendor {
+ ParcelableHolder extension;
+ }
+
+ /** Reason for invoking fingerprint authentication. */
+ @VintfStability
+ @Backing(type="int")
+ enum Fingerprint {
+ UNKNOWN,
+ }
+
+ /** Reason for invoking face authentication. */
+ @VintfStability
+ @Backing(type="int")
+ enum Face {
+ UNKNOWN,
+ STARTED_WAKING_UP,
+ PRIMARY_BOUNCER_SHOWN,
+ ASSISTANT_VISIBLE,
+ ALTERNATE_BIOMETRIC_BOUNCER_SHOWN,
+ NOTIFICATION_PANEL_CLICKED,
+ OCCLUDING_APP_REQUESTED,
+ PICK_UP_GESTURE_TRIGGERED,
+ QS_EXPANDED,
+ SWIPE_UP_ON_BOUNCER,
+ UDFPS_POINTER_DOWN,
+ }
+
+ AuthenticateReason.Vendor vendorAuthenticateReason;
+ AuthenticateReason.Face faceAuthenticateReason;
+ AuthenticateReason.Fingerprint fingerprintAuthenticateReason;
+}
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/DisplayState.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/DisplayState.aidl
new file mode 100644
index 0000000..d01eac8
--- /dev/null
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/DisplayState.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.common;
+
+/**
+ * Display state during an operation.
+ *
+ * @hide
+ */
+@VintfStability
+@Backing(type="int")
+enum DisplayState {
+ /** The display state is unknown. */
+ UNKNOWN,
+
+ /** The display is on and showing the lockscreen (or an occluding app). */
+ LOCKSCREEN,
+
+ /** The display is off or dozing. */
+ NO_UI,
+
+ /** The display is showing a screensaver (dreaming). */
+ SCREENSAVER,
+
+ /** The display is dreaming with always on display. */
+ AOD,
+}
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
index a8f768d..f4191d7 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
@@ -16,6 +16,8 @@
package android.hardware.biometrics.common;
+import android.hardware.biometrics.common.AuthenticateReason;
+import android.hardware.biometrics.common.DisplayState;
import android.hardware.biometrics.common.OperationReason;
import android.hardware.biometrics.common.WakeReason;
@@ -43,7 +45,7 @@
*/
OperationReason reason = OperationReason.UNKNOWN;
- /* Flag indicating that the display is in AOD mode. */
+ /** @deprecated use displayState instead. */
boolean isAod = false;
/** Flag indicating that crypto was requested. */
@@ -58,4 +60,15 @@
* policy.
*/
WakeReason wakeReason = WakeReason.UNKNOWN;
+
+ /** The current display state. */
+ DisplayState displayState = DisplayState.UNKNOWN;
+
+ /**
+ * An associated reason for an authenticate operation.
+ *
+ * This should be interpreted as a hint to enable optimizations or tracing. The
+ * framework may choose to omit the reason at any time based on the device's policy.
+ */
+ @nullable AuthenticateReason authenticateReason;
}
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
index 276e92a..3989161 100644
--- a/camera/device/3.2/types.hal
+++ b/camera/device/3.2/types.hal
@@ -346,15 +346,18 @@
* An override pixel format for the buffers in this stream.
*
* The HAL must respect the requested format in Stream unless it is
- * IMPLEMENTATION_DEFINED, in which case the override format here must be
- * used by the client instead, for this stream. This allows cross-platform
- * HALs to use a standard format since IMPLEMENTATION_DEFINED formats often
- * require device-specific information. In all other cases, the
+ * IMPLEMENTATION_DEFINED output, in which case the override format
+ * here must be used by the client instead, for this stream. This allows
+ * cross-platform HALs to use a standard format since IMPLEMENTATION_DEFINED
+ * formats often require device-specific information. In all other cases, the
* overrideFormat must match the requested format.
*
* When HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform
* gralloc module must select a format based on the usage flags provided by
* the camera device and the other endpoint of the stream.
+ *
+ * For private reprocessing, the HAL must not override the input stream's
+ * IMPLEMENTATION_DEFINED format.
*/
android.hardware.graphics.common@1.0::PixelFormat overrideFormat;
diff --git a/camera/device/aidl/android/hardware/camera/device/HalStream.aidl b/camera/device/aidl/android/hardware/camera/device/HalStream.aidl
index b8ec3de..25a80bc 100644
--- a/camera/device/aidl/android/hardware/camera/device/HalStream.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/HalStream.aidl
@@ -38,7 +38,7 @@
* An override pixel format for the buffers in this stream.
*
* The HAL must respect the requested format in Stream unless it is
- * IMPLEMENTATION_DEFINED, in which case the override format here must be
+ * IMPLEMENTATION_DEFINED output, in which case the override format here must be
* used by the client instead, for this stream. This allows cross-platform
* HALs to use a standard format since IMPLEMENTATION_DEFINED formats often
* require device-specific information. In all other cases, the
@@ -47,6 +47,9 @@
* When HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform
* gralloc module must select a format based on the usage flags provided by
* the camera device and the other endpoint of the stream.
+ *
+ * For private reprocessing, the HAL must not override the input stream's
+ * IMPLEMENTATION_DEFINED format.
*/
android.hardware.graphics.common.PixelFormat overrideFormat;
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index e1ad1f3..622835e 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -78,7 +78,7 @@
"compatibility_matrix.8.xml",
],
kernel_configs: [
- "kernel_config_current_5.10",
"kernel_config_current_5.15",
+ "kernel_config_current_6.1",
],
}
diff --git a/current.txt b/current.txt
index ef1f65a..358d05a 100644
--- a/current.txt
+++ b/current.txt
@@ -934,5 +934,6 @@
42abd285a4293dadb8c89bc63b90cae2872fbffe90c4517aa3ea4965e8aecff7 android.hardware.graphics.common@1.2::types
4f1a02d21a22104c734f71cdbba19b6f7e93d4ee107ff79f0dbdd171a8430e0e android.hardware.automotive.vehicle@2.0::types
a2fbd9747fbb9ceb8c1090b5a24138312246502d5af0654a8c2b603a9bf521fc android.hardware.gnss@1.0::IGnssCallback
+889b59e3e7a59afa67bf19882a44f51a2f9e43b6556ec52baa9ec3efd1ef7fbe android.hardware.camera.device@3.2::types
# There will be no more HIDL HALs. Use AIDL instead.
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 70c4e4c..4974e71 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -874,6 +874,13 @@
}
TEST_P(GraphicsComposerAidlTest, GetOverlaySupport) {
+ const auto& [versionStatus, version] = mComposerClient->getInterfaceVersion();
+ ASSERT_TRUE(versionStatus.isOk());
+ if (version == 1) {
+ GTEST_SUCCEED() << "Device does not support the new API for overlay support";
+ return;
+ }
+
const auto& [status, properties] = mComposerClient->getOverlaySupport();
if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl
index e543886..4d70588 100644
--- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryCapacityLevel.aidl
@@ -34,11 +34,11 @@
package android.hardware.health;
@Backing(type="int") @VintfStability
enum BatteryCapacityLevel {
- UNSUPPORTED = -1,
- UNKNOWN = 0,
- CRITICAL = 1,
- LOW = 2,
- NORMAL = 3,
- HIGH = 4,
- FULL = 5,
+ UNSUPPORTED = (-1) /* -1 */,
+ UNKNOWN,
+ CRITICAL,
+ LOW,
+ NORMAL,
+ HIGH,
+ FULL,
}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
index d523fad..2dd01b1 100644
--- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/BatteryHealthData.aidl
@@ -36,4 +36,5 @@
parcelable BatteryHealthData {
long batteryManufacturingDateSeconds;
long batteryFirstUsageSeconds;
+ long batteryStateOfHealth;
}
diff --git a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
index 664cc70..bfa1475 100644
--- a/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
+++ b/health/aidl/aidl_api/android.hardware.health/current/android/hardware/health/HealthInfo.aidl
@@ -57,9 +57,8 @@
android.hardware.health.BatteryCapacityLevel batteryCapacityLevel;
long batteryChargeTimeToFullNowSeconds;
int batteryFullChargeDesignCapacityUah;
- int batteryStateOfHealth;
android.hardware.health.BatteryChargingState chargingState;
android.hardware.health.BatteryChargingPolicy chargingPolicy;
@nullable android.hardware.health.BatteryHealthData batteryHealthData;
- const int BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = -1;
+ const int BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = (-1) /* -1 */;
}
diff --git a/health/aidl/android/hardware/health/BatteryHealthData.aidl b/health/aidl/android/hardware/health/BatteryHealthData.aidl
index fb17f63..594bcce 100644
--- a/health/aidl/android/hardware/health/BatteryHealthData.aidl
+++ b/health/aidl/android/hardware/health/BatteryHealthData.aidl
@@ -29,4 +29,11 @@
* The date of first usage is reported in epoch.
*/
long batteryFirstUsageSeconds;
+ /**
+ * Measured battery state of health (remaining estimate full charge capacity
+ * relative to the rated capacity in %).
+ * Value must be 0 if batteryStatus is UNKNOWN.
+ * Otherwise, value must be in the range 0 to 100.
+ */
+ long batteryStateOfHealth;
}
diff --git a/health/aidl/android/hardware/health/HealthInfo.aidl b/health/aidl/android/hardware/health/HealthInfo.aidl
index 238f524..af84089 100644
--- a/health/aidl/android/hardware/health/HealthInfo.aidl
+++ b/health/aidl/android/hardware/health/HealthInfo.aidl
@@ -137,13 +137,6 @@
*/
int batteryFullChargeDesignCapacityUah;
/**
- * Measured battery state of health (remaining estimate full charge capacity
- * relative to the rated capacity in %).
- * Value must be 0 if batteryStatus is UNKNOWN.
- * Otherwise, value must be in the range 0 to 100.
- */
- int batteryStateOfHealth;
- /**
* Battery charging state
*/
BatteryChargingState chargingState;
diff --git a/health/aidl/default/Health.cpp b/health/aidl/default/Health.cpp
index 15a3dbc..f401643 100644
--- a/health/aidl/default/Health.cpp
+++ b/health/aidl/default/Health.cpp
@@ -148,6 +148,11 @@
!res.isOk()) {
LOG(WARNING) << "Cannot get First_usage_date: " << res.getDescription();
}
+ if (auto res = GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_STATE_OF_HEALTH,
+ 0, &out->batteryStateOfHealth);
+ !res.isOk()) {
+ LOG(WARNING) << "Cannot get Battery_state_of_health: " << res.getDescription();
+ }
return ndk::ScopedAStatus::ok();
}
diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
index 6506ea2..69d4789 100644
--- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -278,6 +278,10 @@
*result_listener << " for batteryFirstUsageSeconds.";
return false;
}
+ if (!ExplainMatchResult(Ge(-1), arg.batteryStateOfHealth, result_listener)) {
+ *result_listener << " for batteryStateOfHealth.";
+ return false;
+ }
return true;
}
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index 26e91bd..ed3ca74 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -35,9 +35,12 @@
"libbinder_ndk",
"libcrypto",
"libbase",
+ "libgatekeeper",
"packagemanager_aidl-cpp",
],
static_libs: [
+ "android.hardware.gatekeeper@1.0",
+ "android.hardware.gatekeeper-V1-ndk",
"android.hardware.security.rkp-V3-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
@@ -59,6 +62,7 @@
],
srcs: [
"AttestKeyTest.cpp",
+ "AuthTest.cpp",
"DeviceUniqueAttestationTest.cpp",
"KeyBlobUpgradeTest.cpp",
"KeyMintTest.cpp",
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index cdcaaf3..bbf3633 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -106,7 +106,7 @@
// with any other key purpose, but the original VTS tests incorrectly did exactly that.
// This means that a device that launched prior to Android T (API level 33) may
// accept or even require KeyPurpose::SIGN too.
- if (property_get_int32("ro.board.first_api_level", 0) < 33) {
+ if (property_get_int32("ro.board.first_api_level", 0) < __ANDROID_API_T__) {
AuthorizationSet key_desc_plus_sign = key_desc;
key_desc_plus_sign.push_back(TAG_PURPOSE, KeyPurpose::SIGN);
@@ -142,11 +142,14 @@
return false;
}
- // Check if chipset has received a waiver allowing it to be launched with
- // Android S (or later) with Keymaster 4.0 in StrongBox
+ // Check if chipset has received a waiver allowing it to be launched with Android S or T with
+ // Keymaster 4.0 in StrongBox.
bool is_chipset_allowed_km4_strongbox(void) const {
std::array<char, PROPERTY_VALUE_MAX> buffer;
+ const int32_t first_api_level = property_get_int32("ro.board.first_api_level", 0);
+ if (first_api_level <= 0 || first_api_level > __ANDROID_API_T__) return false;
+
auto res = property_get("ro.vendor.qti.soc_model", buffer.data(), nullptr);
if (res <= 0) return false;
diff --git a/security/keymint/aidl/vts/functional/AuthTest.cpp b/security/keymint/aidl/vts/functional/AuthTest.cpp
new file mode 100644
index 0000000..a31ac01
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/AuthTest.cpp
@@ -0,0 +1,412 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "keymint_1_test"
+#include <cutils/log.h>
+
+#include <iostream>
+#include <optional>
+
+#include "KeyMintAidlTestBase.h"
+
+#include <aidl/android/hardware/gatekeeper/GatekeeperEnrollResponse.h>
+#include <aidl/android/hardware/gatekeeper/GatekeeperVerifyResponse.h>
+#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
+#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+using aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
+using aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
+using aidl::android::hardware::gatekeeper::IGatekeeper;
+using aidl::android::hardware::security::keymint::HardwareAuthToken;
+using aidl::android::hardware::security::secureclock::ISecureClock;
+
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <android/hardware/gatekeeper/1.0/types.h>
+#include <gatekeeper/password_handle.h> // for password_handle_t
+#include <hardware/hw_auth_token.h>
+
+using ::android::sp;
+using IHidlGatekeeper = ::android::hardware::gatekeeper::V1_0::IGatekeeper;
+using HidlGatekeeperResponse = ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
+using HidlGatekeeperStatusCode = ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
+
+namespace aidl::android::hardware::security::keymint::test {
+
+class AuthTest : public KeyMintAidlTestBase {
+ public:
+ void SetUp() {
+ KeyMintAidlTestBase::SetUp();
+
+ // Find the default Gatekeeper instance.
+ string gk_name = string(IGatekeeper::descriptor) + "/default";
+ if (AServiceManager_isDeclared(gk_name.c_str())) {
+ // Enroll a user with AIDL Gatekeeper.
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService(gk_name.c_str()));
+ gk_ = IGatekeeper::fromBinder(binder);
+ } else {
+ // Prior to Android U, Gatekeeper was HIDL not AIDL and so may not be present.
+ // Try to enroll user with HIDL Gatekeeper instead.
+ string gk_name = "default";
+ hidl_gk_ = IHidlGatekeeper::getService(gk_name.c_str());
+ if (hidl_gk_ == nullptr) {
+ std::cerr << "No HIDL Gatekeeper instance for '" << gk_name << "' found.\n";
+ return;
+ }
+ std::cerr << "No AIDL Gatekeeper instance for '" << gk_name << "' found, using HIDL.\n";
+ }
+
+ // If the device needs timestamps, find the default ISecureClock instance.
+ if (timestamp_token_required_) {
+ string clock_name = string(ISecureClock::descriptor) + "/default";
+ if (AServiceManager_isDeclared(clock_name.c_str())) {
+ ::ndk::SpAIBinder binder(AServiceManager_waitForService(clock_name.c_str()));
+ clock_ = ISecureClock::fromBinder(binder);
+ } else {
+ std::cerr << "No ISecureClock instance for '" << clock_name << "' found.\n";
+ }
+ }
+
+ // Enroll a password for a user.
+ uid_ = 10001;
+ password_ = "correcthorsebatterystaple";
+ std::optional<GatekeeperEnrollResponse> rsp = doEnroll(password_);
+ ASSERT_TRUE(rsp.has_value());
+ sid_ = rsp->secureUserId;
+ handle_ = rsp->data;
+ }
+
+ void TearDown() {
+ if (gk_ == nullptr) return;
+ gk_->deleteUser(uid_);
+ }
+
+ bool GatekeeperAvailable() { return (gk_ != nullptr) || (hidl_gk_ != nullptr); }
+
+ std::optional<GatekeeperEnrollResponse> doEnroll(const std::vector<uint8_t>& newPwd,
+ const std::vector<uint8_t>& curHandle = {},
+ const std::vector<uint8_t>& curPwd = {}) {
+ if (gk_ != nullptr) {
+ while (true) {
+ GatekeeperEnrollResponse rsp;
+ Status status = gk_->enroll(uid_, curHandle, curPwd, newPwd, &rsp);
+ if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
+ sleep(1);
+ continue;
+ }
+ if (status.isOk()) {
+ return std::move(rsp);
+ } else {
+ GTEST_LOG_(ERROR) << "doEnroll(AIDL) failed: " << status;
+ return std::nullopt;
+ }
+ }
+ } else if (hidl_gk_ != nullptr) {
+ while (true) {
+ HidlGatekeeperResponse rsp;
+ auto status = hidl_gk_->enroll(
+ uid_, curHandle, curPwd, newPwd,
+ [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
+ if (!status.isOk()) {
+ GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed";
+ return std::nullopt;
+ }
+ if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
+ sleep(1);
+ continue;
+ }
+ if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
+ GTEST_LOG_(ERROR) << "doEnroll(HIDL) failed with " << int(rsp.code);
+ return std::nullopt;
+ }
+ // "Parse" the returned data to get at the secure user ID.
+ if (rsp.data.size() != sizeof(::gatekeeper::password_handle_t)) {
+ GTEST_LOG_(ERROR)
+ << "HAL returned password handle of invalid length " << rsp.data.size();
+ return std::nullopt;
+ }
+ const ::gatekeeper::password_handle_t* handle =
+ reinterpret_cast<const ::gatekeeper::password_handle_t*>(rsp.data.data());
+
+ // Translate HIDL response to look like an AIDL response.
+ GatekeeperEnrollResponse aidl_rsp;
+ aidl_rsp.statusCode = IGatekeeper::STATUS_OK;
+ aidl_rsp.data = rsp.data;
+ aidl_rsp.secureUserId = handle->user_id;
+ return aidl_rsp;
+ }
+ } else {
+ return std::nullopt;
+ }
+ }
+
+ std::optional<GatekeeperEnrollResponse> doEnroll(const string& newPwd,
+ const std::vector<uint8_t>& curHandle = {},
+ const string& curPwd = {}) {
+ return doEnroll(std::vector<uint8_t>(newPwd.begin(), newPwd.end()), curHandle,
+ std::vector<uint8_t>(curPwd.begin(), curPwd.end()));
+ }
+
+ std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
+ const std::vector<uint8_t>& handle,
+ const std::vector<uint8_t>& pwd) {
+ if (gk_ != nullptr) {
+ while (true) {
+ GatekeeperVerifyResponse rsp;
+ Status status = gk_->verify(uid_, challenge, handle, pwd, &rsp);
+ if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IGatekeeper::ERROR_RETRY_TIMEOUT) {
+ sleep(1);
+ continue;
+ }
+ if (status.isOk()) {
+ return rsp.hardwareAuthToken;
+ } else {
+ GTEST_LOG_(ERROR) << "doVerify(AIDL) failed: " << status;
+ return std::nullopt;
+ }
+ }
+ } else if (hidl_gk_ != nullptr) {
+ while (true) {
+ HidlGatekeeperResponse rsp;
+ auto status = hidl_gk_->verify(
+ uid_, challenge, handle, pwd,
+ [&rsp](const HidlGatekeeperResponse& cbRsp) { rsp = cbRsp; });
+ if (!status.isOk()) {
+ GTEST_LOG_(ERROR) << "doVerify(HIDL) failed";
+ return std::nullopt;
+ }
+ if (rsp.code == HidlGatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
+ sleep(1);
+ continue;
+ }
+ if (rsp.code != HidlGatekeeperStatusCode::STATUS_OK) {
+ GTEST_LOG_(ERROR) << "doVerify(HIDL) failed with " << int(rsp.code);
+ return std::nullopt;
+ }
+ // "Parse" the returned data to get auth token contents.
+ if (rsp.data.size() != sizeof(hw_auth_token_t)) {
+ GTEST_LOG_(ERROR) << "Incorrect size of AuthToken payload.";
+ return std::nullopt;
+ }
+ const hw_auth_token_t* hwAuthToken =
+ reinterpret_cast<const hw_auth_token_t*>(rsp.data.data());
+ HardwareAuthToken authToken;
+ authToken.timestamp.milliSeconds = betoh64(hwAuthToken->timestamp);
+ authToken.challenge = hwAuthToken->challenge;
+ authToken.userId = hwAuthToken->user_id;
+ authToken.authenticatorId = hwAuthToken->authenticator_id;
+ authToken.authenticatorType = static_cast<HardwareAuthenticatorType>(
+ betoh32(hwAuthToken->authenticator_type));
+ authToken.mac.assign(&hwAuthToken->hmac[0], &hwAuthToken->hmac[32]);
+ return authToken;
+ }
+ } else {
+ return std::nullopt;
+ }
+ }
+ std::optional<HardwareAuthToken> doVerify(uint64_t challenge,
+ const std::vector<uint8_t>& handle,
+ const string& pwd) {
+ return doVerify(challenge, handle, std::vector<uint8_t>(pwd.begin(), pwd.end()));
+ }
+
+ // Variants of the base class methods but with authentication information included.
+ string ProcessMessage(const vector<uint8_t>& key_blob, KeyPurpose operation,
+ const string& message, const AuthorizationSet& in_params,
+ AuthorizationSet* out_params, const HardwareAuthToken& hat) {
+ AuthorizationSet begin_out_params;
+ ErrorCode result = Begin(operation, key_blob, in_params, out_params, hat);
+ EXPECT_EQ(ErrorCode::OK, result);
+ if (result != ErrorCode::OK) {
+ return "";
+ }
+
+ std::optional<secureclock::TimeStampToken> time_token = std::nullopt;
+ if (timestamp_token_required_ && clock_ != nullptr) {
+ // Ask a secure clock instance for a timestamp, including the per-op challenge.
+ secureclock::TimeStampToken token;
+ EXPECT_EQ(ErrorCode::OK,
+ GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &token)));
+ time_token = token;
+ }
+
+ string output;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &output, hat, time_token));
+ return output;
+ }
+
+ string EncryptMessage(const vector<uint8_t>& key_blob, const string& message,
+ const AuthorizationSet& in_params, AuthorizationSet* out_params,
+ const HardwareAuthToken& hat) {
+ SCOPED_TRACE("EncryptMessage");
+ return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params, hat);
+ }
+
+ string DecryptMessage(const vector<uint8_t>& key_blob, const string& ciphertext,
+ const AuthorizationSet& params, const HardwareAuthToken& hat) {
+ SCOPED_TRACE("DecryptMessage");
+ AuthorizationSet out_params;
+ string plaintext =
+ ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params, hat);
+ EXPECT_TRUE(out_params.empty());
+ return plaintext;
+ }
+
+ protected:
+ std::shared_ptr<IGatekeeper> gk_;
+ sp<IHidlGatekeeper> hidl_gk_;
+ std::shared_ptr<ISecureClock> clock_;
+ string password_;
+ uint32_t uid_;
+ long sid_;
+ std::vector<uint8_t> handle_;
+};
+
+// Test use of a key that requires user-authentication within recent history.
+TEST_P(AuthTest, TimeoutAuthentication) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+ if (timestamp_token_required_ && clock_ == nullptr) {
+ GTEST_SKIP() << "Device requires timestamps and no ISecureClock available";
+ }
+
+ // Create an AES key that requires authentication within the last 3 seconds.
+ const uint32_t timeout_secs = 3;
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
+ .Authorization(TAG_AUTH_TIMEOUT, timeout_secs);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Attempt to use the AES key without authentication.
+ const string message = "Hello World!";
+ AuthorizationSet out_params;
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+
+ // Verify to get a HAT, arbitrary challenge.
+ const uint64_t challenge = 42;
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+
+ // Adding the auth token makes it possible to use the AES key.
+ const string ciphertext = EncryptMessage(keyblob, message, params, &out_params, hat.value());
+ const string plaintext = DecryptMessage(keyblob, ciphertext, params, hat.value());
+ EXPECT_EQ(message, plaintext);
+
+ // Altering a single bit in the MAC means no auth.
+ HardwareAuthToken dodgy_hat = hat.value();
+ ASSERT_GT(dodgy_hat.mac.size(), 0);
+ dodgy_hat.mac[0] ^= 0x01;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, dodgy_hat));
+
+ // Wait for long enough that the hardware auth token expires.
+ sleep(timeout_secs + 1);
+ if (!timestamp_token_required_) {
+ // KeyMint implementation has its own clock, and can immediately detect timeout.
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
+ } else {
+ // KeyMint implementation has no clock, so only detects timeout via timestamp token provided
+ // on update()/finish().
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, hat));
+ secureclock::TimeStampToken time_token;
+ EXPECT_EQ(ErrorCode::OK,
+ GetReturnErrorCode(clock_->generateTimeStamp(challenge_, &time_token)));
+
+ string output;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &output, hat, time_token));
+ }
+}
+
+// Test use of a key that requires an auth token for each action on the operation, with
+// a per-operation challenge value included.
+TEST_P(AuthTest, AuthPerOperation) {
+ if (!GatekeeperAvailable()) {
+ GTEST_SKIP() << "No Gatekeeper available";
+ }
+
+ // Create an AES key that requires authentication per-action.
+ auto builder = AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_USER_SECURE_ID, sid_)
+ .Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD);
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ ASSERT_EQ(ErrorCode::OK,
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain));
+
+ // Attempt to use the AES key without authentication fails after begin.
+ const string message = "Hello World!";
+ AuthorizationSet out_params;
+ auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ string output;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED, Finish(message, {} /* signature */, &output));
+
+ // Verify to get a HAT, but with an arbitrary challenge.
+ const uint64_t unrelated_challenge = 42;
+ const std::optional<HardwareAuthToken> unrelated_hat =
+ doVerify(unrelated_challenge, handle_, password_);
+ ASSERT_TRUE(unrelated_hat.has_value());
+ EXPECT_EQ(unrelated_hat->userId, sid_);
+
+ // Attempt to use the AES key with an unrelated authentication fails after begin.
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params, unrelated_hat.value()));
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &output, unrelated_hat.value()));
+
+ // Now get a HAT with the challenge from an in-progress operation.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ const std::optional<HardwareAuthToken> hat = doVerify(challenge_, handle_, password_);
+ ASSERT_TRUE(hat.has_value());
+ EXPECT_EQ(hat->userId, sid_);
+ string ciphertext;
+ EXPECT_EQ(ErrorCode::OK, Finish(message, {} /* signature */, &ciphertext, hat.value()));
+
+ // Altering a single bit in the MAC means no auth.
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, keyblob, params, &out_params));
+ std::optional<HardwareAuthToken> dodgy_hat = doVerify(challenge_, handle_, password_);
+ ASSERT_TRUE(dodgy_hat.has_value());
+ EXPECT_EQ(dodgy_hat->userId, sid_);
+ ASSERT_GT(dodgy_hat->mac.size(), 0);
+ dodgy_hat->mac[0] ^= 0x01;
+ EXPECT_EQ(ErrorCode::KEY_USER_NOT_AUTHENTICATED,
+ Finish(message, {} /* signature */, &ciphertext, hat.value()));
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(AuthTest);
+
+} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 41d47ee..fb5ef49 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -108,27 +108,6 @@
return true;
}
-// Extract attestation record from cert. Returned object is still part of cert; don't free it
-// separately.
-ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
- ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
- EXPECT_TRUE(!!oid.get());
- if (!oid.get()) return nullptr;
-
- int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
- EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
- if (location == -1) return nullptr;
-
- X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
- EXPECT_TRUE(!!attest_rec_ext)
- << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug.";
- if (!attest_rec_ext) return nullptr;
-
- ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
- EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
- return attest_rec;
-}
-
void check_attestation_version(uint32_t attestation_version, int32_t aidl_version) {
// Version numbers in attestation extensions should be a multiple of 100.
EXPECT_EQ(attestation_version % 100, 0);
@@ -214,7 +193,7 @@
* which is mandatory for KeyMint version 2 or first_api_level 33 or greater.
*/
bool KeyMintAidlTestBase::isDeviceIdAttestationRequired() {
- return AidlVersion() >= 2 || property_get_int32("ro.vendor.api_level", 0) >= 33;
+ return AidlVersion() >= 2 || property_get_int32("ro.vendor.api_level", 0) >= __ANDROID_API_T__;
}
/**
@@ -222,7 +201,7 @@
* which is supported for KeyMint version 3 or first_api_level greater than 33.
*/
bool KeyMintAidlTestBase::isSecondImeiIdAttestationRequired() {
- return AidlVersion() >= 3 && property_get_int32("ro.vendor.api_level", 0) > 33;
+ return AidlVersion() >= 3 && property_get_int32("ro.vendor.api_level", 0) > __ANDROID_API_T__;
}
bool KeyMintAidlTestBase::Curve25519Supported() {
@@ -552,12 +531,13 @@
ErrorCode KeyMintAidlTestBase::Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
const AuthorizationSet& in_params,
- AuthorizationSet* out_params) {
+ AuthorizationSet* out_params,
+ std::optional<HardwareAuthToken> hat) {
SCOPED_TRACE("Begin");
Status result;
BeginResult out;
- result = keymint_->begin(purpose, key_blob, in_params.vector_data(), std::nullopt, &out);
+ result = keymint_->begin(purpose, key_blob, in_params.vector_data(), hat, &out);
if (result.isOk()) {
*out_params = out.params;
@@ -611,8 +591,9 @@
return GetReturnErrorCode(result);
}
-ErrorCode KeyMintAidlTestBase::Finish(const string& input, const string& signature,
- string* output) {
+ErrorCode KeyMintAidlTestBase::Finish(const string& input, const string& signature, string* output,
+ std::optional<HardwareAuthToken> hat,
+ std::optional<secureclock::TimeStampToken> time_token) {
SCOPED_TRACE("Finish");
Status result;
@@ -621,8 +602,8 @@
vector<uint8_t> oPut;
result = op_->finish(vector<uint8_t>(input.begin(), input.end()),
- vector<uint8_t>(signature.begin(), signature.end()), {} /* authToken */,
- {} /* timestampToken */, {} /* confirmationToken */, &oPut);
+ vector<uint8_t>(signature.begin(), signature.end()), hat, time_token,
+ {} /* confirmationToken */, &oPut);
if (result.isOk()) output->append(oPut.begin(), oPut.end());
@@ -845,7 +826,7 @@
int vendor_api_level = property_get_int32("ro.vendor.api_level", 0);
if (SecLevel() == SecurityLevel::STRONGBOX) {
// This is known to be broken on older vendor implementations.
- if (vendor_api_level < 33) {
+ if (vendor_api_level < __ANDROID_API_T__) {
compare_output = false;
} else {
additional_information = " (b/194134359) ";
@@ -1899,6 +1880,27 @@
return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
}
+// Extract attestation record from cert. Returned object is still part of cert; don't free it
+// separately.
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
+ ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+ EXPECT_TRUE(!!oid.get());
+ if (!oid.get()) return nullptr;
+
+ int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+ EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
+ if (location == -1) return nullptr;
+
+ X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+ EXPECT_TRUE(!!attest_rec_ext)
+ << "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug.";
+ if (!attest_rec_ext) return nullptr;
+
+ ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+ EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
+ return attest_rec;
+}
+
vector<uint8_t> make_name_from_str(const string& name) {
X509_NAME_Ptr x509_name(X509_NAME_new());
EXPECT_TRUE(x509_name.get() != nullptr);
@@ -2043,7 +2045,7 @@
}
void device_id_attestation_vsr_check(const ErrorCode& result) {
- if (get_vsr_api_level() >= 34) {
+ if (get_vsr_api_level() > __ANDROID_API_T__) {
ASSERT_FALSE(result == ErrorCode::INVALID_TAG)
<< "It is a specification violation for INVALID_TAG to be returned due to ID "
<< "mismatch in a Device ID Attestation call. INVALID_TAG is only intended to "
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 7c11b95..a6a9df6 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -161,7 +161,8 @@
const AuthorizationSet& in_params, AuthorizationSet* out_params,
std::shared_ptr<IKeyMintOperation>& op);
ErrorCode Begin(KeyPurpose purpose, const vector<uint8_t>& key_blob,
- const AuthorizationSet& in_params, AuthorizationSet* out_params);
+ const AuthorizationSet& in_params, AuthorizationSet* out_params,
+ std::optional<HardwareAuthToken> hat = std::nullopt);
ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
AuthorizationSet* out_params);
ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params);
@@ -169,7 +170,9 @@
ErrorCode UpdateAad(const string& input);
ErrorCode Update(const string& input, string* output);
- ErrorCode Finish(const string& message, const string& signature, string* output);
+ ErrorCode Finish(const string& message, const string& signature, string* output,
+ std::optional<HardwareAuthToken> hat = std::nullopt,
+ std::optional<secureclock::TimeStampToken> time_token = std::nullopt);
ErrorCode Finish(const string& message, string* output) {
return Finish(message, {} /* signature */, output);
}
@@ -398,6 +401,7 @@
string bin2hex(const vector<uint8_t>& data);
X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate);
vector<uint8_t> make_name_from_str(const string& name);
void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
vector<uint8_t>* payload_value);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 357405f..9e66f08 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1136,7 +1136,7 @@
* that has been generated using an associate IRemotelyProvisionedComponent.
*/
TEST_P(NewKeyGenerationTest, RsaWithRkpAttestation) {
- if (get_vsr_api_level() < 32 || AidlVersion() < 2) {
+ if (get_vsr_api_level() < __ANDROID_API_T__ || AidlVersion() < 2) {
GTEST_SKIP() << "Only required for VSR 12+ and KeyMint 2+";
}
@@ -1214,7 +1214,7 @@
* that has been generated using an associate IRemotelyProvisionedComponent.
*/
TEST_P(NewKeyGenerationTest, EcdsaWithRkpAttestation) {
- if (get_vsr_api_level() <= 32 || AidlVersion() < 2) {
+ if (get_vsr_api_level() < __ANDROID_API_T__ || AidlVersion() < 2) {
GTEST_SKIP() << "Only required for VSR 12+ and KeyMint 2+";
}
@@ -8629,7 +8629,7 @@
TEST_P(VsrRequirementTest, Vsr13Test) {
int vsr_api_level = get_vsr_api_level();
- if (vsr_api_level < 33) {
+ if (vsr_api_level < __ANDROID_API_T__) {
GTEST_SKIP() << "Applies only to VSR API level 33, this device is: " << vsr_api_level;
}
EXPECT_GE(AidlVersion(), 2) << "VSR 13+ requires KeyMint version 2";
@@ -8637,7 +8637,7 @@
TEST_P(VsrRequirementTest, Vsr14Test) {
int vsr_api_level = get_vsr_api_level();
- if (vsr_api_level < 34) {
+ if (vsr_api_level < __ANDROID_API_U__) {
GTEST_SKIP() << "Applies only to VSR API level 34, this device is: " << vsr_api_level;
}
EXPECT_GE(AidlVersion(), 3) << "VSR 14+ requires KeyMint version 3";
diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 573f10b..bf40976 100644
--- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -23,6 +23,7 @@
#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
#include <android/binder_manager.h>
#include <binder/IServiceManager.h>
+#include <cppbor.h>
#include <cppbor_parse.h>
#include <gmock/gmock.h>
#include <keymaster/cppcose/cppcose.h>
@@ -797,6 +798,128 @@
BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
}
+void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
+ vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
+ bool* device_locked, vector<uint8_t>* verified_boot_hash) {
+ X509_Ptr cert(parse_cert_blob(attestation_cert));
+ ASSERT_TRUE(cert.get());
+
+ ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+ ASSERT_TRUE(attest_rec);
+
+ auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
+ verified_boot_state, device_locked, verified_boot_hash);
+ ASSERT_EQ(error, ErrorCode::OK);
+}
+
+/**
+ * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
+ */
+TEST_P(CertificateRequestV2Test, DeviceInfo) {
+ // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
+ std::shared_ptr<IKeyMintDevice> keyMint;
+ if (!matching_keymint_device(GetParam(), &keyMint)) {
+ // No matching IKeyMintDevice.
+ GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
+ return;
+ }
+ KeyMintHardwareInfo info;
+ ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
+
+ // Get IDs attested by KeyMint.
+ MacedPublicKey macedPubKey;
+ bytevec privateKeyBlob;
+ auto irpcStatus =
+ provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
+ ASSERT_TRUE(irpcStatus.isOk());
+
+ AttestationKey attestKey;
+ attestKey.keyBlob = std::move(privateKeyBlob);
+ attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
+
+ // Generate an ECDSA key that is attested by the generated P256 keypair.
+ AuthorizationSet keyDesc = AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .AttestationChallenge("foo")
+ .AttestationApplicationId("bar")
+ .Digest(Digest::NONE)
+ .SetDefaultValidity();
+ KeyCreationResult creationResult;
+ auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
+ ASSERT_TRUE(kmStatus.isOk());
+
+ vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
+ vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
+ // We didn't provision the attestation key.
+ ASSERT_EQ(key_cert_chain.size(), 1);
+
+ // Parse attested patch levels.
+ auto auths = HwEnforcedAuthorizations(key_characteristics);
+
+ auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
+ auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
+ auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
+
+ ASSERT_TRUE(attestedSystemPatchLevel.has_value());
+ ASSERT_TRUE(attestedVendorPatchLevel.has_value());
+ ASSERT_TRUE(attestedBootPatchLevel.has_value());
+
+ // Parse attested AVB values.
+ vector<uint8_t> key;
+ VerifiedBoot attestedVbState;
+ bool attestedBootloaderState;
+ vector<uint8_t> attestedVbmetaDigest;
+ parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
+ &attestedBootloaderState, &attestedVbmetaDigest);
+
+ // Get IDs from DeviceInfo.
+ bytevec csr;
+ irpcStatus =
+ provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
+ ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage();
+
+ auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(result) << result.message();
+
+ std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
+ ASSERT_TRUE(csrPayload);
+
+ auto deviceInfo = csrPayload->get(2)->asMap();
+ ASSERT_TRUE(deviceInfo);
+
+ auto vbState = deviceInfo->get("vb_state")->asTstr();
+ auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
+ auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
+ auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
+ auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
+ auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
+ auto securityLevel = deviceInfo->get("security_level")->asTstr();
+
+ ASSERT_TRUE(vbState);
+ ASSERT_TRUE(bootloaderState);
+ ASSERT_TRUE(vbmetaDigest);
+ ASSERT_TRUE(systemPatchLevel);
+ ASSERT_TRUE(vendorPatchLevel);
+ ASSERT_TRUE(bootPatchLevel);
+ ASSERT_TRUE(securityLevel);
+
+ auto kmDeviceName = device_suffix(GetParam());
+
+ // Compare DeviceInfo against IDs attested by KeyMint.
+ ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
+ (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
+ ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
+ (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
+ (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
+ ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
+ (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
+ ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
+ ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
+ ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
+ ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
+}
+
INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
diff --git a/staging/threadnetwork/aidl/Android.bp b/staging/threadnetwork/aidl/Android.bp
index fcd3ab8..b59d6da 100644
--- a/staging/threadnetwork/aidl/Android.bp
+++ b/staging/threadnetwork/aidl/Android.bp
@@ -1,3 +1,12 @@
+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"],
+}
+
aidl_interface {
name: "android.hardware.threadnetwork",
host_supported: true,
diff --git a/staging/threadnetwork/aidl/default/Android.bp b/staging/threadnetwork/aidl/default/Android.bp
index c701295..8fc22ad 100644
--- a/staging/threadnetwork/aidl/default/Android.bp
+++ b/staging/threadnetwork/aidl/default/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+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_defaults {
name: "threadnetwork_service_default",
vendor: true,
diff --git a/staging/threadnetwork/aidl/vts/Android.bp b/staging/threadnetwork/aidl/vts/Android.bp
index 70386d9..e2609ed 100644
--- a/staging/threadnetwork/aidl/vts/Android.bp
+++ b/staging/threadnetwork/aidl/vts/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+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_test {
name: "VtsHalThreadNetworkTargetTest",
defaults: [
diff --git a/thermal/utils/Android.bp b/thermal/utils/Android.bp
new file mode 100644
index 0000000..72e1e34
--- /dev/null
+++ b/thermal/utils/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_library_static {
+ name: "libthermalutils",
+ vendor_available: true,
+ export_include_dirs: ["include"],
+ srcs: [
+ "ThermalHidlWrapper.cpp",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "android.hardware.thermal@2.0",
+ "android.hardware.thermal-V1-ndk",
+ ],
+}
diff --git a/thermal/utils/ThermalHidlWrapper.cpp b/thermal/utils/ThermalHidlWrapper.cpp
new file mode 100644
index 0000000..05a992a
--- /dev/null
+++ b/thermal/utils/ThermalHidlWrapper.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+#include "include/thermalutils/ThermalHidlWrapper.h"
+
+#include <hidl/HidlTransportSupport.h>
+
+#include <cmath>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace thermal {
+
+using ::android::hardware::Void;
+
+namespace {
+
+template <typename T, typename U>
+Return<void> setFailureAndCallback(T _hidl_cb, hidl_vec<U> data, std::string_view debug_msg) {
+ ThermalStatus status;
+ status.code = ThermalStatusCode::FAILURE;
+ status.debugMessage = debug_msg.data();
+ _hidl_cb(status, data);
+ return Void();
+}
+
+template <typename T>
+Return<void> setFailureAndCallback(T _hidl_cb, std::string_view debug_msg) {
+ ThermalStatus status;
+ status.code = ThermalStatusCode::FAILURE;
+ status.debugMessage = debug_msg.data();
+ _hidl_cb(status);
+ return Void();
+}
+
+template <typename T, typename U>
+Return<void> setInitFailureAndCallback(T _hidl_cb, hidl_vec<U> data) {
+ return setFailureAndCallback(
+ _hidl_cb, data, "Thermal AIDL HAL client used by HIDL wrapper was not initialized");
+}
+
+template <typename T>
+Return<void> setInitFailureAndCallback(T _hidl_cb) {
+ return setFailureAndCallback(
+ _hidl_cb, "Thermal AIDL HAL client used by HIDL wrapper was not initialized");
+}
+
+template <typename T, typename U>
+Return<void> setUnsupportedFailureAndCallback(T _hidl_cb, hidl_vec<U> data) {
+ return setFailureAndCallback(_hidl_cb, data, "Operation unsupported by Thermal HIDL wrapper");
+}
+
+TemperatureType_2_0 convertAidlTemperatureType(const TemperatureType& type) {
+ if (type < TemperatureType::CPU || type > TemperatureType::NPU) {
+ return TemperatureType_2_0::UNKNOWN;
+ }
+ return static_cast<TemperatureType_2_0>(type);
+}
+
+CoolingType_2_0 convertAidlCoolingType(const CoolingType& type) {
+ if (type < CoolingType::FAN || type > CoolingType::COMPONENT) {
+ return CoolingType_2_0::COMPONENT;
+ }
+ return static_cast<CoolingType_2_0>(type);
+}
+
+Temperature_2_0 convertAidlTemperature(const Temperature& temperature) {
+ Temperature_2_0 t = Temperature_2_0{
+ convertAidlTemperatureType(temperature.type), temperature.name, temperature.value,
+ static_cast<ThrottlingSeverity_2_0>(temperature.throttlingStatus)};
+ return t;
+}
+
+CoolingDevice_2_0 convertAidlCoolingDevice(const CoolingDevice& cooling_device) {
+ CoolingDevice_2_0 t =
+ CoolingDevice_2_0{convertAidlCoolingType(cooling_device.type), cooling_device.name,
+ static_cast<uint64_t>(cooling_device.value)};
+ return t;
+}
+TemperatureThreshold_2_0 convertAidlTemperatureThreshold(const TemperatureThreshold& threshold) {
+ TemperatureThreshold_2_0 t =
+ TemperatureThreshold_2_0{convertAidlTemperatureType(threshold.type), threshold.name,
+ threshold.hotThrottlingThresholds.data(),
+ threshold.coldThrottlingThresholds.data(), NAN};
+ return t;
+}
+
+} // namespace
+
+// Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+Return<void> ThermalHidlWrapper::getTemperatures(getTemperatures_cb _hidl_cb) {
+ hidl_vec<Temperature_1_0> ret_1_0;
+ setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::getCpuUsages(
+ std::function<void(const ThermalStatus&, const hidl_vec<CpuUsage>&)> _hidl_cb) {
+ hidl_vec<CpuUsage> ret_1_0;
+ setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::getCoolingDevices(
+ std::function<void(const ThermalStatus&, const hidl_vec<CoolingDevice_1_0>&)> _hidl_cb) {
+ hidl_vec<CoolingDevice_1_0> ret_1_0;
+ setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
+ return Void();
+}
+
+// Methods from ::android::hardware::thermal::V2_0::IThermal follow.
+Return<void> ThermalHidlWrapper::getCurrentTemperatures(
+ bool filterType, TemperatureType_2_0 type,
+ std::function<void(const ThermalStatus&, const hidl_vec<Temperature_2_0>&)> _hidl_cb) {
+ hidl_vec<Temperature_2_0> ret_2_0;
+ if (!thermal_service_) {
+ setInitFailureAndCallback(_hidl_cb, ret_2_0);
+ }
+
+ std::vector<Temperature> ret_aidl;
+ ThermalStatus status;
+ ::ndk::ScopedAStatus a_status;
+ if (filterType) {
+ a_status = thermal_service_->getTemperaturesWithType(static_cast<TemperatureType>(type),
+ &ret_aidl);
+ } else {
+ a_status = thermal_service_->getTemperatures(&ret_aidl);
+ }
+ if (a_status.isOk()) {
+ std::vector<Temperature_2_0> ret;
+ for (const auto& temperature : ret_aidl) {
+ ret.push_back(convertAidlTemperature(temperature));
+ }
+ _hidl_cb(status, hidl_vec<Temperature_2_0>(ret));
+ } else {
+ setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
+ }
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::getTemperatureThresholds(
+ bool filterType, TemperatureType_2_0 type,
+ std::function<void(const ThermalStatus&, const hidl_vec<TemperatureThreshold_2_0>&)>
+ _hidl_cb) {
+ hidl_vec<TemperatureThreshold_2_0> ret_2_0;
+ if (!thermal_service_) {
+ setInitFailureAndCallback(_hidl_cb, ret_2_0);
+ }
+
+ std::vector<TemperatureThreshold> ret_aidl;
+ ThermalStatus status;
+ ::ndk::ScopedAStatus a_status;
+ if (filterType) {
+ a_status = thermal_service_->getTemperatureThresholdsWithType(
+ static_cast<TemperatureType>(type), &ret_aidl);
+ } else {
+ a_status = thermal_service_->getTemperatureThresholds(&ret_aidl);
+ }
+ if (a_status.isOk()) {
+ std::vector<TemperatureThreshold_2_0> ret;
+ for (const auto& threshold : ret_aidl) {
+ ret.push_back(convertAidlTemperatureThreshold(threshold));
+ }
+ _hidl_cb(status, hidl_vec<TemperatureThreshold_2_0>(ret));
+ } else {
+ setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
+ }
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::registerThermalChangedCallback(
+ const sp<IThermalChangedCallback_2_0>& callback, bool filterType, TemperatureType_2_0 type,
+ std::function<void(const ThermalStatus&)> _hidl_cb) {
+ if (!thermal_service_) {
+ setInitFailureAndCallback(_hidl_cb);
+ }
+ if (callback == nullptr) {
+ setFailureAndCallback(_hidl_cb, "Invalid nullptr callback");
+ return Void();
+ }
+ std::lock_guard<std::mutex> _lock(callback_wrappers_mutex_);
+ for (const auto& callback_wrapper : callback_wrappers_) {
+ if (::android::hardware::interfacesEqual(callback_wrapper->callback_2_0_.get(),
+ callback.get())) {
+ setFailureAndCallback(_hidl_cb, "The callback was already registered through wrapper");
+ return Void();
+ }
+ }
+ std::shared_ptr<IThermalChangedCallbackWrapper> callback_wrapper =
+ ndk::SharedRefBase::make<IThermalChangedCallbackWrapper>(callback);
+ ::ndk::ScopedAStatus a_status;
+ ThermalStatus status;
+ if (filterType) {
+ a_status = thermal_service_->registerThermalChangedCallbackWithType(
+ callback_wrapper, static_cast<TemperatureType>(type));
+ } else {
+ a_status = thermal_service_->registerThermalChangedCallback(callback_wrapper);
+ }
+ if (a_status.isOk()) {
+ callback_wrappers_.push_back(callback_wrapper);
+ _hidl_cb(status);
+ } else {
+ setFailureAndCallback(_hidl_cb, a_status.getMessage());
+ }
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::unregisterThermalChangedCallback(
+ const sp<IThermalChangedCallback_2_0>& callback,
+ std::function<void(const ThermalStatus&)> _hidl_cb) {
+ if (!thermal_service_) {
+ setInitFailureAndCallback(_hidl_cb);
+ }
+ if (callback == nullptr) {
+ setFailureAndCallback(_hidl_cb, "Invalid nullptr callback");
+ return Void();
+ }
+ std::lock_guard<std::mutex> _lock(callback_wrappers_mutex_);
+ for (auto it = callback_wrappers_.begin(); it != callback_wrappers_.end(); it++) {
+ auto callback_wrapper = *it;
+ if (::android::hardware::interfacesEqual(callback_wrapper->callback_2_0_.get(),
+ callback.get())) {
+ ::ndk::ScopedAStatus a_status;
+ ThermalStatus status;
+ a_status = thermal_service_->unregisterThermalChangedCallback(callback_wrapper);
+ if (a_status.isOk()) {
+ callback_wrappers_.erase(it);
+ _hidl_cb(status);
+ } else {
+ setFailureAndCallback(_hidl_cb, a_status.getMessage());
+ }
+ return Void();
+ }
+ }
+ setFailureAndCallback(_hidl_cb, "The callback was not registered through wrapper before");
+ return Void();
+}
+
+Return<void> ThermalHidlWrapper::getCurrentCoolingDevices(
+ bool filterType, CoolingType_2_0 type,
+ std::function<void(const ThermalStatus&, const hidl_vec<CoolingDevice_2_0>&)> _hidl_cb) {
+ hidl_vec<CoolingDevice_2_0> ret_2_0;
+ if (!thermal_service_) {
+ setInitFailureAndCallback(_hidl_cb, ret_2_0);
+ }
+
+ std::vector<CoolingDevice> ret_aidl;
+ ThermalStatus status;
+ ::ndk::ScopedAStatus a_status;
+ if (filterType) {
+ a_status = thermal_service_->getCoolingDevicesWithType(static_cast<CoolingType>(type),
+ &ret_aidl);
+ } else {
+ a_status = thermal_service_->getCoolingDevices(&ret_aidl);
+ }
+ if (a_status.isOk()) {
+ std::vector<CoolingDevice_2_0> ret;
+ for (const auto& cooling_device : ret_aidl) {
+ ret.push_back(convertAidlCoolingDevice(cooling_device));
+ }
+ _hidl_cb(status, hidl_vec<CoolingDevice_2_0>(ret));
+ } else {
+ setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
+ }
+ return Void();
+}
+
+// Methods from ::android::hidl::base::V1_0::IBase follow.
+Return<void> ThermalHidlWrapper::debug(const hidl_handle& handle,
+ const hidl_vec<hidl_string>& args) {
+ if (handle != nullptr && handle->numFds >= 1) {
+ int fd = handle->data[0];
+ char** arr = new char*[args.size()];
+ for (size_t i = 0; i < args.size(); i++) {
+ arr[i] = strdup(args[i].c_str());
+ }
+ thermal_service_->dump(fd, (const char**)arr, args.size());
+ }
+ return Void();
+}
+
+::ndk::ScopedAStatus ThermalHidlWrapper::IThermalChangedCallbackWrapper::notifyThrottling(
+ const Temperature& temperature) {
+ callback_2_0_->notifyThrottling(convertAidlTemperature(temperature));
+ return ::ndk::ScopedAStatus::ok();
+}
+
+} // namespace thermal
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/thermal/utils/include/thermalutils/ThermalHidlWrapper.h b/thermal/utils/include/thermalutils/ThermalHidlWrapper.h
new file mode 100644
index 0000000..1fec100
--- /dev/null
+++ b/thermal/utils/include/thermalutils/ThermalHidlWrapper.h
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <aidl/android/hardware/thermal/IThermal.h>
+#include <android/hardware/thermal/2.0/IThermal.h>
+#include <android/hardware/thermal/2.0/IThermalChangedCallback.h>
+#include <android/hardware/thermal/2.0/types.h>
+#include <hidl/Status.h>
+
+#include <utility>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace thermal {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+using IThermal_Aidl = ::aidl::android::hardware::thermal::IThermal;
+using ::android::hardware::thermal::V1_0::CpuUsage;
+using CoolingType_2_0 = ::android::hardware::thermal::V2_0::CoolingType;
+using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
+using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
+using IThermal_2_0 = ::android::hardware::thermal::V2_0::IThermal;
+using IThermalChangedCallback_2_0 = ::android::hardware::thermal::V2_0::IThermalChangedCallback;
+using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
+using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
+using TemperatureType_2_0 = ::android::hardware::thermal::V2_0::TemperatureType;
+
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
+
+using TemperatureThreshold_2_0 = ::android::hardware::thermal::V2_0::TemperatureThreshold;
+using ThrottlingSeverity_2_0 = ::android::hardware::thermal::V2_0::ThrottlingSeverity;
+
+// This wrapper converts all Thermal HIDL 2.0 calls to AIDL calls and converts AIDL response to
+// HIDL 2.0 response.
+//
+// For Thermal HIDL 1.0 calls, it returns unsupported error.
+class ThermalHidlWrapper : public IThermal_2_0 {
+ public:
+ explicit ThermalHidlWrapper(::std::shared_ptr<IThermal_Aidl> thermal_service)
+ : thermal_service_(std::move(thermal_service)) {}
+
+ // Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+ Return<void> getTemperatures(getTemperatures_cb _hidl_cb) override;
+ Return<void> getCpuUsages(getCpuUsages_cb _hidl_cb) override;
+ Return<void> getCoolingDevices(getCoolingDevices_cb _hidl_cb) override;
+
+ // Methods from ::android::hardware::thermal::V2_0::IThermal follow.
+ Return<void> getCurrentTemperatures(bool filterType, TemperatureType_2_0 type,
+ getCurrentTemperatures_cb _hidl_cb) override;
+ Return<void> getTemperatureThresholds(bool filterType, TemperatureType_2_0 type,
+ getTemperatureThresholds_cb _hidl_cb) override;
+ Return<void> registerThermalChangedCallback(
+ const sp<IThermalChangedCallback_2_0>& callback, bool filterType,
+ TemperatureType_2_0 type, registerThermalChangedCallback_cb _hidl_cb) override;
+ Return<void> unregisterThermalChangedCallback(
+ const sp<IThermalChangedCallback_2_0>& callback,
+ unregisterThermalChangedCallback_cb _hidl_cb) override;
+ Return<void> getCurrentCoolingDevices(bool filterType, CoolingType_2_0 type,
+ getCurrentCoolingDevices_cb _hidl_cb) override;
+
+ // Methods from ::android::hidl::base::V1_0::IBase follow.
+ Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& args) override;
+
+ private:
+ class IThermalChangedCallbackWrapper : public BnThermalChangedCallback {
+ public:
+ explicit IThermalChangedCallbackWrapper(const sp<IThermalChangedCallback_2_0>& callback_2_0)
+ : callback_2_0_(callback_2_0) {}
+ ::ndk::ScopedAStatus notifyThrottling(const Temperature& temperature) override;
+ sp<IThermalChangedCallback_2_0> callback_2_0_;
+ };
+
+ // Reference to thermal service.
+ ::std::shared_ptr<IThermal_Aidl> thermal_service_;
+ // Mutex lock for read/write on callback wrappers.
+ std::mutex callback_wrappers_mutex_;
+ // All thermal changed callback wrappers registered.
+ ::std::vector<std::shared_ptr<IThermalChangedCallbackWrapper>> callback_wrappers_;
+};
+
+} // namespace thermal
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/thermal/utils/tests/Android.bp b/thermal/utils/tests/Android.bp
new file mode 100644
index 0000000..fd74e8b
--- /dev/null
+++ b/thermal/utils/tests/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "ThermalHidlWrapperTest",
+ srcs: ["ThermalHidlWrapperTest.cpp"],
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "android.hardware.thermal@1.0",
+ "android.hardware.thermal@2.0",
+ "android.hardware.thermal-V1-ndk",
+ ],
+ static_libs: [
+ "libthermalutils",
+ "libgtest",
+ ],
+ test_suites: [
+ "device-tests",
+ ],
+}
diff --git a/thermal/utils/tests/ThermalHidlWrapperTest.cpp b/thermal/utils/tests/ThermalHidlWrapperTest.cpp
new file mode 100644
index 0000000..1723a1a
--- /dev/null
+++ b/thermal/utils/tests/ThermalHidlWrapperTest.cpp
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "thermal_hidl_wrapper_test"
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/thermal/BnThermal.h>
+#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <android/hardware/thermal/2.0/IThermal.h>
+#include <android/hardware/thermal/2.0/IThermalChangedCallback.h>
+#include <android/hardware/thermal/2.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <thermalutils/ThermalHidlWrapper.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <chrono>
+#include <cmath>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+namespace aidl::android::hardware::thermal {
+
+namespace {
+
+using ::android::sp;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
+using ::android::hardware::thermal::V2_0::CoolingDevice;
+using ::android::hardware::thermal::V2_0::CoolingType;
+using IThermal_2_0 = ::android::hardware::thermal::V2_0::IThermal;
+using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
+using ::android::hardware::thermal::V2_0::Temperature;
+using ::android::hardware::thermal::V2_0::TemperatureThreshold;
+using ::android::hardware::thermal::V2_0::TemperatureType;
+using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
+
+constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
+static const Temperature kThrottleTemp = {
+ .type = TemperatureType::SKIN,
+ .name = "test temperature sensor",
+ .value = 98.6,
+ .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+class ThermalCallbackArgs {
+ public:
+ Temperature temperature;
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
+ public IThermalChangedCallback {
+ public:
+ Return<void> notifyThrottling(const Temperature& temperature) override {
+ ThermalCallbackArgs args;
+ args.temperature = temperature;
+ NotifyFromCallback(kCallbackNameNotifyThrottling, args);
+ return Void();
+ }
+};
+
+// The main test class for THERMAL HIDL HAL 2.0.
+class ThermalHidlWrapperTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+ ASSERT_NE(binder, nullptr);
+ mThermal = sp<ThermalHidlWrapper>::make(IThermal::fromBinder(ndk::SpAIBinder(binder)));
+ ASSERT_NE(mThermal, nullptr);
+ mThermalCallback = new (std::nothrow) ThermalCallback();
+ ASSERT_NE(mThermalCallback, nullptr);
+ auto ret = mThermal->registerThermalChangedCallback(
+ mThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if register again
+ ret = mThermal->registerThermalChangedCallback(
+ mThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ void TearDown() override {
+ auto ret = mThermal->unregisterThermalChangedCallback(
+ mThermalCallback,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if unregister again
+ ret = mThermal->unregisterThermalChangedCallback(
+ mThermalCallback,
+ [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ }
+
+ protected:
+ sp<IThermal_2_0> mThermal;
+ sp<ThermalCallback> mThermalCallback;
+}; // class ThermalHidlWrapperTest
+
+// Test ThermalChangedCallback::notifyThrottling().
+// This just calls into and back from our local ThermalChangedCallback impl.
+TEST_P(ThermalHidlWrapperTest, NotifyThrottlingTest) {
+ sp<ThermalCallback> thermalCallback = new (std::nothrow) ThermalCallback();
+ auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
+ ASSERT_TRUE(ret.isOk());
+ auto res = thermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
+ EXPECT_TRUE(res.no_timeout);
+ ASSERT_TRUE(res.args);
+ EXPECT_EQ(kThrottleTemp, res.args->temperature);
+}
+
+// Test Thermal->registerThermalChangedCallback.
+TEST_P(ThermalHidlWrapperTest, RegisterThermalChangedCallbackTest) {
+ // Expect to fail with same callback
+ auto ret = mThermal->registerThermalChangedCallback(
+ mThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail with null callback
+ ret = mThermal->registerThermalChangedCallback(
+ nullptr, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::FAILURE, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
+ // Expect to succeed with different callback
+ ret = mThermal->registerThermalChangedCallback(
+ localThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Remove the local callback
+ ret = mThermal->unregisterThermalChangedCallback(
+ localThermalCallback,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail with null callback
+ ret = mThermal->unregisterThermalChangedCallback(nullptr, [](ThermalStatus status) {
+ EXPECT_EQ(ThermalStatusCode::FAILURE, status.code);
+ });
+ ASSERT_TRUE(ret.isOk());
+}
+
+// Test Thermal->unregisterThermalChangedCallback.
+TEST_P(ThermalHidlWrapperTest, UnregisterThermalChangedCallbackTest) {
+ sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
+ // Expect to fail as the callback was not registered before
+ auto ret = mThermal->unregisterThermalChangedCallback(
+ localThermalCallback,
+ [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Register a local callback
+ ret = mThermal->registerThermalChangedCallback(
+ localThermalCallback, false, TemperatureType::SKIN,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to succeed with callback removed
+ ret = mThermal->unregisterThermalChangedCallback(
+ localThermalCallback,
+ [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail as the callback has been unregistered already
+ ret = mThermal->unregisterThermalChangedCallback(
+ localThermalCallback,
+ [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+ ASSERT_TRUE(ret.isOk());
+}
+
+// Sanity test for Thermal::getCurrentTemperatures().
+TEST_P(ThermalHidlWrapperTest, TemperatureTest) {
+ mThermal->getCurrentTemperatures(false, TemperatureType::SKIN,
+ [](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+ if (temperatures.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ for (int i = 0; i < temperatures.size(); ++i) {
+ EXPECT_LT(0u, temperatures[i].name.size());
+ }
+ });
+ auto types = hidl_enum_range<TemperatureType>();
+ for (const auto& type : types) {
+ mThermal->getCurrentTemperatures(
+ true, type, [&type](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+ if (temperatures.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ for (int i = 0; i < temperatures.size(); ++i) {
+ EXPECT_EQ(type, temperatures[i].type);
+ EXPECT_LT(0u, temperatures[i].name.size());
+ }
+ });
+ }
+}
+
+// Sanity test for Thermal::getTemperatureThresholds().
+TEST_P(ThermalHidlWrapperTest, TemperatureThresholdTest) {
+ mThermal->getTemperatureThresholds(
+ false, TemperatureType::SKIN,
+ [](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
+ if (temperatures.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ });
+ for (int i = static_cast<int>(TemperatureType::UNKNOWN);
+ i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
+ auto type = static_cast<TemperatureType>(i);
+ mThermal->getTemperatureThresholds(
+ true, type,
+ [&type](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
+ if (temperatures.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ for (int i = 0; i < temperatures.size(); ++i) {
+ EXPECT_EQ(type, temperatures[i].type);
+ }
+ });
+ }
+}
+
+// Sanity test for Thermal::getCurrentCoolingDevices().
+TEST_P(ThermalHidlWrapperTest, CoolingDeviceTest) {
+ mThermal->getCurrentCoolingDevices(
+ false, CoolingType::CPU,
+ [](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
+ if (cooling_devices.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ for (int i = 0; i < cooling_devices.size(); ++i) {
+ EXPECT_LT(0u, cooling_devices[i].name.size());
+ }
+ });
+ for (int i = 0; i <= static_cast<int>(CoolingType::COMPONENT); ++i) {
+ auto type = static_cast<CoolingType>(i);
+ mThermal->getCurrentCoolingDevices(
+ true, type, [&type](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
+ if (cooling_devices.size()) {
+ EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+ } else {
+ EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+ }
+ for (int i = 0; i < cooling_devices.size(); ++i) {
+ EXPECT_EQ(type, cooling_devices[i].type);
+ EXPECT_LT(0u, cooling_devices[i].name.size());
+ }
+ });
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalHidlWrapperTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ThermalHidlWrapperTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
+ ::android::hardware::PrintInstanceNameToString);
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
+
+} // namespace aidl::android::hardware::thermal
diff --git a/tv/cec/1.0/default/HdmiCecDefault.cpp b/tv/cec/1.0/default/HdmiCecDefault.cpp
index 26ccb7d..2a5197c 100644
--- a/tv/cec/1.0/default/HdmiCecDefault.cpp
+++ b/tv/cec/1.0/default/HdmiCecDefault.cpp
@@ -278,6 +278,10 @@
Return<bool> HdmiCecDefault::isConnected(int32_t portId) {
uint16_t addr;
+ if (portId < 0 || portId >= mHdmiCecPorts.size()) {
+ LOG(ERROR) << "Port id is out of bounds, portId = " << portId;
+ return false;
+ }
int ret = ioctl(mHdmiCecPorts[portId]->mCecFd, CEC_ADAP_G_PHYS_ADDR, &addr);
if (ret) {
LOG(ERROR) << "Is connected failed, Error = " << strerror(errno);
diff --git a/wifi/aidl/android/hardware/wifi/MacAddress.aidl b/wifi/aidl/android/hardware/wifi/MacAddress.aidl
index d59dfe3..d238565 100644
--- a/wifi/aidl/android/hardware/wifi/MacAddress.aidl
+++ b/wifi/aidl/android/hardware/wifi/MacAddress.aidl
@@ -20,8 +20,6 @@
* Byte array representing a Mac Address. Use when we need to
* pass an array of Mac Addresses to a method, as variable-sized
* 2D arrays are not supported in AIDL.
- *
- * TODO (b/210705533): Replace this type with a 2D byte array.
*/
@VintfStability
parcelable MacAddress {
diff --git a/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
index be2fa31..314d599 100644
--- a/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanMatchInd.aidl
@@ -123,7 +123,7 @@
NanRangingIndication rangingIndicationType;
/**
* Security Context Identifier attribute contains PMKID. Shall be included in NDP setup and
- * response messages. Security Context Identifie identifies the Security Context. For NAN
+ * response messages. Security Context Identifier identifies the Security Context. For NAN
* Shared Key Cipher Suite, this field contains the 16 octet PMKID identifying the PMK used for
* setting up the Secure Data Path.
*/
diff --git a/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl b/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl
index 31eeb2b..a823a3f 100644
--- a/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl
+++ b/wifi/aidl/android/hardware/wifi/NanPairingAkm.aidl
@@ -17,6 +17,6 @@
package android.hardware.wifi;
/**
- * THe AKM used of NAN pairing
+ * The AKM used in the NAN pairing.
*/
@VintfStability @Backing(type="int") enum NanPairingAkm { SAE = 0, PASN=1 }
diff --git a/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl b/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl
index 32e8409..6d85eea 100644
--- a/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl
+++ b/wifi/aidl/android/hardware/wifi/NpkSecurityAssociation.aidl
@@ -20,7 +20,7 @@
import android.hardware.wifi.NanPairingAkm;
/**
- * The security sssociation info after Aware Pairing setup.
+ * The security association info after Aware Pairing setup.
*/
@VintfStability
parcelable NpkSecurityAssociation {
@@ -37,7 +37,7 @@
*/
byte[32] npk;
/**
- * The AKM is used for key exchange in this security sssociation
+ * The AKM is used for key exchange in this security association
*/
NanPairingAkm akm;
/**
diff --git a/wifi/aidl/android/hardware/wifi/Ssid.aidl b/wifi/aidl/android/hardware/wifi/Ssid.aidl
index fd985a3..230cef6 100644
--- a/wifi/aidl/android/hardware/wifi/Ssid.aidl
+++ b/wifi/aidl/android/hardware/wifi/Ssid.aidl
@@ -20,8 +20,6 @@
* Byte array representing an Ssid. Use when we need to
* pass an array of Ssid's to a method, as variable-sized
* 2D arrays are not supported in AIDL.
- *
- * TODO (b/210705533): Replace this type with a 2D byte array.
*/
@VintfStability
parcelable Ssid {