Merge "Improve A2DP Bits handling" into main
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 2a8e58f..baaa55f 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -32,6 +32,7 @@
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioGainConfig;
+using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
@@ -321,20 +322,25 @@
//
// Mix ports:
// * "r_submix output", maximum 10 opened streams, maximum 10 active streams
-// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
// * "r_submix input", maximum 10 opened streams, maximum 10 active streams
-// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
+// * "r_submix output direct", DIRECT|IEC958_NONAUDIO, 1 max open, 1 max active
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
+// * "r_submix input direct", DIRECT, 1 max open, 1 max active
+// - profile PCM 16-bit; STEREO; 8000, 11025, 16000, 32000, 44100, 48000, 192000
+
//
// Routes:
-// "r_submix output" -> "Remote Submix Out"
-// "Remote Submix In" -> "r_submix input"
+// "r_submix output", "r_submix output direct" -> "Remote Submix Out"
+// "Remote Submix In" -> "r_submix input", "r_submix input direct"
//
std::unique_ptr<Configuration> getRSubmixConfiguration() {
static const Configuration configuration = []() {
Configuration c;
const std::vector<AudioProfile> remoteSubmixPcmAudioProfiles{
createProfile(PcmType::INT_16_BIT, {AudioChannelLayout::LAYOUT_STEREO},
- {8000, 11025, 16000, 32000, 44100, 48000})};
+ {8000, 11025, 16000, 32000, 44100, 48000, 192000})};
// Device ports
@@ -359,13 +365,41 @@
rsubmixOutMix.profiles = remoteSubmixPcmAudioProfiles;
c.ports.push_back(rsubmixOutMix);
+ // Adding a DIRECT flag to rsubmixInMix breaks the mixer paths, so we need separate
+ // non direct and direct paths. It is added because for IEC61937 encapsulated over PCM, we
+ // need the DIRECT and IEC958_NONAUDIO flags as AudioFlinger adds them.
+ AudioPort rsubmixOutDirectMix =
+ createPort(c.nextPortId++, "r_submix output direct",
+ makeBitPositionFlagMask({
+ AudioOutputFlags::DIRECT,
+ AudioOutputFlags::IEC958_NONAUDIO}),
+ false /* isInput */,
+ createPortMixExt(1 /* maxOpenStreamCount */,
+ 1 /* maxActiveStreamCount */));
+ rsubmixOutDirectMix.profiles = remoteSubmixPcmAudioProfiles;
+ c.ports.push_back(rsubmixOutDirectMix);
+
AudioPort rsubmixInMix =
createPort(c.nextPortId++, "r_submix input", 0, true, createPortMixExt(10, 10));
rsubmixInMix.profiles = remoteSubmixPcmAudioProfiles;
c.ports.push_back(rsubmixInMix);
- c.routes.push_back(createRoute({rsubmixOutMix}, rsubmixOutDevice));
+ // Adding a DIRECT flag to rsubmixInMix breaks the capture paths, so we need separate
+ // non direct and direct paths. It is added because for IEC61937 encapsulated over PCM, we
+ // need the DIRECT flag for the capability so AudioFlinger can find a DIRECT input match.
+ AudioPort rsubmixInDirectMix =
+ createPort(c.nextPortId++, "r_submix input direct",
+ makeBitPositionFlagMask({AudioInputFlags::DIRECT}),
+ true /* isInput */,
+ createPortMixExt(1 /* maxOpenStreamCount */,
+ 1 /* maxActiveStreamCount */));
+ rsubmixInDirectMix.profiles = remoteSubmixPcmAudioProfiles;
+ c.ports.push_back(rsubmixInDirectMix);
+
+ c.routes.push_back(createRoute(
+ {rsubmixOutMix, rsubmixOutDirectMix}, rsubmixOutDevice));
c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInMix));
+ c.routes.push_back(createRoute({rsubmixInDevice}, rsubmixInDirectMix));
return c;
}();
diff --git a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
index 2f42889..f3965ba 100644
--- a/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/ModuleRemoteSubmix.cpp
@@ -27,6 +27,7 @@
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
@@ -47,6 +48,10 @@
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
+ if (context.getFormat().type != AudioFormatType::PCM) {
+ LOG(DEBUG) << __func__ << ": not supported for format " << context.getFormat().toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
return createStreamInstance<StreamInRemoteSubmix>(result, std::move(context), sinkMetadata,
microphones);
}
@@ -54,6 +59,10 @@
ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo, std::shared_ptr<StreamOut>* result) {
+ if (context.getFormat().type != AudioFormatType::PCM) {
+ LOG(DEBUG) << __func__ << ": not supported for format " << context.getFormat().toString();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
return createStreamInstance<StreamOutRemoteSubmix>(result, std::move(context), sourceMetadata,
offloadInfo);
}
diff --git a/bluetooth/audio/flags/Android.bp b/bluetooth/audio/flags/Android.bp
new file mode 100644
index 0000000..0d18a4d
--- /dev/null
+++ b/bluetooth/audio/flags/Android.bp
@@ -0,0 +1,12 @@
+aconfig_declarations {
+ name: "btaudiohal_flags",
+ package: "com.android.btaudio.hal.flags",
+ srcs: ["btaudiohal.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "btaudiohal_flags_c_lib",
+ aconfig_declarations: "btaudiohal_flags",
+ vendor: true,
+ host_supported: true,
+}
diff --git a/bluetooth/audio/flags/btaudiohal.aconfig b/bluetooth/audio/flags/btaudiohal.aconfig
new file mode 100644
index 0000000..763777e
--- /dev/null
+++ b/bluetooth/audio/flags/btaudiohal.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.btaudio.hal.flags"
+
+flag {
+ name: "dsa_lea"
+ namespace: "pixel_bluetooth"
+ description: "Flag for DSA Over LEA"
+ bug: "270987427"
+}
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index f5f8163..c0817f5 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -63,6 +63,10 @@
"libhidlbase",
"libxml2",
"libflatbuffers-cpp",
+ "server_configurable_flags",
+ ],
+ static_libs: [
+ "btaudiohal_flags_c_lib",
],
generated_sources: ["le_audio_codec_capabilities"],
generated_headers: [
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index 3519ace..c057505 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -20,6 +20,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android/binder_manager.h>
+#include <com_android_btaudio_hal_flags.h>
#include <hardware/audio.h>
#include "BluetoothAudioSession.h"
@@ -36,6 +37,14 @@
static constexpr int kWritePollMs = 1; // polled non-blocking interval
static constexpr int kReadPollMs = 1; // polled non-blocking interval
+static std::string toString(const std::vector<LatencyMode>& latencies) {
+ std::stringstream latencyModesStr;
+ for (LatencyMode mode : latencies) {
+ latencyModesStr << " " << toString(mode);
+ }
+ return latencyModesStr.str();
+}
+
BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
: session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {}
@@ -65,6 +74,7 @@
stack_iface_ = stack_iface;
latency_modes_ = latency_modes;
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+ << " - All LatencyModes=" << toString(latency_modes)
<< ", AudioConfiguration=" << audio_config.toString();
ReportSessionStatus();
}
@@ -604,31 +614,46 @@
return std::vector<LatencyMode>();
}
- std::vector<LatencyMode> supported_latency_modes;
- if (session_type_ ==
- SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
- for (LatencyMode mode : latency_modes_) {
- if (mode == LatencyMode::LOW_LATENCY) {
- // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
- continue;
+ if (com::android::btaudio::hal::flags::dsa_lea()) {
+ std::vector<LatencyMode> supported_latency_modes;
+ if (session_type_ ==
+ SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY) {
+ // LOW_LATENCY is not supported for LE_HARDWARE_OFFLOAD_ENC sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
}
- supported_latency_modes.push_back(mode);
+ } else {
+ for (LatencyMode mode : latency_modes_) {
+ if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
+ // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
+ continue;
+ }
+ if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
+ mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
+ // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC
+ // sessions
+ continue;
+ }
+ supported_latency_modes.push_back(mode);
+ }
}
- } else {
- for (LatencyMode mode : latency_modes_) {
- if (!low_latency_allowed_ && mode == LatencyMode::LOW_LATENCY) {
- // ignore LOW_LATENCY mode if Bluetooth stack doesn't allow
- continue;
- }
- if (mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE ||
- mode == LatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE) {
- // DSA_SW and DSA_HW only supported for LE_HARDWARE_OFFLOAD_ENC sessions
- continue;
- }
- supported_latency_modes.push_back(mode);
- }
+ LOG(DEBUG) << __func__ << " - Supported LatencyMode="
+ << toString(supported_latency_modes);
+ return supported_latency_modes;
}
- return supported_latency_modes;
+
+ if (low_latency_allowed_) return latency_modes_;
+ std::vector<LatencyMode> modes;
+ for (LatencyMode mode : latency_modes_) {
+ if (mode == LatencyMode::LOW_LATENCY)
+ // ignore those low latency mode if Bluetooth stack doesn't allow
+ continue;
+ modes.push_back(mode);
+ }
+ return modes;
}
void BluetoothAudioSession::SetLatencyMode(const LatencyMode& latency_mode) {
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index e7fad4d..8fc77ae 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -35,6 +35,7 @@
@VintfStability
parcelable ChannelSoudingRawData {
int procedureCounter;
+ int[] frequencyCompensation;
boolean aborted;
android.hardware.bluetooth.ranging.ChannelSoundingSingleSideData initiatorData;
android.hardware.bluetooth.ranging.ChannelSoundingSingleSideData reflectorData;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 9fe85da..ddaba72 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -38,6 +38,7 @@
@nullable byte[] packetQuality;
@nullable byte[] packetRssiDbm;
@nullable android.hardware.bluetooth.ranging.Nadm[] packetNadm;
+ @nullable int[] measuredFreqOffset;
@nullable List<android.hardware.bluetooth.ranging.ComplexNumber> packetPct1;
@nullable List<android.hardware.bluetooth.ranging.ComplexNumber> packetPct2;
byte referencePowerDbm;
diff --git a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
index a51ba37..4125748 100644
--- a/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/aidl_api/android.hardware.bluetooth.ranging/current/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -36,6 +36,7 @@
parcelable StepTonePct {
List<android.hardware.bluetooth.ranging.ComplexNumber> tonePcts;
byte[] toneQualityIndicator;
+ byte toneExtensionAntennaIndex;
const int TONE_QUALITY_GOOD = 0;
const int TONE_QUALITY_MEDIUM = 1;
const int TONE_QUALITY_LOW = 2;
@@ -44,4 +45,9 @@
const int EXTENSION_SLOT_TONE_NOT_EXPECTED_TO_BE_PRESENT = 1;
const int EXTENSION_SLOT_TONE_EXPECTED_TO_BE_PRESENT = 2;
const int EXTENSION_SLOT_SHIFT_AMOUNT = 4;
+ const byte TONE_EXTENSION_ANTENNA_1 = 0x0;
+ const byte TONE_EXTENSION_ANTENNA_2 = 0x1;
+ const byte TONE_EXTENSION_ANTENNA_3 = 0x2;
+ const byte TONE_EXTENSION_ANTENNA_4 = 0x3;
+ const byte TONE_EXTENSION_UNUSED = 0xFFu8;
}
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
index 3c8a62f..0106865 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoudingRawData.aidl
@@ -29,6 +29,11 @@
*/
int procedureCounter;
/**
+ * Frequency Compensation indicates fractional frequency
+ * offset (FFO) value of initiator, in 0.01ppm
+ */
+ int[] frequencyCompensation;
+ /**
* Indicate if the procedure aborted.
*/
boolean aborted;
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
index 2c3f201..942fc0d 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/ChannelSoundingSingleSideData.aidl
@@ -42,6 +42,10 @@
*/
@nullable Nadm[] packetNadm;
/**
+ * Measured Frequency Offset from mode 0, relative to the remote device, in 0.01ppm
+ */
+ @nullable int[] measuredFreqOffset;
+ /**
* Packet_PCT1 or packet_PCT2 of mode-1 or mode-3, if sounding sequence is used and sounding
* phase-based ranging is supported.
*/
diff --git a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
index 99c6d65..4650861 100644
--- a/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
+++ b/bluetooth/ranging/aidl/android/hardware/bluetooth/ranging/StepTonePct.aidl
@@ -23,6 +23,10 @@
*/
@VintfStability
parcelable StepTonePct {
+ /**
+ * PCT measured from mode-2 or mode-3 steps
+ * (in ascending order of antenna position with tone extension data at the end).
+ */
List<ComplexNumber> tonePcts;
const int TONE_QUALITY_GOOD = 0;
const int TONE_QUALITY_MEDIUM = 1;
@@ -52,4 +56,20 @@
* See: https://bluetooth.com/specifications/specs/channel-sounding-cr-pr/
*/
byte[] toneQualityIndicator;
+
+ const byte TONE_EXTENSION_ANTENNA_1 = 0x0;
+ const byte TONE_EXTENSION_ANTENNA_2 = 0x1;
+ const byte TONE_EXTENSION_ANTENNA_3 = 0x2;
+ const byte TONE_EXTENSION_ANTENNA_4 = 0x3;
+ const byte TONE_EXTENSION_UNUSED = 0xFFu8;
+ /**
+ * Tone Extension Antenna Index indicates the Antenna position used in tone extension slot
+ *
+ * 0x00 = A1
+ * 0x01 = A2
+ * 0x02 = A3
+ * 0x03 = A4
+ * 0xFF = Tone extension not used
+ */
+ byte toneExtensionAntennaIndex;
}
diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index 023fc8f..8ce37cd 100644
--- a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -36,4 +36,9 @@
interface ISecretkeeper {
android.hardware.security.authgraph.IAuthGraphKeyExchange getAuthGraphKe();
byte[] processSecretManagementRequest(in byte[] request);
+ void deleteIds(in android.hardware.security.secretkeeper.SecretId[] ids);
+ void deleteAll();
+ const int ERROR_UNKNOWN_KEY_ID = 1;
+ const int ERROR_INTERNAL_ERROR = 2;
+ const int ERROR_REQUEST_MALFORMED = 3;
}
diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ErrorCode.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl
similarity index 92%
rename from security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ErrorCode.aidl
rename to security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl
index cc07f9b..87d0233 100644
--- a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ErrorCode.aidl
+++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/SecretId.aidl
@@ -33,10 +33,7 @@
package android.hardware.security.secretkeeper;
/* @hide */
-@Backing(type="int") @VintfStability
-enum ErrorCode {
- OK = 0,
- UNKNOWN_KEY_ID = 1,
- INTERNAL_ERROR = 2,
- REQUEST_MALFORMED = 3,
+@VintfStability
+parcelable SecretId {
+ byte[] id;
}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
index cb3e9b9..49c3446 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
@@ -17,6 +17,7 @@
package android.hardware.security.secretkeeper;
import android.hardware.security.authgraph.IAuthGraphKeyExchange;
+import android.hardware.security.secretkeeper.SecretId;
@VintfStability
/**
@@ -30,14 +31,12 @@
* - A trusted execution environment such as ARM TrustZone.
* - A completely separate, purpose-built and certified secure CPU.
*
- * TODO(b/291224769): Extend the HAL interface to include:
- * 1. Dice policy operation - These allow sealing of the secrets with a class of Dice chains.
- * Typical operations are (securely) updating the dice policy sealing the Secrets above. These
- * operations are core to AntiRollback protected secrets - ie, ensuring secrets of a pVM are only
- * accessible to same or higher versions of the images.
- * 2. Maintenance API: This is required for removing the Secretkeeper entries for obsolete pVMs.
*/
interface ISecretkeeper {
+ const int ERROR_UNKNOWN_KEY_ID = 1;
+ const int ERROR_INTERNAL_ERROR = 2;
+ const int ERROR_REQUEST_MALFORMED = 3;
+
/**
* Retrieve the instance of the `IAuthGraphKeyExchange` HAL that should be used for shared
* session key establishment. These keys are used to perform encryption of messages as
@@ -60,8 +59,8 @@
* Virtual Machines). For this, service (& client) must implement a key exchange protocol, which
* is critical for establishing the secure channel.
*
- * If an encrypted response cannot be generated, then a service-specific Binder error using an
- * error code from ErrorCode.aidl will be returned.
+ * If an encrypted response cannot be generated, then a service-specific Binder error using one
+ * of the ERROR_ codes above will be returned.
*
* Secretkeeper database should guarantee the following properties:
*
@@ -82,4 +81,19 @@
* @return CBOR-encoded ProtectedResponsePacket. See SecretManagement.cddl for its definition
*/
byte[] processSecretManagementRequest(in byte[] request);
+
+ /**
+ * Delete the data corresponding to a collection of IDs.
+ *
+ * Note that unlike `processSecretManagementRequest`, the contents of this method are in
+ * plaintext, and no client authentication is required.
+ *
+ * @param Secret identifiers to delete.
+ */
+ void deleteIds(in SecretId[] ids);
+
+ /**
+ * Delete data of all clients.
+ */
+ void deleteAll();
}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ErrorCode.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl
similarity index 69%
rename from security/secretkeeper/aidl/android/hardware/security/secretkeeper/ErrorCode.aidl
rename to security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl
index e9cce09..bd982e7 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ErrorCode.aidl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretId.aidl
@@ -17,17 +17,13 @@
package android.hardware.security.secretkeeper;
/**
- * Secretkeeper unencrypted error code, returned via AIDL as service specific errors in
- * EX_SERVICE_SPECIFIC.
+ * SecretId contains an identifier for a secret held by Secretkeeper.
* @hide
*/
@VintfStability
-@Backing(type="int")
-enum ErrorCode {
- OK = 0,
- UNKNOWN_KEY_ID = 1,
- INTERNAL_ERROR = 2,
- REQUEST_MALFORMED = 3,
-
- // TODO(b/291224769): Create a more exhaustive set of error code values.
+parcelable SecretId {
+ /**
+ * 64-byte identifier for a secret.
+ */
+ byte[] id;
}
diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
index 66ca8ed..3d08078 100644
--- a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
+++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl
@@ -9,8 +9,8 @@
CryptoPayload<Payload, Key> = [ ; COSE_Encrypt0 (untagged), [RFC 9052 s5.2]
protected: bstr .cbor {
1 : 3, ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag
- 4 : bstr ; key identifier, uniquely identifies the session
- ; TODO(b/291228560): Refer to the Key Exchange spec.
+ 4 : bstr ; key identifier set to session ID produced
+ ; by AuthGraph key exchange.
},
unprotected: {
5 : bstr .size 12 ; IV
@@ -32,8 +32,11 @@
StoreSecretOpcode = 2 ; Store a secret
GetSecretOpcode = 3 ; Get the secret
+; Retrieve Secretkeeper version.
GetVersionParams = ()
+; Store a secret identified by the given ID, with access to the secret policed
+; by the associated sealing policy.
StoreSecretParams = (
id : SecretId,
secret : Secret,
@@ -42,6 +45,9 @@
; INCLUDE DicePolicy.cddl for: DicePolicy
+; Retrieve a secret identified by the given ID, policed according to the sealing
+; policy that was associated with the secret. If successful, optionally also
+; update the sealing policy for the secret.
GetSecretParams = (
id : SecretId,
; Retrieving the value of a secret may optionally also update the sealing
@@ -68,7 +74,6 @@
; An error code in the inner response message indicates a failure in
; secret management processing.
-; TODO(b/291224769): Create a more exhaustive set of ErrorCodes
ErrorCode = &(
; Use this as if no other error code can be used.
ErrorCode_UnexpectedServerError: 1,
diff --git a/security/secretkeeper/aidl/vts/Android.bp b/security/secretkeeper/aidl/vts/Android.bp
index c130a3a..7fc7a70 100644
--- a/security/secretkeeper/aidl/vts/Android.bp
+++ b/security/secretkeeper/aidl/vts/Android.bp
@@ -25,6 +25,7 @@
"general-tests",
"vts",
],
+ test_config: "AndroidTest.xml",
rustlibs: [
"libsecretkeeper_comm_nostd",
"libsecretkeeper_core_nostd",
@@ -36,6 +37,7 @@
"libbinder_rs",
"libcoset",
"liblog_rust",
+ "liblogger",
],
require_root: true,
}
diff --git a/security/secretkeeper/aidl/vts/AndroidTest.xml b/security/secretkeeper/aidl/vts/AndroidTest.xml
new file mode 100644
index 0000000..4fee78f
--- /dev/null
+++ b/security/secretkeeper/aidl/vts/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for Secretkeeper VTS tests.">
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="VtsSecretkeeperTargetTest" value="/data/local/tmp/VtsSecretkeeperTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
+ <option name="test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsSecretkeeperTargetTest" />
+ <!-- Rust tests are run in parallel by default. Run these ones
+ single-threaded, so that one test's secrets don't affect
+ the behaviour of a different test. -->
+ <option name="native-test-flag" value="--test-threads=1" />
+ </test>
+</configuration>
diff --git a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
index a473bd0..6a70d02 100644
--- a/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
+++ b/security/secretkeeper/aidl/vts/secretkeeper_test_client.rs
@@ -14,26 +14,28 @@
* limitations under the License.
*/
-#[cfg(test)]
+#![cfg(test)]
+
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
+use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::SecretId::SecretId;
+use authgraph_vts_test as ag_vts;
+use authgraph_boringssl as boring;
+use authgraph_core::key;
use binder::StatusCode;
use coset::{CborSerializable, CoseEncrypt0};
-use log::warn;
+use log::{info, warn};
use secretkeeper_core::cipher;
use secretkeeper_comm::data_types::error::SecretkeeperError;
use secretkeeper_comm::data_types::request::Request;
use secretkeeper_comm::data_types::request_response_impl::{
GetVersionRequest, GetVersionResponse, GetSecretRequest, GetSecretResponse, StoreSecretRequest,
StoreSecretResponse };
-use secretkeeper_comm::data_types::{Id, ID_SIZE, Secret, SECRET_SIZE};
+use secretkeeper_comm::data_types::{Id, Secret};
use secretkeeper_comm::data_types::response::Response;
use secretkeeper_comm::data_types::packet::{ResponsePacket, ResponseType};
-use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::ISecretkeeper;
-use authgraph_vts_test as ag_vts;
-use authgraph_boringssl as boring;
-use authgraph_core::key;
-const SECRETKEEPER_IDENTIFIER: &str =
- "android.hardware.security.secretkeeper.ISecretkeeper/nonsecure";
+const SECRETKEEPER_SERVICE: &str = "android.hardware.security.secretkeeper.ISecretkeeper";
+const SECRETKEEPER_INSTANCES: [&'static str; 2] = ["nonsecure", "default"];
const CURRENT_VERSION: u64 = 1;
// TODO(b/291238565): This will change once libdice_policy switches to Explicit-key DiceCertChain
@@ -46,32 +48,62 @@
];
// Random bytes (of ID_SIZE/SECRET_SIZE) generated for tests.
-const ID_EXAMPLE: [u8; ID_SIZE] = [
+const ID_EXAMPLE: Id = Id([
0xF1, 0xB2, 0xED, 0x3B, 0xD1, 0xBD, 0xF0, 0x7D, 0xE1, 0xF0, 0x01, 0xFC, 0x61, 0x71, 0xD3, 0x42,
0xE5, 0x8A, 0xAF, 0x33, 0x6C, 0x11, 0xDC, 0xC8, 0x6F, 0xAE, 0x12, 0x5C, 0x26, 0x44, 0x6B, 0x86,
0xCC, 0x24, 0xFD, 0xBF, 0x91, 0x4A, 0x54, 0x84, 0xF9, 0x01, 0x59, 0x25, 0x70, 0x89, 0x38, 0x8D,
0x5E, 0xE6, 0x91, 0xDF, 0x68, 0x60, 0x69, 0x26, 0xBE, 0xFE, 0x79, 0x58, 0xF7, 0xEA, 0x81, 0x7D,
-];
-const ID_NOT_STORED: [u8; ID_SIZE] = [
+]);
+const ID_EXAMPLE_2: Id = Id([
+ 0x6A, 0xCC, 0xB1, 0xEB, 0xBB, 0xAB, 0xE3, 0xEA, 0x44, 0xBD, 0xDC, 0x75, 0x75, 0x7D, 0xC0, 0xE5,
+ 0xC7, 0x86, 0x41, 0x56, 0x39, 0x66, 0x96, 0x10, 0xCB, 0x43, 0x10, 0x79, 0x03, 0xDC, 0xE6, 0x9F,
+ 0x12, 0x2B, 0xEF, 0x28, 0x9C, 0x1E, 0x32, 0x46, 0x5F, 0xA3, 0xE7, 0x8D, 0x53, 0x63, 0xE8, 0x30,
+ 0x5A, 0x17, 0x6F, 0xEF, 0x42, 0xD6, 0x58, 0x7A, 0xF0, 0xCB, 0xD4, 0x40, 0x58, 0x96, 0x32, 0xF4,
+]);
+const ID_NOT_STORED: Id = Id([
0x56, 0xD0, 0x4E, 0xAA, 0xC1, 0x7B, 0x55, 0x6B, 0xA0, 0x2C, 0x65, 0x43, 0x39, 0x0A, 0x6C, 0xE9,
0x1F, 0xD0, 0x0E, 0x20, 0x3E, 0xFB, 0xF5, 0xF9, 0x3F, 0x5B, 0x11, 0x1B, 0x18, 0x73, 0xF6, 0xBB,
0xAB, 0x9F, 0xF2, 0xD6, 0xBD, 0xBA, 0x25, 0x68, 0x22, 0x30, 0xF2, 0x1F, 0x90, 0x05, 0xF3, 0x64,
0xE7, 0xEF, 0xC6, 0xB6, 0xA0, 0x85, 0xC9, 0x40, 0x40, 0xF0, 0xB4, 0xB9, 0xD8, 0x28, 0xEE, 0x9C,
-];
-const SECRET_EXAMPLE: [u8; SECRET_SIZE] = [
+]);
+const SECRET_EXAMPLE: Secret = Secret([
0xA9, 0x89, 0x97, 0xFE, 0xAE, 0x97, 0x55, 0x4B, 0x32, 0x35, 0xF0, 0xE8, 0x93, 0xDA, 0xEA, 0x24,
0x06, 0xAC, 0x36, 0x8B, 0x3C, 0x95, 0x50, 0x16, 0x67, 0x71, 0x65, 0x26, 0xEB, 0xD0, 0xC3, 0x98,
-];
+]);
-fn get_connection() -> Option<binder::Strong<dyn ISecretkeeper>> {
- match binder::get_interface(SECRETKEEPER_IDENTIFIER) {
- Ok(sk) => Some(sk),
- Err(StatusCode::NAME_NOT_FOUND) => None,
- Err(e) => {
- panic!(
- "unexpected error while fetching connection to Secretkeeper {:?}",
- e
- );
+fn get_connection() -> Option<(binder::Strong<dyn ISecretkeeper>, String)> {
+ // Initialize logging (which is OK to call multiple times).
+ logger::init(logger::Config::default().with_min_level(log::Level::Debug));
+
+ // TODO: replace this with a parameterized set of tests that run for each available instance of
+ // ISecretkeeper (rather than having a fixed set of instance names to look for).
+ for instance in &SECRETKEEPER_INSTANCES {
+ let name = format!("{SECRETKEEPER_SERVICE}/{instance}");
+ match binder::get_interface(&name) {
+ Ok(sk) => {
+ info!("Running test against /{instance}");
+ return Some((sk, name));
+ }
+ Err(StatusCode::NAME_NOT_FOUND) => {
+ info!("No /{instance} instance of ISecretkeeper present");
+ }
+ Err(e) => {
+ panic!("unexpected error while fetching connection to Secretkeeper {:?}", e);
+ }
+ }
+ }
+ None
+}
+
+/// Macro to perform test setup. Invokes `return` if no Secretkeeper instance available.
+macro_rules! setup_client {
+ {} => {
+ match SkClient::new() {
+ Some(sk) => sk,
+ None => {
+ warn!("Secretkeeper HAL is unavailable, skipping test");
+ return;
+ }
}
}
}
@@ -79,42 +111,86 @@
/// Secretkeeper client information.
struct SkClient {
sk: binder::Strong<dyn ISecretkeeper>,
+ name: String,
aes_keys: [key::AesKey; 2],
session_id: Vec<u8>,
}
+impl Drop for SkClient {
+ fn drop(&mut self) {
+ // Delete any IDs that may be left over.
+ self.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
+ }
+}
+
impl SkClient {
fn new() -> Option<Self> {
- let sk = get_connection()?;
+ let (sk, name) = get_connection()?;
let (aes_keys, session_id) = authgraph_key_exchange(sk.clone());
- Some(Self {
- sk,
- aes_keys,
- session_id,
- })
+ Some(Self { sk, name, aes_keys, session_id })
}
+
/// Wrapper around `ISecretkeeper::processSecretManagementRequest` that handles
/// encryption and decryption.
fn secret_management_request(&self, req_data: &[u8]) -> Vec<u8> {
let aes_gcm = boring::BoringAes;
let rng = boring::BoringRng;
- let request_bytes = cipher::encrypt_message(
- &aes_gcm,
- &rng,
- &self.aes_keys[0],
- &self.session_id,
- &req_data,
- )
- .unwrap();
+ let request_bytes =
+ cipher::encrypt_message(&aes_gcm, &rng, &self.aes_keys[0], &self.session_id, &req_data)
+ .unwrap();
- let response_bytes = self
- .sk
- .processSecretManagementRequest(&request_bytes)
- .unwrap();
+ let response_bytes = self.sk.processSecretManagementRequest(&request_bytes).unwrap();
let response_encrypt0 = CoseEncrypt0::from_slice(&response_bytes).unwrap();
cipher::decrypt_message(&aes_gcm, &self.aes_keys[1], &response_encrypt0).unwrap()
}
+
+ /// Helper method to store a secret.
+ fn store(&self, id: &Id, secret: &Secret) {
+ let store_request = StoreSecretRequest {
+ id: id.clone(),
+ secret: secret.clone(),
+ sealing_policy: HYPOTHETICAL_DICE_POLICY.to_vec(),
+ };
+ let store_request = store_request.serialize_to_packet().to_vec().unwrap();
+
+ let store_response = self.secret_management_request(&store_request);
+ let store_response = ResponsePacket::from_slice(&store_response).unwrap();
+
+ assert_eq!(store_response.response_type().unwrap(), ResponseType::Success);
+ // Really just checking that the response is indeed StoreSecretResponse
+ let _ = StoreSecretResponse::deserialize_from_packet(store_response).unwrap();
+ }
+
+ /// Helper method to get a secret.
+ fn get(&self, id: &Id) -> Option<Secret> {
+ let get_request = GetSecretRequest { id: id.clone(), updated_sealing_policy: None };
+ let get_request = get_request.serialize_to_packet().to_vec().unwrap();
+
+ let get_response = self.secret_management_request(&get_request);
+ let get_response = ResponsePacket::from_slice(&get_response).unwrap();
+
+ if get_response.response_type().unwrap() == ResponseType::Success {
+ let get_response = *GetSecretResponse::deserialize_from_packet(get_response).unwrap();
+ Some(Secret(get_response.secret.0))
+ } else {
+ // Only expect a not-found failure.
+ let err = *SecretkeeperError::deserialize_from_packet(get_response).unwrap();
+ assert_eq!(err, SecretkeeperError::EntryNotFound);
+ None
+ }
+ }
+
+ /// Helper method to delete secrets.
+ fn delete(&self, ids: &[&Id]) {
+ let ids: Vec<SecretId> = ids.iter().map(|id| SecretId { id: id.0.to_vec() }).collect();
+ self.sk.deleteIds(&ids).unwrap();
+ }
+
+ /// Helper method to delete everything.
+ fn delete_all(&self) {
+ self.sk.deleteAll().unwrap();
+ }
}
/// Perform AuthGraph key exchange, returning the session keys and session ID.
@@ -128,7 +204,7 @@
/// mainline key exchange against a local source implementation.
#[test]
fn authgraph_mainline() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
@@ -142,7 +218,7 @@
/// a corrupted session ID signature.
#[test]
fn authgraph_corrupt_sig() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
@@ -158,7 +234,7 @@
/// when corrupted keys are returned to it.
#[test]
fn authgraph_corrupt_keys() {
- let sk = match get_connection() {
+ let (sk, _) = match get_connection() {
Some(sk) => sk,
None => {
warn!("Secretkeeper HAL is unavailable, skipping test");
@@ -175,13 +251,7 @@
#[test]
fn secret_management_get_version() {
- let sk_client = match SkClient::new() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let sk_client = setup_client!();
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
@@ -190,10 +260,7 @@
let response_bytes = sk_client.secret_management_request(&request_bytes);
let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
- assert_eq!(
- response_packet.response_type().unwrap(),
- ResponseType::Success
- );
+ assert_eq!(response_packet.response_type().unwrap(), ResponseType::Success);
let get_version_response =
*GetVersionResponse::deserialize_from_packet(response_packet).unwrap();
assert_eq!(get_version_response.version, CURRENT_VERSION);
@@ -201,13 +268,7 @@
#[test]
fn secret_management_malformed_request() {
- let sk_client = match SkClient::new() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let sk_client = setup_client!();
let request = GetVersionRequest {};
let request_packet = request.serialize_to_packet();
@@ -219,93 +280,112 @@
let response_bytes = sk_client.secret_management_request(&request_bytes);
let response_packet = ResponsePacket::from_slice(&response_bytes).unwrap();
- assert_eq!(
- response_packet.response_type().unwrap(),
- ResponseType::Error
- );
+ assert_eq!(response_packet.response_type().unwrap(), ResponseType::Error);
let err = *SecretkeeperError::deserialize_from_packet(response_packet).unwrap();
assert_eq!(err, SecretkeeperError::RequestMalformed);
}
#[test]
fn secret_management_store_get_secret_found() {
- let sk_client = match SkClient::new() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let sk_client = setup_client!();
- let store_request = StoreSecretRequest {
- id: Id(ID_EXAMPLE),
- secret: Secret(SECRET_EXAMPLE),
- sealing_policy: HYPOTHETICAL_DICE_POLICY.to_vec(),
- };
-
- let store_request = store_request.serialize_to_packet().to_vec().unwrap();
-
- let store_response = sk_client.secret_management_request(&store_request);
- let store_response = ResponsePacket::from_slice(&store_response).unwrap();
-
- assert_eq!(
- store_response.response_type().unwrap(),
- ResponseType::Success
- );
- // Really just checking that the response is indeed StoreSecretResponse
- let _ = StoreSecretResponse::deserialize_from_packet(store_response).unwrap();
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
// Get the secret that was just stored
- let get_request = GetSecretRequest {
- id: Id(ID_EXAMPLE),
- updated_sealing_policy: None,
- };
- let get_request = get_request.serialize_to_packet().to_vec().unwrap();
-
- let get_response = sk_client.secret_management_request(&get_request);
- let get_response = ResponsePacket::from_slice(&get_response).unwrap();
- assert_eq!(get_response.response_type().unwrap(), ResponseType::Success);
- let get_response = *GetSecretResponse::deserialize_from_packet(get_response).unwrap();
- assert_eq!(get_response.secret.0, SECRET_EXAMPLE);
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
}
#[test]
fn secret_management_store_get_secret_not_found() {
- let sk_client = match SkClient::new() {
- Some(sk) => sk,
- None => {
- warn!("Secretkeeper HAL is unavailable, skipping test");
- return;
- }
- };
+ let sk_client = setup_client!();
// Store a secret (corresponding to an id).
- let store_request = StoreSecretRequest {
- id: Id(ID_EXAMPLE),
- secret: Secret(SECRET_EXAMPLE),
- sealing_policy: HYPOTHETICAL_DICE_POLICY.to_vec(),
- };
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
- let store_request = store_request.serialize_to_packet().to_vec().unwrap();
- let store_response = sk_client.secret_management_request(&store_request);
- let store_response = ResponsePacket::from_slice(&store_response).unwrap();
+ // Get the secret that was never stored
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
+}
- assert_eq!(
- store_response.response_type().unwrap(),
- ResponseType::Success
- );
+#[test]
+fn secretkeeper_store_delete_ids() {
+ let sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_EXAMPLE]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+
+ sk_client.delete(&[&ID_EXAMPLE_2]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_multiple_ids() {
+ let sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE_2]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_duplicate_ids() {
+ let sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ // Delete the same secret twice.
+ sk_client.delete(&[&ID_EXAMPLE, &ID_EXAMPLE]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+}
+
+#[test]
+fn secretkeeper_store_delete_nonexistent() {
+ let sk_client = setup_client!();
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+ sk_client.delete(&[&ID_NOT_STORED]);
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), Some(SECRET_EXAMPLE));
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
+}
+
+#[test]
+fn secretkeeper_store_delete_all() {
+ let sk_client = setup_client!();
+
+ if sk_client.name != "nonsecure" {
+ // Don't run deleteAll() on a secure device, as it might affect
+ // real secrets.
+ warn!("skipping deleteAll test due to real impl");
+ return;
+ }
+
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+ sk_client.store(&ID_EXAMPLE_2, &SECRET_EXAMPLE);
+
+ sk_client.delete_all();
+
+ assert_eq!(sk_client.get(&ID_EXAMPLE), None);
+ assert_eq!(sk_client.get(&ID_EXAMPLE_2), None);
+
+ // Store a new secret (corresponding to an id).
+ sk_client.store(&ID_EXAMPLE, &SECRET_EXAMPLE);
+
+ // Get the restored secret.
+ assert_eq!(sk_client.get(&ID_EXAMPLE), Some(SECRET_EXAMPLE));
// (Try to) Get the secret that was never stored
- let get_request = GetSecretRequest {
- id: Id(ID_NOT_STORED),
- updated_sealing_policy: None,
- };
- let get_request = get_request.serialize_to_packet().to_vec().unwrap();
- let get_response = sk_client.secret_management_request(&get_request);
-
- // Check that response is `SecretkeeperError::EntryNotFound`
- let get_response = ResponsePacket::from_slice(&get_response).unwrap();
- assert_eq!(get_response.response_type().unwrap(), ResponseType::Error);
- let err = *SecretkeeperError::deserialize_from_packet(get_response).unwrap();
- assert_eq!(err, SecretkeeperError::EntryNotFound);
+ assert_eq!(sk_client.get(&ID_NOT_STORED), None);
}
diff --git a/security/secretkeeper/default/src/store.rs b/security/secretkeeper/default/src/store.rs
index 7b2d0b9..a7fb3b7 100644
--- a/security/secretkeeper/default/src/store.rs
+++ b/security/secretkeeper/default/src/store.rs
@@ -33,4 +33,14 @@
let optional_val = self.0.get(key);
Ok(optional_val.cloned())
}
+
+ fn delete(&mut self, key: &[u8]) -> Result<(), Error> {
+ self.0.remove(key);
+ Ok(())
+ }
+
+ fn delete_all(&mut self) -> Result<(), Error> {
+ self.0.clear();
+ Ok(())
+ }
}
diff --git a/sensors/aidl/default/Android.bp b/sensors/aidl/default/Android.bp
index 08ee773..e93c391 100644
--- a/sensors/aidl/default/Android.bp
+++ b/sensors/aidl/default/Android.bp
@@ -97,12 +97,5 @@
prebuilts: [
"sensors-default.rc", // init rc
"sensors-default.xml", // vintf fragment
- "android.hardware.sensor.ambient_temperature.prebuilt.xml",
- "android.hardware.sensor.barometer.prebuilt.xml",
- "android.hardware.sensor.gyroscope.prebuilt.xml",
- "android.hardware.sensor.hinge_angle.prebuilt.xml",
- "android.hardware.sensor.light.prebuilt.xml",
- "android.hardware.sensor.proximity.prebuilt.xml",
- "android.hardware.sensor.relative_humidity.prebuilt.xml",
],
}