Merge "ExternalCameraHAL: Get old image if taking picture without preview" into main
diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING
index e325001..26f4b3a 100644
--- a/audio/aidl/TEST_MAPPING
+++ b/audio/aidl/TEST_MAPPING
@@ -72,12 +72,7 @@
"name": "audiosystem_tests"
},
{
- "name": "CtsVirtualDevicesTestCases",
- "options" : [
- {
- "include-filter": "android.virtualdevice.cts.VirtualAudioTest"
- }
- ]
+ "name": "CtsVirtualDevicesAudioTestCases"
}
]
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index f51f65e..d47b0b1 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -77,6 +77,7 @@
"r_submix/ModuleRemoteSubmix.cpp",
"r_submix/SubmixRoute.cpp",
"r_submix/StreamRemoteSubmix.cpp",
+ "stub/DriverStubImpl.cpp",
"stub/ModuleStub.cpp",
"stub/StreamStub.cpp",
"usb/ModuleUsb.cpp",
diff --git a/audio/aidl/default/Configuration.cpp b/audio/aidl/default/Configuration.cpp
index 54e2d18..0ff8eb4 100644
--- a/audio/aidl/default/Configuration.cpp
+++ b/audio/aidl/default/Configuration.cpp
@@ -324,9 +324,9 @@
//
// 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
//
// Routes:
// "r_submix output" -> "Remote Submix Out"
@@ -337,7 +337,7 @@
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
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index c14d06e..45ce5ef 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -47,6 +47,7 @@
using aidl::android::media::audio::common::AudioDeviceType;
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::AudioMMapPolicy;
@@ -1200,7 +1201,9 @@
}
if (in_requested.gain.has_value()) {
- // Let's pretend that gain can always be applied.
+ if (!setAudioPortConfigGain(*portIt, in_requested.gain.value())) {
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
out_suggested->gain = in_requested.gain.value();
}
@@ -1242,6 +1245,52 @@
return ndk::ScopedAStatus::ok();
}
+bool Module::setAudioPortConfigGain(const AudioPort& port, const AudioGainConfig& gainRequested) {
+ auto& ports = getConfig().ports;
+ if (gainRequested.index < 0 || gainRequested.index >= (int)port.gains.size()) {
+ LOG(ERROR) << __func__ << ": gains for port " << port.id << " is undefined";
+ return false;
+ }
+ int stepValue = port.gains[gainRequested.index].stepValue;
+ if (stepValue == 0) {
+ LOG(ERROR) << __func__ << ": port gain step value is 0";
+ return false;
+ }
+ int minValue = port.gains[gainRequested.index].minValue;
+ int maxValue = port.gains[gainRequested.index].maxValue;
+ if (gainRequested.values[0] > maxValue || gainRequested.values[0] < minValue) {
+ LOG(ERROR) << __func__ << ": gain value " << gainRequested.values[0]
+ << " out of range of min and max gain config";
+ return false;
+ }
+ int gainIndex = (gainRequested.values[0] - minValue) / stepValue;
+ int totalSteps = (maxValue - minValue) / stepValue;
+ if (totalSteps == 0) {
+ LOG(ERROR) << __func__ << ": difference between port gain min value " << minValue
+ << " and max value " << maxValue << " is less than step value " << stepValue;
+ return false;
+ }
+ // Root-power quantities are used in curve:
+ // 10^((minMb / 100 + (maxMb / 100 - minMb / 100) * gainIndex / totalSteps) / (10 * 2))
+ // where 100 is the conversion from mB to dB, 10 comes from the log 10 conversion from power
+ // ratios, and 2 means are the square of amplitude.
+ float gain =
+ pow(10, (minValue + (maxValue - minValue) * (gainIndex / (float)totalSteps)) / 2000);
+ if (gain < 0) {
+ LOG(ERROR) << __func__ << ": gain " << gain << " is less than 0";
+ return false;
+ }
+ for (const auto& route : getConfig().routes) {
+ if (route.sinkPortId != port.id) {
+ continue;
+ }
+ for (const auto sourcePortId : route.sourcePortIds) {
+ mStreams.setGain(sourcePortId, gain);
+ }
+ }
+ return true;
+}
+
ndk::ScopedAStatus Module::resetAudioPatch(int32_t in_patchId) {
auto& patches = getConfig().patches;
auto patchIt = findById<AudioPatch>(patches, in_patchId);
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 3e4650d..de66293 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -855,6 +855,11 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus StreamCommonImpl::setGain(float gain) {
+ LOG(DEBUG) << __func__ << ": gain " << gain;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
LOG(DEBUG) << __func__;
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
diff --git a/audio/aidl/default/StreamSwitcher.cpp b/audio/aidl/default/StreamSwitcher.cpp
index 8ba15a8..0052889 100644
--- a/audio/aidl/default/StreamSwitcher.cpp
+++ b/audio/aidl/default/StreamSwitcher.cpp
@@ -260,4 +260,12 @@
return mStream->bluetoothParametersUpdated();
}
+ndk::ScopedAStatus StreamSwitcher::setGain(float gain) {
+ if (mStream == nullptr) {
+ LOG(ERROR) << __func__ << ": stream was closed";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ return mStream->setGain(gain);
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/StreamAlsa.cpp b/audio/aidl/default/alsa/StreamAlsa.cpp
index f548903..c77bfca 100644
--- a/audio/aidl/default/alsa/StreamAlsa.cpp
+++ b/audio/aidl/default/alsa/StreamAlsa.cpp
@@ -75,6 +75,10 @@
}
decltype(mAlsaDeviceProxies) alsaDeviceProxies;
for (const auto& device : getDeviceProfiles()) {
+ if ((device.direction == PCM_OUT && mIsInput) ||
+ (device.direction == PCM_IN && !mIsInput)) {
+ continue;
+ }
alsa::DeviceProxy proxy;
if (device.isExternal) {
// Always ask alsa configure as required since the configuration should be supported
@@ -92,6 +96,9 @@
}
alsaDeviceProxies.push_back(std::move(proxy));
}
+ if (alsaDeviceProxies.empty()) {
+ return ::android::NO_INIT;
+ }
mAlsaDeviceProxies = std::move(alsaDeviceProxies);
return ::android::OK;
}
@@ -110,6 +117,7 @@
mReadWriteRetries);
maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
} else {
+ alsa::applyGain(buffer, mGain, bytesToTransfer, mConfig.value().format, mConfig->channels);
for (auto& proxy : mAlsaDeviceProxies) {
proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
@@ -159,4 +167,9 @@
mAlsaDeviceProxies.clear();
}
+ndk::ScopedAStatus StreamAlsa::setGain(float gain) {
+ mGain = gain;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/alsa/Utils.cpp b/audio/aidl/default/alsa/Utils.cpp
index 8eaf162..10374f2 100644
--- a/audio/aidl/default/alsa/Utils.cpp
+++ b/audio/aidl/default/alsa/Utils.cpp
@@ -22,6 +22,8 @@
#include <aidl/android/media/audio/common/AudioFormatType.h>
#include <aidl/android/media/audio/common/PcmType.h>
#include <android-base/logging.h>
+#include <audio_utils/primitives.h>
+#include <cutils/compiler.h>
#include "Utils.h"
#include "core-impl/utils.h"
@@ -343,4 +345,68 @@
return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
}
+void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat,
+ int channelCount) {
+ if (channelCount != 1 && channelCount != 2) {
+ LOG(WARNING) << __func__ << ": unsupported channel count " << channelCount;
+ return;
+ }
+ if (!getPcmFormatToAudioFormatDescMap().contains(pcmFormat)) {
+ LOG(WARNING) << __func__ << ": unsupported pcm format " << pcmFormat;
+ return;
+ }
+ const float unityGainFloat = 1.0f;
+ if (std::abs(gain - unityGainFloat) < 1e-6) {
+ return;
+ }
+ int numFrames;
+ switch (pcmFormat) {
+ case PCM_FORMAT_S16_LE: {
+ const uint16_t unityGainQ4_12 = u4_12_from_float(unityGainFloat);
+ const uint16_t vl = u4_12_from_float(gain);
+ const uint32_t vrl = (vl << 16) | vl;
+ if (channelCount == 2) {
+ numFrames = bytesToTransfer / sizeof(uint32_t);
+ uint32_t* intBuffer = (uint32_t*)buffer;
+ if (CC_UNLIKELY(vl > unityGainQ4_12)) {
+ // volume is boosted, so we might need to clamp even though
+ // we process only one track.
+ do {
+ int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
+ int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
+ l = clamp16(l);
+ r = clamp16(r);
+ *intBuffer++ = (r << 16) | (l & 0xFFFF);
+ } while (--numFrames);
+ } else {
+ do {
+ int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
+ int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
+ *intBuffer++ = (r << 16) | (l & 0xFFFF);
+ } while (--numFrames);
+ }
+ } else {
+ numFrames = bytesToTransfer / sizeof(uint16_t);
+ int16_t* intBuffer = (int16_t*)buffer;
+ if (CC_UNLIKELY(vl > unityGainQ4_12)) {
+ // volume is boosted, so we might need to clamp even though
+ // we process only one track.
+ do {
+ int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
+ *intBuffer++ = clamp16(mono);
+ } while (--numFrames);
+ } else {
+ do {
+ int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
+ *intBuffer++ = static_cast<int16_t>(mono & 0xFFFF);
+ } while (--numFrames);
+ }
+ }
+ } break;
+ default:
+ // TODO(336370745): Implement gain for other supported formats
+ break;
+ }
+}
+
} // namespace aidl::android::hardware::audio::core::alsa
diff --git a/audio/aidl/default/alsa/Utils.h b/audio/aidl/default/alsa/Utils.h
index 980f685..a97ea10 100644
--- a/audio/aidl/default/alsa/Utils.h
+++ b/audio/aidl/default/alsa/Utils.h
@@ -59,6 +59,8 @@
AlsaProxy mProxy;
};
+void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat,
+ int channelCount);
::aidl::android::media::audio::common::AudioChannelLayout getChannelLayoutMaskFromChannelCount(
unsigned int channelCount, int isInput);
::aidl::android::media::audio::common::AudioChannelLayout getChannelIndexMaskFromChannelCount(
diff --git a/audio/aidl/default/config/audioPolicy/api/current.txt b/audio/aidl/default/config/audioPolicy/api/current.txt
index 3547f54..e57c108 100644
--- a/audio/aidl/default/config/audioPolicy/api/current.txt
+++ b/audio/aidl/default/config/audioPolicy/api/current.txt
@@ -191,6 +191,7 @@
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AAC_XHE;
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC3;
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC4;
+ enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AC4_L4;
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_ALAC;
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AMR_NB;
enum_constant public static final android.audio.policy.configuration.AudioFormat AUDIO_FORMAT_AMR_WB;
diff --git a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
index d93f697..108a6a3 100644
--- a/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
+++ b/audio/aidl/default/config/audioPolicy/audio_policy_configuration.xsd
@@ -389,6 +389,7 @@
<xs:enumeration value="AUDIO_FORMAT_APTX"/>
<xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
<xs:enumeration value="AUDIO_FORMAT_AC4"/>
+ <xs:enumeration value="AUDIO_FORMAT_AC4_L4"/>
<xs:enumeration value="AUDIO_FORMAT_LDAC"/>
<xs:enumeration value="AUDIO_FORMAT_MAT"/>
<xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
diff --git a/audio/aidl/default/include/core-impl/DriverStubImpl.h b/audio/aidl/default/include/core-impl/DriverStubImpl.h
new file mode 100644
index 0000000..40a9fea
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/DriverStubImpl.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "core-impl/Stream.h"
+
+namespace aidl::android::hardware::audio::core {
+
+class DriverStubImpl : virtual public DriverInterface {
+ public:
+ explicit DriverStubImpl(const StreamContext& context);
+
+ ::android::status_t init() override;
+ ::android::status_t drain(StreamDescriptor::DrainMode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
+ ::android::status_t standby() override;
+ ::android::status_t start() override;
+ ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
+ int32_t* latencyMs) override;
+ void shutdown() override;
+
+ private:
+ const size_t mBufferSizeFrames;
+ const size_t mFrameSizeBytes;
+ const int mSampleRate;
+ const bool mIsAsynchronous;
+ const bool mIsInput;
+ bool mIsInitialized = false; // Used for validating the state machine logic.
+ bool mIsStandby = true; // Used for validating the state machine logic.
+ int64_t mStartTimeNs = 0;
+ long mFramesSinceStart = 0;
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 00eeb4e..8548aff 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -263,6 +263,9 @@
::aidl::android::media::audio::common::AudioPortConfig* out_suggested, bool* applied);
ndk::ScopedAStatus updateStreamsConnectedState(const AudioPatch& oldPatch,
const AudioPatch& newPatch);
+ bool setAudioPortConfigGain(
+ const ::aidl::android::media::audio::common::AudioPort& port,
+ const ::aidl::android::media::audio::common::AudioGainConfig& gainRequested);
};
std::ostream& operator<<(std::ostream& os, Module::Type t);
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 100b4c8..f7b9269 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -38,6 +38,7 @@
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOffloadInfo.h>
#include <aidl/android/media/audio/common/MicrophoneInfo.h>
+#include <android-base/thread_annotations.h>
#include <error/expected_utils.h>
#include <fmq/AidlMessageQueue.h>
#include <system/thread_defs.h>
@@ -132,6 +133,9 @@
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
int getTransientStateDelayMs() const { return mDebugParameters.transientStateDelayMs; }
int getSampleRate() const { return mSampleRate; }
+ bool isInput() const {
+ return mFlags.getTag() == ::aidl::android::media::audio::common::AudioIoFlags::input;
+ }
bool isValid() const;
// 'reset' is called on a Binder thread when closing the stream. Does not use
// locking because it only cleans MQ pointers which were also set on the Binder thread.
@@ -342,6 +346,7 @@
virtual ndk::ScopedAStatus setConnectedDevices(
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) = 0;
virtual ndk::ScopedAStatus bluetoothParametersUpdated() = 0;
+ virtual ndk::ScopedAStatus setGain(float gain) = 0;
};
// This is equivalent to automatically generated 'IStreamCommonDelegator' but uses
@@ -443,6 +448,7 @@
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
+ ndk::ScopedAStatus setGain(float gain) override;
protected:
static StreamWorkerInterface::CreateInstance getDefaultInWorkerCreator() {
@@ -609,6 +615,12 @@
return ndk::ScopedAStatus::ok();
}
+ ndk::ScopedAStatus setGain(float gain) {
+ auto s = mStream.lock();
+ if (s) return s->setGain(gain);
+ return ndk::ScopedAStatus::ok();
+ }
+
private:
std::weak_ptr<StreamCommonInterface> mStream;
ndk::SpAIBinder mStreamBinder;
@@ -644,6 +656,12 @@
return isOk ? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ ndk::ScopedAStatus setGain(int32_t portId, float gain) {
+ if (auto it = mStreams.find(portId); it != mStreams.end()) {
+ return it->second.setGain(gain);
+ }
+ return ndk::ScopedAStatus::ok();
+ }
private:
// Maps port ids and port config ids to streams. Multimap because a port
diff --git a/audio/aidl/default/include/core-impl/StreamAlsa.h b/audio/aidl/default/include/core-impl/StreamAlsa.h
index 0356946..8bdf208 100644
--- a/audio/aidl/default/include/core-impl/StreamAlsa.h
+++ b/audio/aidl/default/include/core-impl/StreamAlsa.h
@@ -45,6 +45,7 @@
int32_t* latencyMs) override;
::android::status_t refinePosition(StreamDescriptor::Position* position) override;
void shutdown() override;
+ ndk::ScopedAStatus setGain(float gain) override;
protected:
// Called from 'start' to initialize 'mAlsaDeviceProxies', the vector must be non-empty.
@@ -58,6 +59,9 @@
const int mReadWriteRetries;
// All fields below are only used on the worker thread.
std::vector<alsa::DeviceProxy> mAlsaDeviceProxies;
+
+ private:
+ std::atomic<float> mGain = 1.0;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamPrimary.h b/audio/aidl/default/include/core-impl/StreamPrimary.h
index 8d5c57d..4f19a46 100644
--- a/audio/aidl/default/include/core-impl/StreamPrimary.h
+++ b/audio/aidl/default/include/core-impl/StreamPrimary.h
@@ -16,10 +16,14 @@
#pragma once
+#include <mutex>
#include <vector>
+#include <android-base/thread_annotations.h>
+
+#include "DriverStubImpl.h"
#include "StreamAlsa.h"
-#include "StreamSwitcher.h"
+#include "primary/PrimaryMixer.h"
namespace aidl::android::hardware::audio::core {
@@ -27,21 +31,54 @@
public:
StreamPrimary(StreamContext* context, const Metadata& metadata);
+ // Methods of 'DriverInterface'.
+ ::android::status_t init() override;
+ ::android::status_t drain(StreamDescriptor::DrainMode mode) override;
+ ::android::status_t flush() override;
+ ::android::status_t pause() override;
+ ::android::status_t standby() override;
::android::status_t start() override;
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
int32_t* latencyMs) override;
::android::status_t refinePosition(StreamDescriptor::Position* position) override;
+ void shutdown() override;
+
+ // Overridden methods of 'StreamCommonImpl', called on a Binder thread.
+ ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
protected:
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
+ bool isStubStream();
const bool mIsAsynchronous;
int64_t mStartTimeNs = 0;
long mFramesSinceStart = 0;
bool mSkipNextTransfer = false;
+
+ private:
+ using AlsaDeviceId = std::pair<int, int>;
+
+ static constexpr StreamPrimary::AlsaDeviceId kDefaultCardAndDeviceId{
+ primary::PrimaryMixer::kAlsaCard, primary::PrimaryMixer::kAlsaDevice};
+ static constexpr StreamPrimary::AlsaDeviceId kStubDeviceId{
+ primary::PrimaryMixer::kInvalidAlsaCard, primary::PrimaryMixer::kInvalidAlsaDevice};
+
+ static AlsaDeviceId getCardAndDeviceId(
+ const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices);
+ static bool useStubStream(bool isInput,
+ const ::aidl::android::media::audio::common::AudioDevice& device);
+
+ bool isStubStreamOnWorker() const { return mCurrAlsaDeviceId == kStubDeviceId; }
+
+ DriverStubImpl mStubDriver;
+ mutable std::mutex mLock;
+ AlsaDeviceId mAlsaDeviceId GUARDED_BY(mLock) = kStubDeviceId;
+
+ // Used by the worker thread only.
+ AlsaDeviceId mCurrAlsaDeviceId = kStubDeviceId;
};
-class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
+class StreamInPrimary final : public StreamIn, public StreamPrimary, public StreamInHwGainHelper {
public:
friend class ndk::SharedRefBase;
StreamInPrimary(
@@ -50,14 +87,6 @@
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
- static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
-
- DeviceSwitchBehavior switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
- override;
- std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getHwGain(std::vector<float>* _aidl_return) override;
@@ -65,7 +94,7 @@
};
class StreamOutPrimary final : public StreamOut,
- public StreamSwitcher,
+ public StreamPrimary,
public StreamOutHwVolumeHelper {
public:
friend class ndk::SharedRefBase;
@@ -75,22 +104,10 @@
offloadInfo);
private:
- static bool useStubStream(const ::aidl::android::media::audio::common::AudioDevice& device);
-
- DeviceSwitchBehavior switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
- override;
- std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getHwVolume(std::vector<float>* _aidl_return) override;
ndk::ScopedAStatus setHwVolume(const std::vector<float>& in_channelVolumes) override;
-
- ndk::ScopedAStatus setConnectedDevices(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
- override;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
index 6ea7968..e78e8b7 100644
--- a/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
+++ b/audio/aidl/default/include/core-impl/StreamRemoteSubmix.h
@@ -16,19 +16,18 @@
#pragma once
+#include <atomic>
+#include <mutex>
#include <vector>
#include "core-impl/Stream.h"
-#include "core-impl/StreamSwitcher.h"
#include "r_submix/SubmixRoute.h"
namespace aidl::android::hardware::audio::core {
class StreamRemoteSubmix : public StreamCommonImpl {
public:
- StreamRemoteSubmix(
- StreamContext* context, const Metadata& metadata,
- const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
+ StreamRemoteSubmix(StreamContext* context, const Metadata& metadata);
~StreamRemoteSubmix();
// Methods of 'DriverInterface'.
@@ -45,17 +44,18 @@
// Overridden methods of 'StreamCommonImpl', called on a Binder thread.
ndk::ScopedAStatus prepareToClose() override;
+ ndk::ScopedAStatus setConnectedDevices(const ConnectedDevices& devices) override;
private:
long getDelayInUsForFrameCount(size_t frameCount);
+ ::aidl::android::media::audio::common::AudioDeviceAddress getDeviceAddress() const {
+ std::lock_guard guard(mLock);
+ return mDeviceAddress;
+ }
size_t getStreamPipeSizeInFrames();
- ::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
::android::status_t inRead(void* buffer, size_t frameCount, size_t* actualFrameCount);
-
- const ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress;
- const bool mIsInput;
- r_submix::AudioConfig mStreamConfig;
- std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
+ ::android::status_t outWrite(void* buffer, size_t frameCount, size_t* actualFrameCount);
+ ::android::status_t setCurrentRoute();
// Limit for the number of error log entries to avoid spamming the logs.
static constexpr int kMaxErrorLogs = 5;
@@ -66,6 +66,15 @@
// 5ms between two read attempts when pipe is empty
static constexpr int kReadAttemptSleepUs = 5000;
+ const bool mIsInput;
+ const r_submix::AudioConfig mStreamConfig;
+
+ mutable std::mutex mLock;
+ ::aidl::android::media::audio::common::AudioDeviceAddress mDeviceAddress GUARDED_BY(mLock);
+ std::atomic<bool> mDeviceAddressUpdated = false;
+
+ // Used by the worker thread only.
+ std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
int64_t mStartTimeNs = 0;
long mFramesSinceStart = 0;
int mReadErrorCount = 0;
@@ -73,7 +82,7 @@
int mWriteShutdownCount = 0;
};
-class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
+class StreamInRemoteSubmix final : public StreamIn, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamInRemoteSubmix(
@@ -82,19 +91,13 @@
const std::vector<::aidl::android::media::audio::common::MicrophoneInfo>& microphones);
private:
- DeviceSwitchBehavior switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
- override;
- std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
ndk::ScopedAStatus getActiveMicrophones(
std::vector<::aidl::android::media::audio::common::MicrophoneDynamicInfo>* _aidl_return)
override;
};
-class StreamOutRemoteSubmix final : public StreamOut, public StreamSwitcher {
+class StreamOutRemoteSubmix final : public StreamOut, public StreamRemoteSubmix {
public:
friend class ndk::SharedRefBase;
StreamOutRemoteSubmix(
@@ -104,12 +107,6 @@
offloadInfo);
private:
- DeviceSwitchBehavior switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
- override;
- std::unique_ptr<StreamCommonInterfaceEx> createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) override;
void onClose(StreamDescriptor::State) override { defaultOnClose(); }
};
diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h
index 22b2020..cee44db 100644
--- a/audio/aidl/default/include/core-impl/StreamStub.h
+++ b/audio/aidl/default/include/core-impl/StreamStub.h
@@ -16,38 +16,15 @@
#pragma once
+#include "core-impl/DriverStubImpl.h"
#include "core-impl/Stream.h"
namespace aidl::android::hardware::audio::core {
-class StreamStub : public StreamCommonImpl {
+class StreamStub : public StreamCommonImpl, public DriverStubImpl {
public:
StreamStub(StreamContext* context, const Metadata& metadata);
~StreamStub();
-
- // Methods of 'DriverInterface'.
- ::android::status_t init() override;
- ::android::status_t drain(StreamDescriptor::DrainMode) override;
- ::android::status_t flush() override;
- ::android::status_t pause() override;
- ::android::status_t standby() override;
- ::android::status_t start() override;
- ::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
- int32_t* latencyMs) override;
- void shutdown() override;
-
- private:
- const size_t mBufferSizeFrames;
- const size_t mFrameSizeBytes;
- const int mSampleRate;
- const bool mIsAsynchronous;
- const bool mIsInput;
- bool mIsInitialized = false; // Used for validating the state machine logic.
- bool mIsStandby = true; // Used for validating the state machine logic.
-
- // Used by the worker thread.
- int64_t mStartTimeNs = 0;
- long mFramesSinceStart = 0;
};
class StreamInStub final : public StreamIn, public StreamStub {
diff --git a/audio/aidl/default/include/core-impl/StreamSwitcher.h b/audio/aidl/default/include/core-impl/StreamSwitcher.h
index 5764ad6..2d75e85 100644
--- a/audio/aidl/default/include/core-impl/StreamSwitcher.h
+++ b/audio/aidl/default/include/core-impl/StreamSwitcher.h
@@ -130,6 +130,7 @@
const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices)
override;
ndk::ScopedAStatus bluetoothParametersUpdated() override;
+ ndk::ScopedAStatus setGain(float gain) override;
protected:
// Since switching a stream requires closing down the current stream, StreamSwitcher
diff --git a/audio/aidl/default/primary/PrimaryMixer.h b/audio/aidl/default/primary/PrimaryMixer.h
index 3806428..760d42f 100644
--- a/audio/aidl/default/primary/PrimaryMixer.h
+++ b/audio/aidl/default/primary/PrimaryMixer.h
@@ -16,20 +16,14 @@
#pragma once
-#include <map>
-#include <memory>
-#include <mutex>
-#include <vector>
-
-#include <android-base/thread_annotations.h>
-#include <android/binder_auto_utils.h>
-
#include "alsa/Mixer.h"
namespace aidl::android::hardware::audio::core::primary {
class PrimaryMixer : public alsa::Mixer {
public:
+ static constexpr int kInvalidAlsaCard = -1;
+ static constexpr int kInvalidAlsaDevice = -1;
static constexpr int kAlsaCard = 0;
static constexpr int kAlsaDevice = 0;
diff --git a/audio/aidl/default/primary/StreamPrimary.cpp b/audio/aidl/default/primary/StreamPrimary.cpp
index 7325a91..1176d05 100644
--- a/audio/aidl/default/primary/StreamPrimary.cpp
+++ b/audio/aidl/default/primary/StreamPrimary.cpp
@@ -15,19 +15,22 @@
*/
#define LOG_TAG "AHAL_StreamPrimary"
+
+#include <cstdio>
+
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <audio_utils/clock.h>
#include <error/Result.h>
#include <error/expected_utils.h>
-#include "PrimaryMixer.h"
#include "core-impl/StreamPrimary.h"
-#include "core-impl/StreamStub.h"
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioOffloadInfo;
@@ -38,11 +41,47 @@
StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
: StreamAlsa(context, metadata, 3 /*readWriteRetries*/),
- mIsAsynchronous(!!getContext().getAsyncCallback()) {
+ mIsAsynchronous(!!getContext().getAsyncCallback()),
+ mStubDriver(getContext()) {
context->startStreamDataProcessor();
}
+::android::status_t StreamPrimary::init() {
+ RETURN_STATUS_IF_ERROR(mStubDriver.init());
+ return StreamAlsa::init();
+}
+
+::android::status_t StreamPrimary::drain(StreamDescriptor::DrainMode mode) {
+ return isStubStreamOnWorker() ? mStubDriver.drain(mode) : StreamAlsa::drain(mode);
+}
+
+::android::status_t StreamPrimary::flush() {
+ return isStubStreamOnWorker() ? mStubDriver.flush() : StreamAlsa::flush();
+}
+
+::android::status_t StreamPrimary::pause() {
+ return isStubStreamOnWorker() ? mStubDriver.pause() : StreamAlsa::pause();
+}
+
+::android::status_t StreamPrimary::standby() {
+ return isStubStreamOnWorker() ? mStubDriver.standby() : StreamAlsa::standby();
+}
+
::android::status_t StreamPrimary::start() {
+ bool isStub = true, shutdownAlsaStream = false;
+ {
+ std::lock_guard l(mLock);
+ isStub = mAlsaDeviceId == kStubDeviceId;
+ shutdownAlsaStream =
+ mCurrAlsaDeviceId != mAlsaDeviceId && mCurrAlsaDeviceId != kStubDeviceId;
+ mCurrAlsaDeviceId = mAlsaDeviceId;
+ }
+ if (shutdownAlsaStream) {
+ StreamAlsa::shutdown(); // Close currently opened ALSA devices.
+ }
+ if (isStub) {
+ return mStubDriver.start();
+ }
RETURN_STATUS_IF_ERROR(StreamAlsa::start());
mStartTimeNs = ::android::uptimeNanos();
mFramesSinceStart = 0;
@@ -52,6 +91,9 @@
::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
+ if (isStubStreamOnWorker()) {
+ return mStubDriver.transfer(buffer, frameCount, actualFrameCount, latencyMs);
+ }
// This is a workaround for the emulator implementation which has a host-side buffer
// and is not being able to achieve real-time behavior similar to ADSPs (b/302587331).
if (!mSkipNextTransfer) {
@@ -91,63 +133,85 @@
return ::android::OK;
}
+void StreamPrimary::shutdown() {
+ StreamAlsa::shutdown();
+ mStubDriver.shutdown();
+}
+
+ndk::ScopedAStatus StreamPrimary::setConnectedDevices(const ConnectedDevices& devices) {
+ LOG(DEBUG) << __func__ << ": " << ::android::internal::ToString(devices);
+ if (devices.size() > 1) {
+ LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
+ << devices.size();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ {
+ const bool useStubDriver = devices.empty() || useStubStream(mIsInput, devices[0]);
+ std::lock_guard l(mLock);
+ mAlsaDeviceId = useStubDriver ? kStubDeviceId : getCardAndDeviceId(devices);
+ }
+ if (!devices.empty()) {
+ auto streamDataProcessor = getContext().getStreamDataProcessor().lock();
+ if (streamDataProcessor != nullptr) {
+ streamDataProcessor->setAudioDevice(devices[0]);
+ }
+ }
+ return StreamAlsa::setConnectedDevices(devices);
+}
+
std::vector<alsa::DeviceProfile> StreamPrimary::getDeviceProfiles() {
- static const std::vector<alsa::DeviceProfile> kBuiltInSource{
- alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
- .device = primary::PrimaryMixer::kAlsaDevice,
- .direction = PCM_IN,
+ return {alsa::DeviceProfile{.card = mCurrAlsaDeviceId.first,
+ .device = mCurrAlsaDeviceId.second,
+ .direction = mIsInput ? PCM_IN : PCM_OUT,
.isExternal = false}};
- static const std::vector<alsa::DeviceProfile> kBuiltInSink{
- alsa::DeviceProfile{.card = primary::PrimaryMixer::kAlsaCard,
- .device = primary::PrimaryMixer::kAlsaDevice,
- .direction = PCM_OUT,
- .isExternal = false}};
- return mIsInput ? kBuiltInSource : kBuiltInSink;
+}
+
+bool StreamPrimary::isStubStream() {
+ std::lock_guard l(mLock);
+ return mAlsaDeviceId == kStubDeviceId;
+}
+
+// static
+StreamPrimary::AlsaDeviceId StreamPrimary::getCardAndDeviceId(
+ const std::vector<AudioDevice>& devices) {
+ if (devices.empty() || devices[0].address.getTag() != AudioDeviceAddress::id) {
+ return kDefaultCardAndDeviceId;
+ }
+ std::string deviceAddress = devices[0].address.get<AudioDeviceAddress::id>();
+ AlsaDeviceId cardAndDeviceId;
+ if (const size_t suffixPos = deviceAddress.rfind("CARD_");
+ suffixPos == std::string::npos ||
+ sscanf(deviceAddress.c_str() + suffixPos, "CARD_%d_DEV_%d", &cardAndDeviceId.first,
+ &cardAndDeviceId.second) != 2) {
+ return kDefaultCardAndDeviceId;
+ }
+ LOG(DEBUG) << __func__ << ": parsed with card id " << cardAndDeviceId.first << ", device id "
+ << cardAndDeviceId.second;
+ return cardAndDeviceId;
+}
+
+// static
+bool StreamPrimary::useStubStream(
+ bool isInput, const ::aidl::android::media::audio::common::AudioDevice& device) {
+ static const bool kSimulateInput =
+ GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
+ static const bool kSimulateOutput =
+ GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
+ if (isInput) {
+ return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
+ device.type.type == AudioDeviceType::IN_FM_TUNER ||
+ device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */;
+ }
+ return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
+ device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/;
}
StreamInPrimary::StreamInPrimary(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamIn(std::move(context), microphones),
- StreamSwitcher(&mContextInstance, sinkMetadata),
+ StreamPrimary(&mContextInstance, sinkMetadata),
StreamInHwGainHelper(&mContextInstance) {}
-bool StreamInPrimary::useStubStream(const AudioDevice& device) {
- static const bool kSimulateInput =
- GetBoolProperty("ro.boot.audio.tinyalsa.simulate_input", false);
- return kSimulateInput || device.type.type == AudioDeviceType::IN_TELEPHONY_RX ||
- device.type.type == AudioDeviceType::IN_FM_TUNER ||
- device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated */ ||
- (device.type.type == AudioDeviceType::IN_BUS && device.type.connection.empty());
-}
-
-StreamSwitcher::DeviceSwitchBehavior StreamInPrimary::switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- LOG(DEBUG) << __func__;
- if (devices.size() > 1) {
- LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
- << devices.size();
- return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
- }
- if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
- return DeviceSwitchBehavior::USE_CURRENT_STREAM;
- }
- return DeviceSwitchBehavior::CREATE_NEW_STREAM;
-}
-
-std::unique_ptr<StreamCommonInterfaceEx> StreamInPrimary::createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) {
- if (devices.empty()) {
- LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
- }
- if (useStubStream(devices[0])) {
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamStub>(context, metadata));
- }
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamPrimary>(context, metadata));
-}
-
ndk::ScopedAStatus StreamInPrimary::getHwGain(std::vector<float>* _aidl_return) {
if (isStubStream()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -181,45 +245,9 @@
StreamOutPrimary::StreamOutPrimary(StreamContext&& context, const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamOut(std::move(context), offloadInfo),
- StreamSwitcher(&mContextInstance, sourceMetadata),
+ StreamPrimary(&mContextInstance, sourceMetadata),
StreamOutHwVolumeHelper(&mContextInstance) {}
-bool StreamOutPrimary::useStubStream(const AudioDevice& device) {
- static const bool kSimulateOutput =
- GetBoolProperty("ro.boot.audio.tinyalsa.ignore_output", false);
- return kSimulateOutput || device.type.type == AudioDeviceType::OUT_TELEPHONY_TX ||
- device.type.connection == AudioDeviceDescription::CONNECTION_BUS /*deprecated*/ ||
- (device.type.type == AudioDeviceType::OUT_BUS && device.type.connection.empty());
-}
-
-StreamSwitcher::DeviceSwitchBehavior StreamOutPrimary::switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- LOG(DEBUG) << __func__;
- if (devices.size() > 1) {
- LOG(ERROR) << __func__ << ": primary stream can only be connected to one device, got: "
- << devices.size();
- return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
- }
- if (devices.empty() || useStubStream(devices[0]) == isStubStream()) {
- return DeviceSwitchBehavior::USE_CURRENT_STREAM;
- }
- return DeviceSwitchBehavior::CREATE_NEW_STREAM;
-}
-
-std::unique_ptr<StreamCommonInterfaceEx> StreamOutPrimary::createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) {
- if (devices.empty()) {
- LOG(FATAL) << __func__ << ": called with empty devices"; // see 'switchCurrentStream'
- }
- if (useStubStream(devices[0])) {
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamStub>(context, metadata));
- }
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamPrimary>(context, metadata));
-}
-
ndk::ScopedAStatus StreamOutPrimary::getHwVolume(std::vector<float>* _aidl_return) {
if (isStubStream()) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
@@ -245,15 +273,4 @@
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus StreamOutPrimary::setConnectedDevices(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- if (!devices.empty()) {
- auto streamDataProcessor = mContextInstance.getStreamDataProcessor().lock();
- if (streamDataProcessor != nullptr) {
- streamDataProcessor->setAudioDevice(devices[0]);
- }
- }
- return StreamSwitcher::setConnectedDevices(devices);
-}
-
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
index db105b6..93fe028 100644
--- a/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
+++ b/audio/aidl/default/r_submix/StreamRemoteSubmix.cpp
@@ -26,128 +26,106 @@
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::audio::core::r_submix::SubmixRoute;
using aidl::android::media::audio::common::AudioDeviceAddress;
+using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioOffloadInfo;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
namespace aidl::android::hardware::audio::core {
-StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata,
- const AudioDeviceAddress& deviceAddress)
+StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& metadata)
: StreamCommonImpl(context, metadata),
- mDeviceAddress(deviceAddress),
- mIsInput(isInput(metadata)) {
- mStreamConfig.frameSize = context->getFrameSize();
- mStreamConfig.format = context->getFormat();
- mStreamConfig.channelLayout = context->getChannelLayout();
- mStreamConfig.sampleRate = context->getSampleRate();
-}
+ mIsInput(isInput(metadata)),
+ mStreamConfig{.sampleRate = context->getSampleRate(),
+ .format = context->getFormat(),
+ .channelLayout = context->getChannelLayout(),
+ .frameSize = context->getFrameSize()} {}
StreamRemoteSubmix::~StreamRemoteSubmix() {
cleanupWorker();
}
::android::status_t StreamRemoteSubmix::init() {
- mCurrentRoute = SubmixRoute::findOrCreateRoute(mDeviceAddress, mStreamConfig);
- if (mCurrentRoute == nullptr) {
- return ::android::NO_INIT;
- }
- if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
- LOG(ERROR) << __func__ << ": invalid stream config";
- return ::android::NO_INIT;
- }
- sp<MonoPipe> sink = mCurrentRoute->getSink();
- if (sink == nullptr) {
- LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
- return ::android::NO_INIT;
- }
- if ((!mIsInput || mCurrentRoute->isStreamInOpen()) && sink->isShutdown()) {
- LOG(DEBUG) << __func__ << ": Shut down sink when opening stream";
- if (::android::OK != mCurrentRoute->resetPipe()) {
- LOG(ERROR) << __func__ << ": reset pipe failed";
- return ::android::NO_INIT;
- }
- }
- mCurrentRoute->openStream(mIsInput);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::drain(StreamDescriptor::DrainMode) {
- usleep(1000);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::flush() {
- usleep(1000);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::pause() {
- usleep(1000);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::standby() {
- mCurrentRoute->standby(mIsInput);
+ if (mCurrentRoute) mCurrentRoute->standby(mIsInput);
return ::android::OK;
}
::android::status_t StreamRemoteSubmix::start() {
- mCurrentRoute->exitStandby(mIsInput);
+ if (mDeviceAddressUpdated.load(std::memory_order_acquire)) {
+ LOG(DEBUG) << __func__ << ": device address updated, reset current route";
+ shutdown();
+ mDeviceAddressUpdated.store(false, std::memory_order_release);
+ }
+ if (!mCurrentRoute) {
+ RETURN_STATUS_IF_ERROR(setCurrentRoute());
+ LOG(DEBUG) << __func__ << ": have current route? " << (mCurrentRoute != nullptr);
+ }
+ if (mCurrentRoute) mCurrentRoute->exitStandby(mIsInput);
mStartTimeNs = ::android::uptimeNanos();
mFramesSinceStart = 0;
return ::android::OK;
}
-ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
- if (!mIsInput) {
- std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(mDeviceAddress);
- if (route != nullptr) {
- sp<MonoPipe> sink = route->getSink();
- if (sink == nullptr) {
- ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
-
- sink->shutdown(true);
- // The client already considers this stream as closed, release the output end.
- route->closeStream(mIsInput);
- } else {
- LOG(DEBUG) << __func__ << ": stream already closed.";
- ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
- }
- }
- return ndk::ScopedAStatus::ok();
-}
-
// Remove references to the specified input and output streams. When the device no longer
// references input and output streams destroy the associated pipe.
void StreamRemoteSubmix::shutdown() {
+ if (!mCurrentRoute) return;
mCurrentRoute->closeStream(mIsInput);
// If all stream instances are closed, we can remove route information for this port.
if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
mCurrentRoute->releasePipe();
LOG(DEBUG) << __func__ << ": pipe destroyed";
- SubmixRoute::removeRoute(mDeviceAddress);
+ SubmixRoute::removeRoute(getDeviceAddress());
}
mCurrentRoute.reset();
}
::android::status_t StreamRemoteSubmix::transfer(void* buffer, size_t frameCount,
size_t* actualFrameCount, int32_t* latencyMs) {
+ if (mDeviceAddressUpdated.load(std::memory_order_acquire)) {
+ // 'setConnectedDevices' was called. I/O will be restarted.
+ return ::android::OK;
+ }
+
*latencyMs = getDelayInUsForFrameCount(getStreamPipeSizeInFrames()) / 1000;
LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
- mCurrentRoute->exitStandby(mIsInput);
- ::android::status_t status = mIsInput ? inRead(buffer, frameCount, actualFrameCount)
- : outWrite(buffer, frameCount, actualFrameCount);
- if ((status != ::android::OK && mIsInput) ||
- ((status != ::android::OK && status != ::android::DEAD_OBJECT) && !mIsInput)) {
- return status;
+ ::android::status_t status = ::android::OK;
+ if (mCurrentRoute) {
+ mCurrentRoute->exitStandby(mIsInput);
+ status = mIsInput ? inRead(buffer, frameCount, actualFrameCount)
+ : outWrite(buffer, frameCount, actualFrameCount);
+ if ((status != ::android::OK && mIsInput) ||
+ ((status != ::android::OK && status != ::android::DEAD_OBJECT) && !mIsInput)) {
+ return status;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": no current route";
+ if (mIsInput) {
+ memset(buffer, 0, mStreamConfig.frameSize * frameCount);
+ }
+ *actualFrameCount = frameCount;
}
mFramesSinceStart += *actualFrameCount;
- if (!mIsInput && status != ::android::DEAD_OBJECT) return ::android::OK;
- // Input streams always need to block, output streams need to block when there is no sink.
- // When the sink exists, more sophisticated blocking algorithm is implemented by MonoPipe.
+ // If there is no route, always block, otherwise:
+ // - Input streams always need to block, output streams need to block when there is no sink.
+ // - When the sink exists, more sophisticated blocking algorithm is implemented by MonoPipe.
+ if (mCurrentRoute && !mIsInput && status != ::android::DEAD_OBJECT) return ::android::OK;
const long bufferDurationUs =
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
@@ -163,6 +141,10 @@
}
::android::status_t StreamRemoteSubmix::refinePosition(StreamDescriptor::Position* position) {
+ if (!mCurrentRoute) {
+ RETURN_STATUS_IF_ERROR(setCurrentRoute());
+ if (!mCurrentRoute) return ::android::OK;
+ }
sp<MonoPipeReader> source = mCurrentRoute->getSource();
if (source == nullptr) {
return ::android::NO_INIT;
@@ -186,6 +168,7 @@
// Calculate the maximum size of the pipe buffer in frames for the specified stream.
size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
+ if (!mCurrentRoute) return r_submix::kDefaultPipeSizeInFrames;
auto pipeConfig = mCurrentRoute->getPipeConfig();
const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
@@ -209,7 +192,7 @@
}
mWriteShutdownCount = 0;
- LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
+ LOG(VERBOSE) << __func__ << ": " << getDeviceAddress().toString() << ", " << frameCount
<< " frames";
const bool shouldBlockWrite = mCurrentRoute->shouldBlockWrite();
@@ -283,8 +266,9 @@
}
mReadErrorCount = 0;
- LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
+ LOG(VERBOSE) << __func__ << ": " << getDeviceAddress().toString() << ", " << frameCount
<< " frames";
+
// read the data from the pipe
char* buff = (char*)buffer;
size_t actuallyRead = 0;
@@ -324,10 +308,91 @@
return ::android::OK;
}
+::android::status_t StreamRemoteSubmix::setCurrentRoute() {
+ const auto address = getDeviceAddress();
+ if (address == AudioDeviceAddress{}) {
+ return ::android::OK;
+ }
+ mCurrentRoute = SubmixRoute::findOrCreateRoute(address, mStreamConfig);
+ if (mCurrentRoute == nullptr) {
+ return ::android::NO_INIT;
+ }
+ if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
+ LOG(ERROR) << __func__ << ": invalid stream config";
+ return ::android::NO_INIT;
+ }
+ sp<MonoPipe> sink = mCurrentRoute->getSink();
+ if (sink == nullptr) {
+ LOG(ERROR) << __func__ << ": nullptr sink when opening stream";
+ return ::android::NO_INIT;
+ }
+ if ((!mIsInput || mCurrentRoute->isStreamInOpen()) && sink->isShutdown()) {
+ LOG(DEBUG) << __func__ << ": Shut down sink when opening stream";
+ if (::android::OK != mCurrentRoute->resetPipe()) {
+ LOG(ERROR) << __func__ << ": reset pipe failed";
+ return ::android::NO_INIT;
+ }
+ }
+ mCurrentRoute->openStream(mIsInput);
+ return ::android::OK;
+}
+
+ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
+ if (!mIsInput) {
+ const auto address = getDeviceAddress();
+ if (address == AudioDeviceAddress{}) return ndk::ScopedAStatus::ok();
+ std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(address);
+ if (route != nullptr) {
+ sp<MonoPipe> sink = route->getSink();
+ if (sink == nullptr) {
+ ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ LOG(DEBUG) << __func__ << ": shutting down MonoPipe sink";
+
+ sink->shutdown(true);
+ // The client already considers this stream as closed, release the output end.
+ route->closeStream(mIsInput);
+ } else {
+ LOG(DEBUG) << __func__ << ": stream already closed.";
+ ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus StreamRemoteSubmix::setConnectedDevices(const ConnectedDevices& devices) {
+ if (devices.size() > 1) {
+ LOG(ERROR) << __func__ << ": Only single device supported, got " << devices.size();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ AudioDeviceAddress newAddress;
+ if (!devices.empty()) {
+ if (auto deviceDesc = devices.front().type;
+ (mIsInput && deviceDesc.type != AudioDeviceType::IN_SUBMIX) ||
+ (!mIsInput && deviceDesc.type != AudioDeviceType::OUT_SUBMIX)) {
+ LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
+ << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ }
+ newAddress = devices.front().address;
+ LOG(DEBUG) << __func__ << ": connected to " << newAddress.toString();
+ } else {
+ LOG(DEBUG) << __func__ << ": disconnected";
+ }
+ RETURN_STATUS_IF_ERROR(StreamCommonImpl::setConnectedDevices(devices));
+ std::lock_guard guard(mLock);
+ if (mDeviceAddress != newAddress) {
+ mDeviceAddress = newAddress;
+ mDeviceAddressUpdated.store(true, std::memory_order_release);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
StreamInRemoteSubmix::StreamInRemoteSubmix(StreamContext&& context,
const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
- : StreamIn(std::move(context), microphones), StreamSwitcher(&mContextInstance, sinkMetadata) {}
+ : StreamIn(std::move(context), microphones),
+ StreamRemoteSubmix(&mContextInstance, sinkMetadata) {}
ndk::ScopedAStatus StreamInRemoteSubmix::getActiveMicrophones(
std::vector<MicrophoneDynamicInfo>* _aidl_return) {
@@ -336,66 +401,10 @@
return ndk::ScopedAStatus::ok();
}
-StreamSwitcher::DeviceSwitchBehavior StreamInRemoteSubmix::switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- // This implementation effectively postpones stream creation until
- // receiving the first call to 'setConnectedDevices' with a non-empty list.
- if (isStubStream()) {
- if (devices.size() == 1) {
- auto deviceDesc = devices.front().type;
- if (deviceDesc.type ==
- ::aidl::android::media::audio::common::AudioDeviceType::IN_SUBMIX) {
- return DeviceSwitchBehavior::CREATE_NEW_STREAM;
- }
- LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
- << " not supported";
- } else {
- LOG(ERROR) << __func__ << ": Only single device supported.";
- }
- return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
- }
- return DeviceSwitchBehavior::USE_CURRENT_STREAM;
-}
-
-std::unique_ptr<StreamCommonInterfaceEx> StreamInRemoteSubmix::createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) {
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
-}
-
StreamOutRemoteSubmix::StreamOutRemoteSubmix(StreamContext&& context,
const SourceMetadata& sourceMetadata,
const std::optional<AudioOffloadInfo>& offloadInfo)
: StreamOut(std::move(context), offloadInfo),
- StreamSwitcher(&mContextInstance, sourceMetadata) {}
-
-StreamSwitcher::DeviceSwitchBehavior StreamOutRemoteSubmix::switchCurrentStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices) {
- // This implementation effectively postpones stream creation until
- // receiving the first call to 'setConnectedDevices' with a non-empty list.
- if (isStubStream()) {
- if (devices.size() == 1) {
- auto deviceDesc = devices.front().type;
- if (deviceDesc.type ==
- ::aidl::android::media::audio::common::AudioDeviceType::OUT_SUBMIX) {
- return DeviceSwitchBehavior::CREATE_NEW_STREAM;
- }
- LOG(ERROR) << __func__ << ": Device type " << toString(deviceDesc.type)
- << " not supported";
- } else {
- LOG(ERROR) << __func__ << ": Only single device supported.";
- }
- return DeviceSwitchBehavior::UNSUPPORTED_DEVICES;
- }
- return DeviceSwitchBehavior::USE_CURRENT_STREAM;
-}
-
-std::unique_ptr<StreamCommonInterfaceEx> StreamOutRemoteSubmix::createNewStream(
- const std::vector<::aidl::android::media::audio::common::AudioDevice>& devices,
- StreamContext* context, const Metadata& metadata) {
- return std::unique_ptr<StreamCommonInterfaceEx>(
- new InnerStreamWrapper<StreamRemoteSubmix>(context, metadata, devices.front().address));
-}
+ StreamRemoteSubmix(&mContextInstance, sourceMetadata) {}
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/r_submix/SubmixRoute.h b/audio/aidl/default/r_submix/SubmixRoute.h
index 5425f12..0097f39 100644
--- a/audio/aidl/default/r_submix/SubmixRoute.h
+++ b/audio/aidl/default/r_submix/SubmixRoute.h
@@ -25,10 +25,12 @@
#include <media/nbaio/MonoPipe.h>
#include <media/nbaio/MonoPipeReader.h>
+#include <Utils.h>
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
#include <aidl/android/media/audio/common/AudioDeviceAddress.h>
#include <aidl/android/media/audio/common/AudioFormatDescription.h>
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
@@ -56,8 +58,8 @@
AudioChannelLayout channelLayout =
AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
AudioChannelLayout::LAYOUT_STEREO);
- size_t frameSize;
- size_t frameCount;
+ size_t frameSize = getFrameSizeInBytes(format, channelLayout);
+ size_t frameCount = 0;
};
class SubmixRoute {
diff --git a/audio/aidl/default/stub/DriverStubImpl.cpp b/audio/aidl/default/stub/DriverStubImpl.cpp
new file mode 100644
index 0000000..beb0114
--- /dev/null
+++ b/audio/aidl/default/stub/DriverStubImpl.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cmath>
+
+#define LOG_TAG "AHAL_Stream"
+#include <android-base/logging.h>
+#include <audio_utils/clock.h>
+
+#include "core-impl/DriverStubImpl.h"
+
+namespace aidl::android::hardware::audio::core {
+
+DriverStubImpl::DriverStubImpl(const StreamContext& context)
+ : mBufferSizeFrames(context.getBufferSizeInFrames()),
+ mFrameSizeBytes(context.getFrameSize()),
+ mSampleRate(context.getSampleRate()),
+ mIsAsynchronous(!!context.getAsyncCallback()),
+ mIsInput(context.isInput()) {}
+
+::android::status_t DriverStubImpl::init() {
+ mIsInitialized = true;
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::drain(StreamDescriptor::DrainMode) {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ if (!mIsInput) {
+ if (!mIsAsynchronous) {
+ static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
+ const size_t delayUs = static_cast<size_t>(
+ std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
+ usleep(delayUs);
+ } else {
+ usleep(500);
+ }
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::flush() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::pause() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::standby() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ mIsStandby = true;
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::start() {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ mIsStandby = false;
+ mStartTimeNs = ::android::uptimeNanos();
+ mFramesSinceStart = 0;
+ return ::android::OK;
+}
+
+::android::status_t DriverStubImpl::transfer(void* buffer, size_t frameCount,
+ size_t* actualFrameCount, int32_t*) {
+ if (!mIsInitialized) {
+ LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
+ }
+ if (mIsStandby) {
+ LOG(FATAL) << __func__ << ": must not happen while in standby";
+ }
+ *actualFrameCount = frameCount;
+ if (mIsAsynchronous) {
+ usleep(500);
+ } else {
+ mFramesSinceStart += *actualFrameCount;
+ const long bufferDurationUs = (*actualFrameCount) * MICROS_PER_SECOND / mSampleRate;
+ const auto totalDurationUs =
+ (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
+ const long totalOffsetUs =
+ mFramesSinceStart * MICROS_PER_SECOND / mSampleRate - totalDurationUs;
+ LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
+ if (totalOffsetUs > 0) {
+ const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
+ LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
+ usleep(sleepTimeUs);
+ }
+ }
+ if (mIsInput) {
+ uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
+ for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
+ byteBuffer[i] = std::rand() % 255;
+ }
+ }
+ return ::android::OK;
+}
+
+void DriverStubImpl::shutdown() {
+ mIsInitialized = false;
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp
index a3d99a8..f6c87e1 100644
--- a/audio/aidl/default/stub/StreamStub.cpp
+++ b/audio/aidl/default/stub/StreamStub.cpp
@@ -32,110 +32,12 @@
namespace aidl::android::hardware::audio::core {
StreamStub::StreamStub(StreamContext* context, const Metadata& metadata)
- : StreamCommonImpl(context, metadata),
- mBufferSizeFrames(getContext().getBufferSizeInFrames()),
- mFrameSizeBytes(getContext().getFrameSize()),
- mSampleRate(getContext().getSampleRate()),
- mIsAsynchronous(!!getContext().getAsyncCallback()),
- mIsInput(isInput(metadata)) {}
+ : StreamCommonImpl(context, metadata), DriverStubImpl(getContext()) {}
StreamStub::~StreamStub() {
cleanupWorker();
}
-::android::status_t StreamStub::init() {
- mIsInitialized = true;
- return ::android::OK;
-}
-
-::android::status_t StreamStub::drain(StreamDescriptor::DrainMode) {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- if (!mIsInput) {
- if (!mIsAsynchronous) {
- static constexpr float kMicrosPerSecond = MICROS_PER_SECOND;
- const size_t delayUs = static_cast<size_t>(
- std::roundf(mBufferSizeFrames * kMicrosPerSecond / mSampleRate));
- usleep(delayUs);
- } else {
- usleep(500);
- }
- }
- return ::android::OK;
-}
-
-::android::status_t StreamStub::flush() {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- return ::android::OK;
-}
-
-::android::status_t StreamStub::pause() {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- return ::android::OK;
-}
-
-::android::status_t StreamStub::standby() {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- mIsStandby = true;
- return ::android::OK;
-}
-
-::android::status_t StreamStub::start() {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- mIsStandby = false;
- mStartTimeNs = ::android::uptimeNanos();
- mFramesSinceStart = 0;
- return ::android::OK;
-}
-
-::android::status_t StreamStub::transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
- int32_t*) {
- if (!mIsInitialized) {
- LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver";
- }
- if (mIsStandby) {
- LOG(FATAL) << __func__ << ": must not happen while in standby";
- }
- *actualFrameCount = frameCount;
- if (mIsAsynchronous) {
- usleep(500);
- } else {
- mFramesSinceStart += *actualFrameCount;
- const long bufferDurationUs =
- (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
- const auto totalDurationUs =
- (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
- const long totalOffsetUs =
- mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs;
- LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs;
- if (totalOffsetUs > 0) {
- const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs);
- LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us";
- usleep(sleepTimeUs);
- }
- }
- if (mIsInput) {
- uint8_t* byteBuffer = static_cast<uint8_t*>(buffer);
- for (size_t i = 0; i < frameCount * mFrameSizeBytes; ++i) {
- byteBuffer[i] = std::rand() % 255;
- }
- }
- return ::android::OK;
-}
-
-void StreamStub::shutdown() {
- mIsInitialized = false;
-}
-
StreamInStub::StreamInStub(StreamContext&& context, const SinkMetadata& sinkMetadata,
const std::vector<MicrophoneInfo>& microphones)
: StreamIn(std::move(context), microphones), StreamStub(&mContextInstance, sinkMetadata) {}
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 2bf70c7..9fe5801 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -87,6 +87,7 @@
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioDualMonoMode;
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::AudioLatencyMode;
@@ -450,6 +451,7 @@
// This is implemented by the 'StreamFixture' utility class.
static constexpr int kNegativeTestBufferSizeFrames = 256;
static constexpr int kDefaultLargeBufferSizeFrames = 48000;
+ static constexpr int32_t kAidlVersion3 = 3;
void SetUpImpl(const std::string& moduleName, bool setUpDebug = true) {
ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName, setUpDebug));
@@ -478,6 +480,7 @@
if (setUpDebug) {
ASSERT_NO_FATAL_FAILURE(SetUpDebug());
}
+ ASSERT_TRUE(module->getInterfaceVersion(&aidlVersion).isOk());
}
void RestartService() {
@@ -490,6 +493,7 @@
if (setUpDebug) {
ASSERT_NO_FATAL_FAILURE(SetUpDebug());
}
+ ASSERT_TRUE(module->getInterfaceVersion(&aidlVersion).isOk());
}
void SetUpDebug() {
@@ -577,6 +581,7 @@
std::unique_ptr<WithDebugFlags> debug;
std::vector<AudioPort> initialPorts;
std::vector<AudioRoute> initialRoutes;
+ int32_t aidlVersion;
};
class WithDevicePortConnectedState {
@@ -1821,6 +1826,46 @@
}
}
+TEST_P(AudioCoreModule, SetAudioPortConfigInvalidPortAudioGain) {
+ if (aidlVersion < kAidlVersion3) {
+ GTEST_SKIP() << "Skip for audio HAL version lower than " << kAidlVersion3;
+ }
+ std::vector<AudioPort> ports;
+ ASSERT_IS_OK(module->getAudioPorts(&ports));
+ bool atLeastOnePortWithNonemptyGain = false;
+ for (const auto port : ports) {
+ AudioPortConfig portConfig;
+ portConfig.portId = port.id;
+ if (port.gains.empty()) {
+ continue;
+ }
+ atLeastOnePortWithNonemptyGain = true;
+ int index = 0;
+ ASSERT_NE(0, port.gains[index].stepValue) << "Invalid audio port config gain step 0";
+ portConfig.gain->index = index;
+ AudioGainConfig invalidGainConfig;
+
+ int invalidGain = port.gains[index].maxValue + port.gains[index].stepValue;
+ invalidGainConfig.values.push_back(invalidGain);
+ portConfig.gain.emplace(invalidGainConfig);
+ bool applied = true;
+ AudioPortConfig suggestedConfig;
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+ << "invalid port gain " << invalidGain << " lower than min gain";
+
+ invalidGain = port.gains[index].minValue - port.gains[index].stepValue;
+ invalidGainConfig.values[0] = invalidGain;
+ portConfig.gain.emplace(invalidGainConfig);
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ module->setAudioPortConfig(portConfig, &suggestedConfig, &applied))
+ << "invalid port gain " << invalidGain << "higher than max gain";
+ }
+ if (!atLeastOnePortWithNonemptyGain) {
+ GTEST_SKIP() << "No audio port contains non-empty gain configuration";
+ }
+}
+
TEST_P(AudioCoreModule, TryConnectMissingDevice) {
// Limit checks to connection types that are known to be detectable by HAL implementations.
static const std::set<std::string> kCheckedConnectionTypes{
diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
index c77a228..f89cb40 100644
--- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp
@@ -191,6 +191,7 @@
}
TEST_P(VisualizerParamTest, testCaptureSampleBufferSizeAndOutput) {
+ SKIP_TEST_IF_DATA_UNSUPPORTED(mDescriptor.common.flags);
ASSERT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize));
ASSERT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode));
ASSERT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode));
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 6668d16..b301557 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -538,6 +538,9 @@
<< getErrorMsg(writeResult);
}
break;
+ case toInt(VehicleApPowerStateReport::ON):
+ ALOGI("Received VehicleApPowerStateReport::ON, entering normal operating state");
+ break;
default:
ALOGE("Unknown VehicleApPowerStateReport: %d", state);
break;
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index fa2a310..b58d0f5 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -31,6 +31,7 @@
#include <android-base/thread_annotations.h>
#include <android/binder_auto_utils.h>
+#include <functional>
#include <memory>
#include <mutex>
#include <shared_mutex>
@@ -138,12 +139,11 @@
// Only used for testing.
int32_t mTestInterfaceVersion = 0;
- // mConfigsByPropId and mConfigFile is lazy initialized.
- mutable std::mutex mConfigInitLock;
- mutable bool mConfigInit GUARDED_BY(mConfigInitLock) = false;
+ mutable std::atomic<bool> mConfigInit = false;
+ mutable std::shared_timed_mutex mConfigLock;
mutable std::unordered_map<int32_t, aidlvhal::VehiclePropConfig> mConfigsByPropId
- GUARDED_BY(mConfigInitLock);
- mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigInitLock);
+ GUARDED_BY(mConfigLock);
+ mutable std::unique_ptr<ndk::ScopedFileDescriptor> mConfigFile GUARDED_BY(mConfigLock);
std::mutex mLock;
std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -175,7 +175,10 @@
android::base::Result<std::vector<int64_t>> checkDuplicateRequests(
const std::vector<aidlvhal::SetValueRequest>& requests);
- VhalResult<void> checkSubscribeOptions(const std::vector<aidlvhal::SubscribeOptions>& options);
+ VhalResult<void> checkSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId)
+ REQUIRES_SHARED(mConfigLock);
VhalResult<void> checkPermissionHelper(const aidlvhal::VehiclePropValue& value,
aidlvhal::VehiclePropertyAccess accessToTest) const;
@@ -184,7 +187,7 @@
VhalResult<void> checkWritePermission(const aidlvhal::VehiclePropValue& value) const;
- android::base::Result<const aidlvhal::VehiclePropConfig*> getConfig(int32_t propId) const;
+ android::base::Result<aidlvhal::VehiclePropConfig> getConfig(int32_t propId) const;
void onBinderDiedWithContext(const AIBinder* clientId);
@@ -196,7 +199,7 @@
bool checkDumpPermission();
- bool getAllPropConfigsFromHardwareLocked() const REQUIRES(mConfigInitLock);
+ bool getAllPropConfigsFromHardwareLocked() const EXCLUDES(mConfigLock);
// The looping handler function to process all onBinderDied or onBinderUnlinked events in
// mBinderEvents.
@@ -209,10 +212,12 @@
int32_t getVhalInterfaceVersion() const;
- // Gets mConfigsByPropId, lazy init it if necessary.
- const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& getConfigsByPropId() const;
- // Gets mConfigFile, lazy init it if necessary.
- const ndk::ScopedFileDescriptor* getConfigFile() const;
+ // Gets mConfigsByPropId, lazy init it if necessary. Note that the reference is only valid in
+ // the scope of the callback and it is guaranteed that read lock is obtained during the
+ // callback.
+ void getConfigsByPropId(
+ std::function<void(const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>&)>
+ callback) const EXCLUDES(mConfigLock);
// Puts the property change events into a queue so that they can handled in batch.
static void batchPropertyChangeEvent(
@@ -239,6 +244,12 @@
static void onBinderUnlinked(void* cookie);
+ static void parseSubscribeOptions(
+ const std::vector<aidlvhal::SubscribeOptions>& options,
+ const std::unordered_map<int32_t, aidlvhal::VehiclePropConfig>& configsByPropId,
+ std::vector<aidlvhal::SubscribeOptions>& onChangeSubscriptions,
+ std::vector<aidlvhal::SubscribeOptions>& continuousSubscriptions);
+
// Test-only
// Set the default timeout for pending requests.
void setTimeout(int64_t timeoutInNano);
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 9dc039d..e062a28 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -95,6 +95,18 @@
return sampleRateHz;
}
+class SCOPED_CAPABILITY SharedScopedLockAssertion {
+ public:
+ SharedScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE_SHARED(mutex) {}
+ ~SharedScopedLockAssertion() RELEASE() {}
+};
+
+class SCOPED_CAPABILITY UniqueScopedLockAssertion {
+ public:
+ UniqueScopedLockAssertion(std::shared_timed_mutex& mutex) ACQUIRE(mutex) {}
+ ~UniqueScopedLockAssertion() RELEASE() {}
+};
+
} // namespace
DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
@@ -355,68 +367,82 @@
}
filteredConfigs.push_back(std::move(config));
}
- for (auto& config : filteredConfigs) {
- mConfigsByPropId[config.prop] = config;
- }
- VehiclePropConfigs vehiclePropConfigs;
- vehiclePropConfigs.payloads = std::move(filteredConfigs);
- auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
- if (!result.ok()) {
- ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
- result.error().message().c_str(), static_cast<int>(result.error().code()));
- mConfigFile = nullptr;
- return false;
+
+ {
+ std::unique_lock<std::shared_timed_mutex> configWriteLock(mConfigLock);
+ UniqueScopedLockAssertion lockAssertion(mConfigLock);
+
+ for (auto& config : filteredConfigs) {
+ mConfigsByPropId[config.prop] = config;
+ }
+ VehiclePropConfigs vehiclePropConfigs;
+ vehiclePropConfigs.payloads = std::move(filteredConfigs);
+ auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
+ if (!result.ok()) {
+ ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+ result.error().message().c_str(), static_cast<int>(result.error().code()));
+ mConfigFile = nullptr;
+ return false;
+ }
+
+ if (result.value() != nullptr) {
+ mConfigFile = std::move(result.value());
+ }
}
- if (result.value() != nullptr) {
- mConfigFile = std::move(result.value());
- }
+ mConfigInit = true;
return true;
}
-const ScopedFileDescriptor* DefaultVehicleHal::getConfigFile() const {
- std::scoped_lock lockGuard(mConfigInitLock);
+void DefaultVehicleHal::getConfigsByPropId(
+ std::function<void(const std::unordered_map<int32_t, VehiclePropConfig>&)> callback) const {
if (!mConfigInit) {
CHECK(getAllPropConfigsFromHardwareLocked())
<< "Failed to get property configs from hardware";
- mConfigInit = true;
}
- return mConfigFile.get();
-}
-const std::unordered_map<int32_t, VehiclePropConfig>& DefaultVehicleHal::getConfigsByPropId()
- const {
- std::scoped_lock lockGuard(mConfigInitLock);
- if (!mConfigInit) {
- CHECK(getAllPropConfigsFromHardwareLocked())
- << "Failed to get property configs from hardware";
- mConfigInit = true;
- }
- return mConfigsByPropId;
+ std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ callback(mConfigsByPropId);
}
ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
- const ScopedFileDescriptor* configFile = getConfigFile();
- const auto& configsByPropId = getConfigsByPropId();
- if (configFile != nullptr) {
+ if (!mConfigInit) {
+ CHECK(getAllPropConfigsFromHardwareLocked())
+ << "Failed to get property configs from hardware";
+ }
+
+ std::shared_lock<std::shared_timed_mutex> configReadLock(mConfigLock);
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ if (mConfigFile != nullptr) {
output->payloads.clear();
- output->sharedMemoryFd.set(dup(configFile->get()));
+ output->sharedMemoryFd.set(dup(mConfigFile->get()));
return ScopedAStatus::ok();
}
- output->payloads.reserve(configsByPropId.size());
- for (const auto& [_, config] : configsByPropId) {
+
+ output->payloads.reserve(mConfigsByPropId.size());
+ for (const auto& [_, config] : mConfigsByPropId) {
output->payloads.push_back(config);
}
return ScopedAStatus::ok();
}
-Result<const VehiclePropConfig*> DefaultVehicleHal::getConfig(int32_t propId) const {
- const auto& configsByPropId = getConfigsByPropId();
- auto it = configsByPropId.find(propId);
- if (it == configsByPropId.end()) {
- return Error() << "no config for property, ID: " << propId;
- }
- return &(it->second);
+Result<VehiclePropConfig> DefaultVehicleHal::getConfig(int32_t propId) const {
+ Result<VehiclePropConfig> result;
+ getConfigsByPropId([this, &result, propId](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ auto it = configsByPropId.find(propId);
+ if (it == configsByPropId.end()) {
+ result = Error() << "no config for property, ID: " << propId;
+ return;
+ }
+ // Copy the VehiclePropConfig
+ result = it->second;
+ });
+ return result;
}
Result<void> DefaultVehicleHal::checkProperty(const VehiclePropValue& propValue) {
@@ -425,15 +451,15 @@
if (!result.ok()) {
return result.error();
}
- const VehiclePropConfig* config = result.value();
- const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, *config);
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(propValue, config);
if (!isGlobalProp(propId) && areaConfig == nullptr) {
// Ignore areaId for global property. For non global property, check whether areaId is
// allowed. areaId must appear in areaConfig.
return Error() << "invalid area ID: " << propValue.areaId << " for prop ID: " << propId
<< ", not listed in config";
}
- if (auto result = checkPropValue(propValue, config); !result.ok()) {
+ if (auto result = checkPropValue(propValue, &config); !result.ok()) {
return Error() << "invalid property value: " << propValue.toString()
<< ", error: " << getErrorMsg(result);
}
@@ -659,17 +685,27 @@
ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
VehiclePropConfigs* output) {
std::vector<VehiclePropConfig> configs;
- const auto& configsByPropId = getConfigsByPropId();
- for (int32_t prop : props) {
- auto it = configsByPropId.find(prop);
- if (it != configsByPropId.end()) {
- configs.push_back(it->second);
- } else {
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- toInt(StatusCode::INVALID_ARG),
- StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+ ScopedAStatus status = ScopedAStatus::ok();
+ getConfigsByPropId([this, &configs, &status, &props](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ for (int32_t prop : props) {
+ auto it = configsByPropId.find(prop);
+ if (it != configsByPropId.end()) {
+ configs.push_back(it->second);
+ } else {
+ status = ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ toInt(StatusCode::INVALID_ARG),
+ StringPrintf("no config for property, ID: %" PRId32, prop).c_str());
+ return;
+ }
}
+ });
+
+ if (!status.isOk()) {
+ return status;
}
+
return vectorToStableLargeParcelable(std::move(configs), output);
}
@@ -691,8 +727,8 @@
}
VhalResult<void> DefaultVehicleHal::checkSubscribeOptions(
- const std::vector<SubscribeOptions>& options) {
- const auto& configsByPropId = getConfigsByPropId();
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId) {
for (const auto& option : options) {
int32_t propId = option.propId;
auto it = configsByPropId.find(propId);
@@ -757,23 +793,15 @@
}
}
}
+
return {};
}
-ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
- const std::vector<SubscribeOptions>& options,
- [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
- // TODO(b/205189110): Use shared memory file count.
- if (callback == nullptr) {
- return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
- }
- if (auto result = checkSubscribeOptions(options); !result.ok()) {
- ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
- return toScopedAStatus(result);
- }
- std::vector<SubscribeOptions> onChangeSubscriptions;
- std::vector<SubscribeOptions> continuousSubscriptions;
- const auto& configsByPropId = getConfigsByPropId();
+void DefaultVehicleHal::parseSubscribeOptions(
+ const std::vector<SubscribeOptions>& options,
+ const std::unordered_map<int32_t, VehiclePropConfig>& configsByPropId,
+ std::vector<SubscribeOptions>& onChangeSubscriptions,
+ std::vector<SubscribeOptions>& continuousSubscriptions) {
for (const auto& option : options) {
int32_t propId = option.propId;
// We have already validate config exists.
@@ -831,6 +859,34 @@
onChangeSubscriptions.push_back(std::move(optionCopy));
}
}
+}
+
+ScopedAStatus DefaultVehicleHal::subscribe(const CallbackType& callback,
+ const std::vector<SubscribeOptions>& options,
+ [[maybe_unused]] int32_t maxSharedMemoryFileCount) {
+ // TODO(b/205189110): Use shared memory file count.
+ if (callback == nullptr) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+ std::vector<SubscribeOptions> onChangeSubscriptions;
+ std::vector<SubscribeOptions> continuousSubscriptions;
+ ScopedAStatus returnStatus = ScopedAStatus::ok();
+ getConfigsByPropId([this, &returnStatus, &options, &onChangeSubscriptions,
+ &continuousSubscriptions](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ if (auto result = checkSubscribeOptions(options, configsByPropId); !result.ok()) {
+ ALOGE("subscribe: invalid subscribe options: %s", getErrorMsg(result).c_str());
+ returnStatus = toScopedAStatus(result);
+ return;
+ }
+ parseSubscribeOptions(options, configsByPropId, onChangeSubscriptions,
+ continuousSubscriptions);
+ });
+
+ if (!returnStatus.isOk()) {
+ return returnStatus;
+ }
{
// Lock to make sure onBinderDied would not be called concurrently.
@@ -891,13 +947,13 @@
return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
}
- const VehiclePropConfig* config = result.value();
- const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
+ const VehiclePropConfig& config = result.value();
+ const VehicleAreaConfig* areaConfig = getAreaConfig(value, config);
if (areaConfig == nullptr && !isGlobalProp(propId)) {
return StatusError(StatusCode::INVALID_ARG) << "no config for area ID: " << value.areaId;
}
- if (!hasRequiredAccess(config->access, accessToTest) &&
+ if (!hasRequiredAccess(config.access, accessToTest) &&
(areaConfig == nullptr || !hasRequiredAccess(areaConfig->access, accessToTest))) {
return StatusError(StatusCode::ACCESS_DENIED)
<< StringPrintf("Property %" PRId32 " does not have the following access: %" PRId32,
@@ -966,7 +1022,6 @@
}
DumpResult result = mVehicleHardware->dump(options);
if (result.refreshPropertyConfigs) {
- std::scoped_lock lockGuard(mConfigInitLock);
getAllPropConfigsFromHardwareLocked();
}
dprintf(fd, "%s", (result.buffer + "\n").c_str());
@@ -974,11 +1029,16 @@
return STATUS_OK;
}
dprintf(fd, "Vehicle HAL State: \n");
- const auto& configsByPropId = getConfigsByPropId();
+ std::unordered_map<int32_t, VehiclePropConfig> configsByPropIdCopy;
+ getConfigsByPropId([this, &configsByPropIdCopy](const auto& configsByPropId) {
+ SharedScopedLockAssertion lockAssertion(mConfigLock);
+
+ configsByPropIdCopy = configsByPropId;
+ });
{
std::scoped_lock<std::mutex> lockGuard(mLock);
dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
- dprintf(fd, "Containing %zu property configs\n", configsByPropId.size());
+ dprintf(fd, "Containing %zu property configs\n", configsByPropIdCopy.size());
dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
dprintf(fd, "Currently have %zu subscribe clients\n", countSubscribeClients());
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
index a458c5b..c62784e 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -145,6 +145,13 @@
<< toString(session_type_);
return;
}
+ } else if (session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH) {
+ if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+ << toString(session_type_);
+ return;
+ }
} else {
LOG(ERROR) << __func__ << " invalid SessionType ="
<< toString(session_type_);
@@ -166,6 +173,13 @@
<< toString(session_type_);
return;
}
+ } else if (session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH) {
+ if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+ LOG(ERROR) << __func__ << " invalid audio config type for SessionType ="
+ << toString(session_type_);
+ return;
+ }
} else {
LOG(ERROR) << __func__
<< " invalid SessionType =" << toString(session_type_);
@@ -604,7 +618,9 @@
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH) {
return false;
}
@@ -629,7 +645,9 @@
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
- session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+ session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
+ session_type_ == SessionType::HFP_SOFTWARE_DECODING_DATAPATH) {
return false;
}
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 5e2cbe3..31e6536 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -462,6 +462,10 @@
GnssData lastGnssData;
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, timeoutSeconds));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ if (i <= 2 && lastGnssData.measurements.size() == 0) {
+ // Allow 3 seconds tolerance for empty measurement
+ continue;
+ }
ASSERT_TRUE(lastGnssData.measurements.size() > 0);
// Validity check GnssData fields
@@ -507,6 +511,10 @@
GnssData lastGnssData;
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, timeoutSeconds));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ if (i <= 2 && lastGnssData.measurements.size() == 0) {
+ // Allow 3 seconds tolerance to report empty measurement
+ continue;
+ }
ASSERT_TRUE(lastGnssData.measurements.size() > 0);
// Validity check GnssData fields
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index f7408d8..8abf7ab 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -419,6 +419,10 @@
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
kFirstGnssMeasurementTimeoutSeconds));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ if (i <= 2 && lastMeasurement.measurements.size() == 0) {
+ // Allow 3 seconds tolerance for empty measurement
+ continue;
+ }
ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
// Validity check GnssData fields
@@ -479,6 +483,10 @@
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
kFirstGnssMeasurementTimeoutSeconds));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ if (i <= 2 && lastMeasurement.measurements.size() == 0) {
+ // Allow 3 seconds tolerance for empty measurement
+ continue;
+ }
ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
// Validity check GnssData fields
@@ -1335,7 +1343,10 @@
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastMeasurement,
kFirstGnssMeasurementTimeoutSeconds));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
- ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+ if (i > 2) {
+ // Allow 3 seconds tolerance for empty measurement
+ ASSERT_TRUE(lastMeasurement.measurements.size() > 0);
+ }
// Validity check GnssData fields
checkGnssMeasurementClockFields(lastMeasurement);
@@ -1790,6 +1801,10 @@
GnssData lastGnssData;
ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, 10));
EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ if (i <= 2 && lastGnssData.measurements.size() == 0) {
+ // Allow 3 seconds tolerance to report empty measurement
+ continue;
+ }
ASSERT_TRUE(lastGnssData.measurements.size() > 0);
// Validity check GnssData fields
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp
new file mode 100644
index 0000000..5753bb0
--- /dev/null
+++ b/graphics/composer/2.2/default/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "hardware_interfaces_license",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.graphics.composer@2.2-service",
+ vendor: true,
+ relative_install_path: "hw",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-DLOG_TAG=\"ComposerHal\"",
+ ],
+ srcs: ["service.cpp"],
+ init_rc: ["android.hardware.graphics.composer@2.2-service.rc"],
+ header_libs: ["android.hardware.graphics.composer@2.2-passthrough"],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.1-resources",
+ "android.hardware.graphics.composer@2.2-resources",
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libfmq",
+ "libhardware",
+ "libhidlbase",
+ "libhwc2on1adapter",
+ "libhwc2onfbadapter",
+ "liblog",
+ "libsync",
+ "libutils",
+ ],
+}
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
deleted file mode 100644
index 6f7ef85..0000000
--- a/graphics/composer/2.2/default/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.graphics.composer@2.2-service
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_CFLAGS := -Wall -Werror -DLOG_TAG=\"ComposerHal\"
-LOCAL_SRC_FILES := service.cpp
-LOCAL_INIT_RC := android.hardware.graphics.composer@2.2-service.rc
-LOCAL_HEADER_LIBRARIES := android.hardware.graphics.composer@2.2-passthrough
-LOCAL_SHARED_LIBRARIES := \
- android.hardware.graphics.composer@2.1 \
- android.hardware.graphics.composer@2.2 \
- android.hardware.graphics.composer@2.1-resources \
- android.hardware.graphics.composer@2.2-resources \
- libbase \
- libbinder \
- libcutils \
- libfmq \
- libhardware \
- libhidlbase \
- libhwc2on1adapter \
- libhwc2onfbadapter \
- liblog \
- libsync \
- libutils
-
-ifdef TARGET_USES_DISPLAY_RENDER_INTENTS
-LOCAL_CFLAGS += -DUSES_DISPLAY_RENDER_INTENTS
-endif
-
-include $(BUILD_EXECUTABLE)
diff --git a/graphics/composer/aidl/vts/RenderEngineVts.cpp b/graphics/composer/aidl/vts/RenderEngineVts.cpp
index 4e7f773..bc5eb6f 100644
--- a/graphics/composer/aidl/vts/RenderEngineVts.cpp
+++ b/graphics/composer/aidl/vts/RenderEngineVts.cpp
@@ -28,9 +28,7 @@
mRenderEngine = ::android::renderengine::RenderEngine::create(args);
}
-TestRenderEngine::~TestRenderEngine() {
- mRenderEngine.release();
-}
+TestRenderEngine::~TestRenderEngine() {}
void TestRenderEngine::setRenderLayers(std::vector<std::shared_ptr<TestLayer>> layers) {
sort(layers.begin(), layers.end(),
diff --git a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
index d80e651..2d34afe 100644
--- a/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
+++ b/media/omx/1.0/vts/functional/store/VtsHalMediaOmxV1_0TargetStoreTest.cpp
@@ -93,9 +93,9 @@
void validateAttributes(
const std::map<const std::string, const testing::internal::RE>& knownPatterns,
- const std::vector<const struct AttributePattern>& unknownPatterns,
+ const std::vector<struct AttributePattern>& unknownPatterns,
hidl_vec<IOmxStore::Attribute> attributes) {
- std::set<const std::string> attributeKeys;
+ std::set<std::string> attributeKeys;
for (const auto& attr : attributes) {
// Make sure there are no duplicates
const auto [nodeIter, inserted] = attributeKeys.insert(attr.key);
@@ -179,7 +179,7 @@
* tried for a match with the second element of the pair. If this second
* match fails, the test will fail.
*/
- const std::vector<const struct AttributePattern> unknownPatterns = {
+ const std::vector<struct AttributePattern> unknownPatterns = {
{"supports-[a-z0-9-]*", "0|1"}};
validateAttributes(knownPatterns, unknownPatterns, attributes);
@@ -248,7 +248,7 @@
};
// Strings for matching rules for node attributes with key patterns
- const std::vector<const struct AttributePattern> unknownPatterns = {
+ const std::vector<struct AttributePattern> unknownPatterns = {
{"measured-frame-rate-" + size + "-range", range_num},
{"feature-[a-zA-Z0-9_-]+", string},
};
@@ -257,9 +257,9 @@
const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9._-]+";
const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
- std::set<const std::string> roleKeys;
- std::map<const std::string, std::set<const std::string>> nodeToRoles;
- std::map<const std::string, std::set<const std::string>> ownerToNodes;
+ std::set<std::string> roleKeys;
+ std::map<const std::string, std::set<std::string>> nodeToRoles;
+ std::map<const std::string, std::set<std::string>> ownerToNodes;
for (const IOmxStore::RoleInfo& role : roleList) {
// Make sure there are no duplicates
const auto [roleIter, inserted] = roleKeys.insert(role.role);
@@ -276,7 +276,7 @@
}
// Check the nodes for this role
- std::set<const std::string> nodeKeys;
+ std::set<std::string> nodeKeys;
for (const IOmxStore::NodeInfo& node : role.nodes) {
// Make sure there are no duplicates
const auto [nodeIter, inserted] = nodeKeys.insert(node.name);
@@ -317,7 +317,7 @@
// Verify that roles for each node match with the information from
// IOmxStore::listRoles().
- std::set<const std::string> nodeKeys;
+ std::set<std::string> nodeKeys;
for (IOmx::ComponentInfo node : nodeList) {
// Make sure there are no duplicates
const auto [nodeIter, inserted] = nodeKeys.insert(node.mName);
@@ -334,7 +334,7 @@
// All the roles advertised by IOmxStore::listRoles() for this
// node must be included in roleKeys.
- std::set<const std::string> difference;
+ std::set<std::string> difference;
std::set_difference(nodeToRoles[node.mName].begin(), nodeToRoles[node.mName].end(),
roleKeys.begin(), roleKeys.end(),
std::inserter(difference, difference.begin()));
@@ -347,7 +347,7 @@
}
// Check that all nodes obtained from IOmxStore::listRoles() are
// supported by the their corresponding IOmx instances.
- std::set<const std::string> difference;
+ std::set<std::string> difference;
std::set_difference(nodes.begin(), nodes.end(), nodeKeys.begin(), nodeKeys.end(),
std::inserter(difference, difference.begin()));
EXPECT_EQ(difference.empty(), true) << "IOmx::listNodes() for IOmx "
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 5c9efef..608d328 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -40,6 +40,9 @@
export_include_dirs: [
"include",
],
+ header_libs: [
+ "libhardware_headers",
+ ],
defaults: [
"keymint_use_latest_hal_aidl_ndk_shared",
],
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
index 2cbf041..2e61f9b 100644
--- a/soundtrigger/2.0/default/Android.bp
+++ b/soundtrigger/2.0/default/Android.bp
@@ -46,3 +46,36 @@
"libhardware_headers",
],
}
+
+soong_config_module_type {
+ name: "soundtrigger_cc_library_shared",
+ module_type: "cc_library_shared",
+ config_namespace: "soundtrigger",
+ value_variables: [
+ "audioserver_multilib",
+ ],
+ properties: ["compile_multilib"],
+}
+
+soundtrigger_cc_library_shared {
+ name: "android.hardware.soundtrigger@2.0-impl",
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["FetchISoundTriggerHw.cpp"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ shared_libs: [
+ "libhardware",
+ "libutils",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.0-core",
+ ],
+ compile_multilib: "32",
+ soong_config_variables: {
+ audioserver_multilib: {
+ compile_multilib: "%s",
+ },
+ },
+}
diff --git a/soundtrigger/2.0/default/Android.mk b/soundtrigger/2.0/default/Android.mk
deleted file mode 100644
index 17e4440..0000000
--- a/soundtrigger/2.0/default/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.soundtrigger@2.0-impl
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
- FetchISoundTriggerHw.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libhardware \
- libutils \
- android.hardware.soundtrigger@2.0 \
- android.hardware.soundtrigger@2.0-core
-
-LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
-LOCAL_MULTILIB := 32
-else
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/2.1/default/Android.bp b/soundtrigger/2.1/default/Android.bp
new file mode 100644
index 0000000..a246680
--- /dev/null
+++ b/soundtrigger/2.1/default/Android.bp
@@ -0,0 +1,57 @@
+//
+// Copyright (C) 2018 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "hardware_interfaces_license",
+ ],
+}
+
+soong_config_module_type_import {
+ from: "hardware/interfaces/soundtrigger/2.0/default/Android.bp",
+ module_types: ["soundtrigger_cc_library_shared"],
+}
+
+soundtrigger_cc_library_shared {
+ name: "android.hardware.soundtrigger@2.1-impl",
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: ["SoundTriggerHw.cpp"],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "libhardware",
+ "libhidlbase",
+ "libhidlmemory",
+ "liblog",
+ "libutils",
+ "android.hardware.soundtrigger@2.1",
+ "android.hardware.soundtrigger@2.0",
+ "android.hardware.soundtrigger@2.0-core",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ ],
+ compile_multilib: "32",
+ soong_config_variables: {
+ audioserver_multilib: {
+ compile_multilib: "%s",
+ },
+ },
+}
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
deleted file mode 100644
index 602f5a7..0000000
--- a/soundtrigger/2.1/default/Android.mk
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.soundtrigger@2.1-impl
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../../NOTICE
-LOCAL_VENDOR_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
- SoundTriggerHw.cpp
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
- libhardware \
- libhidlbase \
- libhidlmemory \
- liblog \
- libutils \
- android.hardware.soundtrigger@2.1 \
- android.hardware.soundtrigger@2.0 \
- android.hardware.soundtrigger@2.0-core \
- android.hidl.allocator@1.0 \
- android.hidl.memory@1.0
-
-LOCAL_C_INCLUDE_DIRS := $(LOCAL_PATH)
-
-ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
-LOCAL_MULTILIB := 32
-else
-LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/threadnetwork/aidl/default/socket_interface.cpp b/threadnetwork/aidl/default/socket_interface.cpp
index a5aa2b4..71c6b4f 100644
--- a/threadnetwork/aidl/default/socket_interface.cpp
+++ b/threadnetwork/aidl/default/socket_interface.cpp
@@ -36,6 +36,7 @@
#include <vector>
#include "common/code_utils.hpp"
+#include "openthread/error.h"
#include "openthread/openthread-system.h"
#include "platform-posix.h"
@@ -56,14 +57,9 @@
otError SocketInterface::Init(ReceiveFrameCallback aCallback, void* aCallbackContext,
RxFrameBuffer& aFrameBuffer) {
- otError error = OT_ERROR_NONE;
+ otError error = InitSocket();
- VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
-
- WaitForSocketFileCreated(mRadioUrl.GetPath());
-
- mSockFd = OpenFile(mRadioUrl);
- VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED);
+ VerifyOrExit(error == OT_ERROR_NONE);
mReceiveFrameCallback = aCallback;
mReceiveFrameContext = aCallbackContext;
@@ -155,9 +151,22 @@
VerifyOrExit(!mIsHardwareResetting, error = OT_ERROR_FAILED);
- WaitForSocketFileCreated(mRadioUrl.GetPath());
- mSockFd = OpenFile(mRadioUrl);
- VerifyOrExit(mSockFd != -1, error = OT_ERROR_FAILED);
+exit:
+ return error;
+}
+
+otError SocketInterface::InitSocket() {
+ otError error = OT_ERROR_NONE;
+ int retries = 0;
+
+ VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
+
+ while (retries++ < kMaxRetriesForSocketInit) {
+ WaitForSocketFileCreated(mRadioUrl.GetPath());
+ mSockFd = OpenFile(mRadioUrl);
+ VerifyOrExit(mSockFd == -1);
+ }
+ error = OT_ERROR_FAILED;
exit:
return error;
@@ -168,11 +177,16 @@
assert(context != nullptr);
+ VerifyOrExit(mSockFd != -1);
+
FD_SET(mSockFd, &context->mReadFdSet);
if (context->mMaxFd < mSockFd) {
context->mMaxFd = mSockFd;
}
+
+exit:
+ return;
}
void SocketInterface::Process(const void* aMainloopContext) {
@@ -181,9 +195,14 @@
assert(context != nullptr);
+ VerifyOrExit(mSockFd != -1);
+
if (FD_ISSET(mSockFd, &context->mReadFdSet)) {
Read();
}
+
+exit:
+ return;
}
otError SocketInterface::HardwareReset(void) {
@@ -198,22 +217,24 @@
void SocketInterface::Read(void) {
uint8_t buffer[kMaxFrameSize];
+ ssize_t rval;
- ssize_t rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer)));
+ VerifyOrExit(mSockFd != -1);
+
+ rval = TEMP_FAILURE_RETRY(read(mSockFd, buffer, sizeof(buffer)));
if (rval > 0) {
ProcessReceivedData(buffer, static_cast<uint16_t>(rval));
} else if (rval < 0) {
DieNow(OT_EXIT_ERROR_ERRNO);
} else {
- if (mIsHardwareResetting) {
- LogInfo("Socket connection is closed due to hardware reset.");
- ResetStates();
- } else {
- LogCrit("Socket connection is closed by remote.");
- exit(OT_EXIT_FAILURE);
- }
+ LogWarn("Socket connection is closed by remote, isHardwareReset: %d", mIsHardwareResetting);
+ ResetStates();
+ InitSocket();
}
+
+exit:
+ return;
}
void SocketInterface::Write(const uint8_t* aFrame, uint16_t aLength) {
diff --git a/threadnetwork/aidl/default/socket_interface.hpp b/threadnetwork/aidl/default/socket_interface.hpp
index 494d76a..83c86e8 100644
--- a/threadnetwork/aidl/default/socket_interface.hpp
+++ b/threadnetwork/aidl/default/socket_interface.hpp
@@ -247,6 +247,15 @@
otError WaitForHardwareResetCompletion(uint32_t aTimeoutMs);
/**
+ * Initialize socket
+ *
+ * @retval TRUE Socket initialization is successful.
+ * @retval FALSE Socket initialization is failed.
+ *
+ */
+ otError InitSocket();
+
+ /**
* Reset socket interface to intitial state.
*
*/
@@ -257,6 +266,7 @@
///< descriptor to become available.
kMaxRetriesForSocketCloseCheck = 3, ///< Maximum retry times for checking
///< if socket is closed.
+ kMaxRetriesForSocketInit = 3, ///< Maximum retry times for socket initialization.
};
ReceiveFrameCallback mReceiveFrameCallback;
diff --git a/weaver/vts/VtsHalWeaverTargetTest.cpp b/weaver/vts/VtsHalWeaverTargetTest.cpp
index 8952dfc..faa8416 100644
--- a/weaver/vts/VtsHalWeaverTargetTest.cpp
+++ b/weaver/vts/VtsHalWeaverTargetTest.cpp
@@ -220,13 +220,10 @@
used_slots.insert(slot);
}
}
- // Starting in Android 14, the system will always use at least one Weaver slot if Weaver is
- // supported at all. This is true even if an LSKF hasn't been set yet, since Weaver is used to
- // protect the initial binding of each user's synthetic password to ensure that binding can be
- // securely deleted if an LSKF is set later. Make sure we saw at least one slot, as otherwise
- // the Weaver implementation must have a bug that makes it not fully usable by Android.
- ASSERT_FALSE(used_slots.empty())
- << "Could not determine which Weaver slots are in use by the system";
+
+ // We should assert !used_slots.empty() here, but that can't be done yet due to
+ // config_disableWeaverOnUnsecuredUsers being supported. The value of that option is not
+ // accessible from here, so we have to assume it might be set to true.
// Find the first free slot.
int found = 0;