aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/src/common/QuirksManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/oboe/src/common/QuirksManager.cpp')
-rw-r--r--externals/oboe/src/common/QuirksManager.cpp319
1 files changed, 0 insertions, 319 deletions
diff --git a/externals/oboe/src/common/QuirksManager.cpp b/externals/oboe/src/common/QuirksManager.cpp
deleted file mode 100644
index 319c7f2551..0000000000
--- a/externals/oboe/src/common/QuirksManager.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright 2019 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 <oboe/AudioStreamBuilder.h>
-#include <oboe/Oboe.h>
-#include <oboe/Utilities.h>
-
-#include "OboeDebug.h"
-#include "QuirksManager.h"
-
-using namespace oboe;
-
-int32_t QuirksManager::DeviceQuirks::clipBufferSize(AudioStream &stream,
- int32_t requestedSize) {
- if (!OboeGlobals::areWorkaroundsEnabled()) {
- return requestedSize;
- }
- int bottomMargin = kDefaultBottomMarginInBursts;
- int topMargin = kDefaultTopMarginInBursts;
- if (isMMapUsed(stream)) {
- if (stream.getSharingMode() == SharingMode::Exclusive) {
- bottomMargin = getExclusiveBottomMarginInBursts();
- topMargin = getExclusiveTopMarginInBursts();
- }
- } else {
- bottomMargin = kLegacyBottomMarginInBursts;
- }
-
- int32_t burst = stream.getFramesPerBurst();
- int32_t minSize = bottomMargin * burst;
- int32_t adjustedSize = requestedSize;
- if (adjustedSize < minSize ) {
- adjustedSize = minSize;
- } else {
- int32_t maxSize = stream.getBufferCapacityInFrames() - (topMargin * burst);
- if (adjustedSize > maxSize ) {
- adjustedSize = maxSize;
- }
- }
- return adjustedSize;
-}
-
-bool QuirksManager::DeviceQuirks::isAAudioMMapPossible(const AudioStreamBuilder &builder) const {
- bool isSampleRateCompatible =
- builder.getSampleRate() == oboe::Unspecified
- || builder.getSampleRate() == kCommonNativeRate
- || builder.getSampleRateConversionQuality() != SampleRateConversionQuality::None;
- return builder.getPerformanceMode() == PerformanceMode::LowLatency
- && isSampleRateCompatible
- && builder.getChannelCount() <= kChannelCountStereo;
-}
-
-bool QuirksManager::DeviceQuirks::shouldConvertFloatToI16ForOutputStreams() {
- std::string productManufacturer = getPropertyString("ro.product.manufacturer");
- if (getSdkVersion() < __ANDROID_API_L__) {
- return true;
- } else if ((productManufacturer == "vivo") && (getSdkVersion() < __ANDROID_API_M__)) {
- return true;
- }
- return false;
-}
-
-/**
- * This is for Samsung Exynos quirks. Samsung Mobile uses Qualcomm chips so
- * the QualcommDeviceQuirks would apply.
- */
-class SamsungExynosDeviceQuirks : public QuirksManager::DeviceQuirks {
-public:
- SamsungExynosDeviceQuirks() {
- std::string chipname = getPropertyString("ro.hardware.chipname");
- isExynos9810 = (chipname == "exynos9810");
- isExynos990 = (chipname == "exynos990");
- isExynos850 = (chipname == "exynos850");
-
- mBuildChangelist = getPropertyInteger("ro.build.changelist", 0);
- }
-
- virtual ~SamsungExynosDeviceQuirks() = default;
-
- int32_t getExclusiveBottomMarginInBursts() const override {
- return kBottomMargin;
- }
-
- int32_t getExclusiveTopMarginInBursts() const override {
- return kTopMargin;
- }
-
- // See Oboe issues #824 and #1247 for more information.
- bool isMonoMMapActuallyStereo() const override {
- return isExynos9810 || isExynos850; // TODO We can make this version specific if it gets fixed.
- }
-
- bool isAAudioMMapPossible(const AudioStreamBuilder &builder) const override {
- return DeviceQuirks::isAAudioMMapPossible(builder)
- // Samsung says they use Legacy for Camcorder
- && builder.getInputPreset() != oboe::InputPreset::Camcorder;
- }
-
- bool isMMapSafe(const AudioStreamBuilder &builder) override {
- const bool isInput = builder.getDirection() == Direction::Input;
- // This detects b/159066712 , S20 LSI has corrupt low latency audio recording
- // and turns off MMAP.
- // See also https://github.com/google/oboe/issues/892
- bool isRecordingCorrupted = isInput
- && isExynos990
- && mBuildChangelist < 19350896;
-
- // Certain S9+ builds record silence when using MMAP and not using the VoiceCommunication
- // preset.
- // See https://github.com/google/oboe/issues/1110
- bool wouldRecordSilence = isInput
- && isExynos9810
- && mBuildChangelist <= 18847185
- && (builder.getInputPreset() != InputPreset::VoiceCommunication);
-
- if (wouldRecordSilence){
- LOGI("QuirksManager::%s() Requested stream configuration would result in silence on "
- "this device. Switching off MMAP.", __func__);
- }
-
- return !isRecordingCorrupted && !wouldRecordSilence;
- }
-
-private:
- // Stay farther away from DSP position on Exynos devices.
- static constexpr int32_t kBottomMargin = 2;
- static constexpr int32_t kTopMargin = 1;
- bool isExynos9810 = false;
- bool isExynos990 = false;
- bool isExynos850 = false;
- int mBuildChangelist = 0;
-};
-
-class QualcommDeviceQuirks : public QuirksManager::DeviceQuirks {
-public:
- QualcommDeviceQuirks() {
- std::string modelName = getPropertyString("ro.soc.model");
- isSM8150 = (modelName == "SDM8150");
- }
-
- virtual ~QualcommDeviceQuirks() = default;
-
- int32_t getExclusiveBottomMarginInBursts() const override {
- return kBottomMargin;
- }
-
- bool isMMapSafe(const AudioStreamBuilder &builder) override {
- // See https://github.com/google/oboe/issues/1121#issuecomment-897957749
- bool isMMapBroken = false;
- if (isSM8150 && (getSdkVersion() <= __ANDROID_API_P__)) {
- LOGI("QuirksManager::%s() MMAP not actually supported on this chip."
- " Switching off MMAP.", __func__);
- isMMapBroken = true;
- }
-
- return !isMMapBroken;
- }
-
-private:
- bool isSM8150 = false;
- static constexpr int32_t kBottomMargin = 1;
-};
-
-QuirksManager::QuirksManager() {
- std::string productManufacturer = getPropertyString("ro.product.manufacturer");
- if (productManufacturer == "samsung") {
- std::string arch = getPropertyString("ro.arch");
- bool isExynos = (arch.rfind("exynos", 0) == 0); // starts with?
- if (isExynos) {
- mDeviceQuirks = std::make_unique<SamsungExynosDeviceQuirks>();
- }
- }
- if (!mDeviceQuirks) {
- std::string socManufacturer = getPropertyString("ro.soc.manufacturer");
- if (socManufacturer == "Qualcomm") {
- // This may include Samsung Mobile devices.
- mDeviceQuirks = std::make_unique<QualcommDeviceQuirks>();
- } else {
- mDeviceQuirks = std::make_unique<DeviceQuirks>();
- }
- }
-}
-
-bool QuirksManager::isConversionNeeded(
- const AudioStreamBuilder &builder,
- AudioStreamBuilder &childBuilder) {
- bool conversionNeeded = false;
- const bool isLowLatency = builder.getPerformanceMode() == PerformanceMode::LowLatency;
- const bool isInput = builder.getDirection() == Direction::Input;
- const bool isFloat = builder.getFormat() == AudioFormat::Float;
- const bool isIEC61937 = builder.getFormat() == AudioFormat::IEC61937;
- const bool isCompressed = isCompressedFormat(builder.getFormat());
-
- // There should be no conversion for IEC61937. Sample rates and channel counts must be set explicitly.
- if (isIEC61937) {
- LOGI("QuirksManager::%s() conversion not needed for IEC61937", __func__);
- return false;
- }
-
- if (isCompressed) {
- LOGI("QuirksManager::%s() conversion not needed for compressed format %d",
- __func__, builder.getFormat());
- return false;
- }
-
- // There are multiple bugs involving using callback with a specified callback size.
- // Issue #778: O to Q had a problem with Legacy INPUT streams for FLOAT streams
- // and a specified callback size. It would assert because of a bad buffer size.
- //
- // Issue #973: O to R had a problem with Legacy output streams using callback and a specified callback size.
- // An AudioTrack stream could still be running when the AAudio FixedBlockReader was closed.
- // Internally b/161914201#comment25
- //
- // Issue #983: O to R would glitch if the framesPerCallback was too small.
- //
- // Most of these problems were related to Legacy stream. MMAP was OK. But we don't
- // know if we will get an MMAP stream. So, to be safe, just do the conversion in Oboe.
- if (OboeGlobals::areWorkaroundsEnabled()
- && builder.willUseAAudio()
- && builder.isDataCallbackSpecified()
- && builder.getFramesPerDataCallback() != 0
- && getSdkVersion() <= __ANDROID_API_R__) {
- LOGI("QuirksManager::%s() avoid setFramesPerCallback(n>0)", __func__);
- childBuilder.setFramesPerCallback(oboe::Unspecified);
- conversionNeeded = true;
- }
-
- // If a SAMPLE RATE is specified for low latency, let the native code choose an optimal rate.
- // This isn't really a workaround. It is an Oboe feature that is convenient to place here.
- // TODO There may be a problem if the devices supports low latency
- // at a higher rate than the default.
- if (builder.getSampleRate() != oboe::Unspecified
- && builder.getSampleRateConversionQuality() != SampleRateConversionQuality::None
- && isLowLatency
- ) {
- childBuilder.setSampleRate(oboe::Unspecified); // native API decides the best sample rate
- conversionNeeded = true;
- }
-
- // Data Format
- // OpenSL ES and AAudio before P do not support FAST path for FLOAT capture.
- if (OboeGlobals::areWorkaroundsEnabled()
- && isFloat
- && isInput
- && builder.isFormatConversionAllowed()
- && isLowLatency
- && (!builder.willUseAAudio() || (getSdkVersion() < __ANDROID_API_P__))
- ) {
- childBuilder.setFormat(AudioFormat::I16); // needed for FAST track
- conversionNeeded = true;
- LOGI("QuirksManager::%s() forcing internal format to I16 for low latency", __func__);
- }
-
- // Add quirk for float output when needed.
- if (OboeGlobals::areWorkaroundsEnabled()
- && isFloat
- && !isInput
- && builder.isFormatConversionAllowed()
- && mDeviceQuirks->shouldConvertFloatToI16ForOutputStreams()
- ) {
- childBuilder.setFormat(AudioFormat::I16);
- conversionNeeded = true;
- LOGI("QuirksManager::%s() float was requested but not supported on pre-L devices "
- "and some devices like Vivo devices may have issues on L devices, "
- "creating an underlying I16 stream and using format conversion to provide a float "
- "stream", __func__);
- }
-
- // Channel Count conversions
- if (OboeGlobals::areWorkaroundsEnabled()
- && builder.isChannelConversionAllowed()
- && builder.getChannelCount() == kChannelCountStereo
- && isInput
- && isLowLatency
- && (!builder.willUseAAudio() && (getSdkVersion() == __ANDROID_API_O__))
- ) {
- // Workaround for heap size regression in O.
- // b/66967812 AudioRecord does not allow FAST track for stereo capture in O
- childBuilder.setChannelCount(kChannelCountMono);
- conversionNeeded = true;
- LOGI("QuirksManager::%s() using mono internally for low latency on O", __func__);
- } else if (OboeGlobals::areWorkaroundsEnabled()
- && builder.getChannelCount() == kChannelCountMono
- && isInput
- && mDeviceQuirks->isMonoMMapActuallyStereo()
- && builder.willUseAAudio()
- // Note: we might use this workaround on a device that supports
- // MMAP but will use Legacy for this stream. But this will only happen
- // on devices that have the broken mono.
- && mDeviceQuirks->isAAudioMMapPossible(builder)
- ) {
- // Workaround for mono actually running in stereo mode.
- childBuilder.setChannelCount(kChannelCountStereo); // Use stereo and extract first channel.
- conversionNeeded = true;
- LOGI("QuirksManager::%s() using stereo internally to avoid broken mono", __func__);
- }
- // Note that MMAP does not support mono in 8.1. But that would only matter on Pixel 1
- // phones and they have almost all been updated to 9.0.
-
- return conversionNeeded;
-}
-
-bool QuirksManager::isMMapSafe(AudioStreamBuilder &builder) {
- if (!OboeGlobals::areWorkaroundsEnabled()) return true;
- return mDeviceQuirks->isMMapSafe(builder);
-}