Merge "audiopolicy: default engine audio source add blutooth ble device [1/1]"
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 1700a95..55a32ae 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -11,7 +11,7 @@
}
-cc_library_shared {
+cc_library {
name: "libmediadrm",
srcs: [
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
new file mode 100644
index 0000000..6f2d054
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+ name: "mediadrm_fuzzer",
+ srcs: [
+ "mediadrm_fuzzer.cpp",
+ ],
+ static_libs: [
+ "libmediadrm",
+ "liblog",
+ "resourcemanager_aidl_interface-ndk_platform",
+ ],
+ header_libs: [
+ "libmedia_headers",
+ "libmediadrm_headers",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libutils",
+ "libbinder_ndk",
+ "libcutils",
+ "libdl",
+ "libmedia",
+ "libmediadrmmetrics_lite",
+ "libmediametrics#1",
+ "libmediautils",
+ "libstagefright_foundation",
+ "android.hardware.drm@1.0",
+ "android.hardware.drm@1.1",
+ "android.hardware.drm@1.2",
+ "android.hardware.drm@1.3",
+ "libhidlallocatorutils",
+ "libhidlbase",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
diff --git a/drm/libmediadrm/fuzzer/README.md b/drm/libmediadrm/fuzzer/README.md
new file mode 100644
index 0000000..3c95cd7
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/README.md
@@ -0,0 +1,56 @@
+# Fuzzer for libmediadrm
+
+## Plugin Design Considerations
+The fuzzer plugin for libmediadrm is designed based on the understanding of the
+library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libmediadrm supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Mime Type (parameter name: `mimeType`)
+3. Key Type (parameter name: `keyType`)
+4. Crypto Mode (parameter name: `cryptoMode`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`DrmPlugin::kSecurityLevelUnknown` 1.`DrmPlugin::kSecurityLevelMax` 2.`DrmPlugin::kSecurityLevelSwSecureCrypto` 3.`DrmPlugin::kSecurityLevelSwSecureDecode` 4.`DrmPlugin::kSecurityLevelHwSecureCrypto` 5.`DrmPlugin::kSecurityLevelHwSecureDecode` 6.`DrmPlugin::kSecurityLevelHwSecureAll`| Value obtained from FuzzedDataProvider in the range 0 to 6|
+| `mimeType` | 0.`video/mp4` 1.`video/mpeg` 2.`video/x-flv` 3.`video/mj2` 4.`video/3gp2` 5.`video/3gpp` 6.`video/3gpp2` 7.`audio/mp4` 8.`audio/mpeg` 9.`audio/aac` 10.`audio/3gp2` 11.`audio/3gpp` 12.`audio/3gpp2` 13.`video/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 13|
+| `keyType` | 0.`DrmPlugin::kKeyType_Offline` 1.`DrmPlugin::kKeyType_Streaming` 2.`DrmPlugin::kKeyType_Release` | Value obtained from FuzzedDataProvider in the range 0 to 2|
+| `cryptoMode` | 0.`CryptoPlugin::kMode_Unencrypted` 1.`CryptoPlugin::kMode_AES_CTR` 2.`CryptoPlugin::kMode_AES_WV` 3.`CryptoPlugin::kMode_AES_CBC` | Value obtained from FuzzedDataProvider in the range 0 to 3|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the drm module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build mediadrm_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) mediadrm_fuzzer
+```
+#### Steps to run
+Create a directory CORPUS_DIR
+```
+ $ adb shell mkdir CORPUS_DIR
+```
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/${TARGET_ARCH}/mediadrm_fuzzer/mediadrm_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
new file mode 100644
index 0000000..8df0477
--- /dev/null
+++ b/drm/libmediadrm/fuzzer/mediadrm_fuzzer.cpp
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+#include <binder/MemoryDealer.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <mediadrm/CryptoHal.h>
+#include <mediadrm/DrmHal.h>
+#include <utils/String8.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+#define AES_BLOCK_SIZE 16
+#define UNUSED_PARAM __attribute__((unused))
+
+using namespace std;
+using namespace android;
+using android::hardware::fromHeap;
+using ::android::os::PersistableBundle;
+using drm::V1_0::BufferType;
+
+enum {
+ INVALID_UUID = 0,
+ PSSH_BOX_UUID,
+ CLEARKEY_UUID,
+};
+
+static const uint8_t kInvalidUUID[16] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
+ 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
+
+static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
+ 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+
+static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+ 0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+static const uint32_t kUUID[] = {INVALID_UUID, PSSH_BOX_UUID, CLEARKEY_UUID};
+
+const DrmPlugin::SecurityLevel kSecurityLevel[] = {
+ DrmPlugin::kSecurityLevelUnknown, DrmPlugin::kSecurityLevelMax,
+ DrmPlugin::kSecurityLevelSwSecureCrypto, DrmPlugin::kSecurityLevelSwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureCrypto, DrmPlugin::kSecurityLevelHwSecureDecode,
+ DrmPlugin::kSecurityLevelHwSecureAll};
+
+const char *kMimeType[] = {"video/mp4", "video/mpeg", "video/x-flv", "video/mj2",
+ "video/3gp2", "video/3gpp", "video/3gpp2", "audio/mp4",
+ "audio/mpeg", "audio/aac", "audio/3gp2", "audio/3gpp",
+ "audio/3gpp2", "video/unknown", "audio/unknown"};
+
+const DrmPlugin::KeyType kKeyType[] = {DrmPlugin::kKeyType_Offline, DrmPlugin::kKeyType_Streaming,
+ DrmPlugin::kKeyType_Release};
+
+const CryptoPlugin::Mode kCryptoMode[] = {CryptoPlugin::kMode_Unencrypted,
+ CryptoPlugin::kMode_AES_CTR, CryptoPlugin::kMode_AES_WV,
+ CryptoPlugin::kMode_AES_CBC};
+
+const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
+const char *kMacAlgorithm[] = {"HmacSHA256", ""};
+const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
+const size_t kNumSecurityLevel = size(kSecurityLevel);
+const size_t kNumMimeType = size(kMimeType);
+const size_t kNumKeyType = size(kKeyType);
+const size_t kNumCryptoMode = size(kCryptoMode);
+const size_t kNumUUID = size(kUUID);
+const size_t kMaxStringLength = 100;
+const size_t kMaxSubSamples = 10;
+const size_t kMaxNumBytes = 1000;
+
+struct DrmListener : virtual public IDrmClient {
+ public:
+ void sendEvent(DrmPlugin::EventType eventType UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const hardware::hidl_vec<uint8_t> &data UNUSED_PARAM) override {}
+
+ void sendExpirationUpdate(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ int64_t expiryTimeInMS UNUSED_PARAM) override {}
+
+ void sendKeysChange(const hardware::hidl_vec<uint8_t> &sessionId UNUSED_PARAM,
+ const std::vector<DrmKeyStatus> &keyStatusList UNUSED_PARAM,
+ bool hasNewUsableKey UNUSED_PARAM) override {}
+
+ void sendSessionLostState(const hardware::hidl_vec<uint8_t> &) override {}
+ DrmListener() {}
+
+ private:
+ DISALLOW_EVIL_CONSTRUCTORS(DrmListener);
+};
+
+class DrmFuzzer {
+ public:
+ void process(const uint8_t *data, size_t size);
+
+ private:
+ void invokeDrm(const uint8_t *data, size_t size);
+ bool initDrm();
+ void invokeDrmCreatePlugin();
+ void invokeDrmOpenSession();
+ void invokeDrmSetListener();
+ void invokeDrmSetAlgorithmAPI();
+ void invokeDrmPropertyAPI();
+ void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
+ void invokeDrmSecureStopAPI();
+ void invokeDrmOfflineLicenseAPI();
+ void invokeDrmCloseSession();
+ void invokeDrmDestroyPlugin();
+ void invokeCrypto(const uint8_t *data);
+ bool initCrypto();
+ void invokeCryptoCreatePlugin();
+ void invokeCryptoDecrypt(const uint8_t *data);
+ void invokeCryptoDestroyPlugin();
+ sp<DrmHal> mDrm = nullptr;
+ sp<CryptoHal> mCrypto = nullptr;
+ Vector<uint8_t> mSessionId = {};
+ FuzzedDataProvider *mFuzzedDataProvider = nullptr;
+};
+
+bool DrmFuzzer::initDrm() {
+ mDrm = new DrmHal();
+ if (!mDrm) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeDrmCreatePlugin() {
+ mDrm->initCheck();
+ String8 packageName(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ uint32_t uuidEnum = kUUID[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumUUID - 1)];
+ switch (uuidEnum) {
+ case INVALID_UUID:
+ mDrm->createPlugin(kInvalidUUID, packageName);
+ break;
+ case PSSH_BOX_UUID:
+ mDrm->createPlugin(kCommonPsshBoxUUID, packageName);
+ break;
+ case CLEARKEY_UUID:
+ mDrm->createPlugin(kClearKeyUUID, packageName);
+ break;
+ default:
+ break;
+ }
+}
+
+void DrmFuzzer::invokeDrmDestroyPlugin() { mDrm->destroyPlugin(); }
+
+void DrmFuzzer::invokeDrmOpenSession() {
+ DrmPlugin::SecurityLevel securityLevel;
+ bool shouldPassRandomSecurityLevel = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomSecurityLevel) {
+ securityLevel =
+ static_cast<DrmPlugin::SecurityLevel>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ securityLevel = kSecurityLevel[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kNumSecurityLevel - 1)];
+ }
+ mDrm->openSession(securityLevel, mSessionId);
+}
+
+void DrmFuzzer::invokeDrmCloseSession() { mDrm->closeSession(mSessionId); }
+
+void DrmFuzzer::invokeDrmSetListener() {
+ sp<DrmListener> listener = new DrmListener();
+ mDrm->setListener(listener);
+}
+
+void DrmFuzzer::invokeDrmSetAlgorithmAPI() {
+ mDrm->setCipherAlgorithm(mSessionId,
+ String8(kCipherAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+ mDrm->setMacAlgorithm(mSessionId, String8(kMacAlgorithm[mFuzzedDataProvider->ConsumeBool()]));
+}
+
+void DrmFuzzer::invokeDrmPropertyAPI() {
+ mDrm->setPropertyString(String8("property"), String8("value"));
+ String8 stringValue;
+ mDrm->getPropertyString(String8("property"), stringValue);
+ Vector<uint8_t> value = {};
+ mDrm->setPropertyByteArray(String8("property"), value);
+ Vector<uint8_t> byteValue;
+ mDrm->getPropertyByteArray(String8("property"), byteValue);
+}
+
+void DrmFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size) {
+ uint32_t openSessions = 0;
+ uint32_t maxSessions = 0;
+ mDrm->getNumberOfSessions(&openSessions, &maxSessions);
+
+ DrmPlugin::HdcpLevel connected;
+ DrmPlugin::HdcpLevel max;
+ mDrm->getHdcpLevels(&connected, &max);
+
+ DrmPlugin::SecurityLevel securityLevel;
+ mDrm->getSecurityLevel(mSessionId, &securityLevel);
+
+ // isCryptoSchemeSupported() shall fill isSupported
+ bool isSupported;
+ String8 mimeType(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+ mDrm->isCryptoSchemeSupported(kClearKeyUUID, mimeType, securityLevel, &isSupported);
+
+ // getProvisionRequest() shall fill legacyRequest and legacyDefaultUrl
+ String8 certificateType(
+ mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ String8 certAuthority(mFuzzedDataProvider->ConsumeRandomLengthString(kMaxStringLength).c_str());
+ Vector<uint8_t> legacyRequest = {};
+ String8 legacyDefaultUrl;
+ mDrm->getProvisionRequest(certificateType, certAuthority, legacyRequest, legacyDefaultUrl);
+
+ // provideProvisionResponse() shall fill certificate and wrappedKey
+ Vector<uint8_t> provisionResponse = {};
+ Vector<uint8_t> certificate = {};
+ Vector<uint8_t> wrappedKey = {};
+ mDrm->provideProvisionResponse(provisionResponse, certificate, wrappedKey);
+
+ // getKeyRequest() shall fill keyRequest, defaultUrl and keyRequestType
+ Vector<uint8_t> initData = {};
+ initData.appendArray(data, size);
+ DrmPlugin::KeyType keyType;
+ bool shouldPassRandomKeyType = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomKeyType) {
+ keyType = static_cast<DrmPlugin::KeyType>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ keyType = kKeyType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumKeyType - 1)];
+ }
+ KeyedVector<String8, String8> mdOptionalParameters = {};
+ Vector<uint8_t> keyRequest = {};
+ String8 defaultUrl;
+ DrmPlugin::KeyRequestType keyRequestType;
+ mDrm->getKeyRequest(mSessionId, initData, mimeType, keyType, mdOptionalParameters, keyRequest,
+ defaultUrl, &keyRequestType);
+
+ // provideKeyResponse() shall fill keySetId
+ Vector<uint8_t> keyResponse = {};
+ keyResponse.appendArray(data, size);
+ Vector<uint8_t> keySetId = {};
+ mDrm->provideKeyResponse(mSessionId, keyResponse, keySetId);
+
+ // restoreKeys
+ mDrm->restoreKeys(mSessionId, keySetId);
+
+ // queryKeyStatus() shall fill infoMap
+ KeyedVector<String8, String8> infoMap = {};
+ mDrm->queryKeyStatus(mSessionId, infoMap);
+
+ // decrypt() shall fill outputVec
+ Vector<uint8_t> keyIdVec = {};
+ keyIdVec.appendArray(data, size);
+
+ Vector<uint8_t> inputVec = {};
+ inputVec.appendArray(data, size);
+
+ Vector<uint8_t> ivVec = {};
+ ivVec.appendArray(data, size);
+
+ Vector<uint8_t> outputVec = {};
+ mDrm->decrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // encrypt() shall fill outputVec
+ mDrm->encrypt(mSessionId, keyIdVec, inputVec, ivVec, outputVec);
+
+ // sign() shall fill signature
+ Vector<uint8_t> message = {};
+ message.appendArray(data, size);
+ Vector<uint8_t> signature = {};
+ mDrm->sign(mSessionId, keyIdVec, message, signature);
+
+ // verify() shall fill match
+ bool match;
+ mDrm->verify(mSessionId, keyIdVec, message, signature, match);
+
+ // signRSA() shall fill signature
+ mDrm->signRSA(mSessionId, String8(kRSAAlgorithm[mFuzzedDataProvider->ConsumeBool()]), message,
+ wrappedKey, signature);
+
+ mDrm->removeKeys(mSessionId);
+}
+
+void DrmFuzzer::invokeDrmSecureStopAPI() {
+ // getSecureStops() shall fill secureStops
+ List<Vector<uint8_t>> secureStops = {};
+ mDrm->getSecureStops(secureStops);
+
+ // getSecureStopIds() shall fill secureStopIds
+ List<Vector<uint8_t>> secureStopIds = {};
+ mDrm->getSecureStopIds(secureStopIds);
+
+ // getSecureStop() shall fill secureStop
+ Vector<uint8_t> ssid = {};
+ Vector<uint8_t> secureStop = {};
+ mDrm->getSecureStop(ssid, secureStop);
+
+ mDrm->removeSecureStop(ssid);
+
+ mDrm->releaseSecureStops(ssid);
+
+ mDrm->removeAllSecureStops();
+}
+
+void DrmFuzzer::invokeDrmOfflineLicenseAPI() {
+ // getOfflineLicenseKeySetIds() shall keySetIds
+ List<Vector<uint8_t>> keySetIds = {};
+ mDrm->getOfflineLicenseKeySetIds(keySetIds);
+
+ // getOfflineLicenseState() shall fill state
+ Vector<uint8_t> const keySetIdOfflineLicense = {};
+ DrmPlugin::OfflineLicenseState state;
+ mDrm->getOfflineLicenseState(keySetIdOfflineLicense, &state);
+
+ mDrm->removeOfflineLicense(keySetIdOfflineLicense);
+}
+
+bool DrmFuzzer::initCrypto() {
+ mCrypto = new CryptoHal();
+ if (!mCrypto) {
+ return false;
+ }
+ return true;
+}
+
+void DrmFuzzer::invokeCryptoCreatePlugin() {
+ mCrypto->initCheck();
+
+ mCrypto->isCryptoSchemeSupported(kClearKeyUUID);
+ mCrypto->createPlugin(kClearKeyUUID, NULL, 0);
+}
+
+void DrmFuzzer::invokeCryptoDestroyPlugin() { mCrypto->destroyPlugin(); }
+
+void DrmFuzzer::invokeCryptoDecrypt(const uint8_t *data) {
+ mCrypto->requiresSecureDecoderComponent(
+ kMimeType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumMimeType - 1)]);
+
+ uint32_t width = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ uint32_t height = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ mCrypto->notifyResolution(width, height);
+
+ mCrypto->setMediaDrmSession(mSessionId);
+
+ const CryptoPlugin::Pattern pattern = {0, 0};
+
+ size_t totalSize = 0;
+ size_t numSubSamples = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
+
+ CryptoPlugin::SubSample subSamples[numSubSamples];
+
+ for (size_t i = 0; i < numSubSamples; ++i) {
+ uint32_t clearBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ uint32_t encryptedBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxNumBytes);
+ subSamples[i].mNumBytesOfClearData = clearBytes;
+ subSamples[i].mNumBytesOfEncryptedData = encryptedBytes;
+ totalSize += subSamples[i].mNumBytesOfClearData;
+ totalSize += subSamples[i].mNumBytesOfEncryptedData;
+ }
+
+ size_t heapSize = totalSize * 2;
+ sp<MemoryDealer> dealer = new MemoryDealer(heapSize, "DrmFuzzerMemory");
+ if (!dealer) {
+ return;
+ }
+
+ sp<HidlMemory> heap = fromHeap(dealer->getMemoryHeap());
+ if (!heap) {
+ return;
+ }
+ int heapSeqNum = mCrypto->setHeap(heap);
+ if (heapSeqNum < 0) {
+ return;
+ }
+
+ const size_t segmentIndex = 0;
+ const uint8_t keyId[AES_BLOCK_SIZE] = {};
+ memcpy((void *)keyId, data, AES_BLOCK_SIZE);
+
+ const uint8_t iv[AES_BLOCK_SIZE] = {};
+ memset((void *)iv, 0, AES_BLOCK_SIZE);
+
+ const SharedBuffer sourceBuffer = {.bufferId = segmentIndex, .offset = 0, .size = totalSize};
+
+ const DestinationBuffer destBuffer = {
+ .type = BufferType::SHARED_MEMORY,
+ {.bufferId = segmentIndex, .offset = totalSize, .size = totalSize},
+ .secureMemory = nullptr};
+
+ const uint64_t offset = 0;
+ AString *errorDetailMsg = nullptr;
+ CryptoPlugin::Mode mode;
+ bool shouldPassRandomCryptoMode = mFuzzedDataProvider->ConsumeBool();
+ if (shouldPassRandomCryptoMode) {
+ mode = static_cast<CryptoPlugin::Mode>(mFuzzedDataProvider->ConsumeIntegral<size_t>());
+ } else {
+ mode =
+ kCryptoMode[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kNumCryptoMode - 1)];
+ }
+ mCrypto->decrypt(keyId, iv, mode, pattern, sourceBuffer, offset, subSamples, numSubSamples,
+ destBuffer, errorDetailMsg);
+
+ if (heapSeqNum >= 0) {
+ mCrypto->unsetHeap(heapSeqNum);
+ }
+ heap.clear();
+}
+
+void DrmFuzzer::invokeDrm(const uint8_t *data, size_t size) {
+ if (!initDrm()) {
+ return;
+ }
+ invokeDrmCreatePlugin();
+ invokeDrmOpenSession();
+ invokeDrmSetAlgorithmAPI();
+ invokeDrmSetListener();
+ invokeDrmPropertyAPI();
+ invokeDrmDecryptEncryptAPI(data, size);
+ invokeDrmSecureStopAPI();
+ invokeDrmOfflineLicenseAPI();
+ invokeDrmCloseSession();
+ invokeDrmDestroyPlugin();
+}
+
+void DrmFuzzer::invokeCrypto(const uint8_t *data) {
+ if (!initCrypto()) {
+ return;
+ }
+ invokeCryptoCreatePlugin();
+ invokeCryptoDecrypt(data);
+ invokeCryptoDestroyPlugin();
+}
+
+void DrmFuzzer::process(const uint8_t *data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ invokeDrm(data, size);
+ invokeCrypto(data);
+ delete mFuzzedDataProvider;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < AES_BLOCK_SIZE) {
+ return 0;
+ }
+ DrmFuzzer drmFuzzer;
+ drmFuzzer.process(data, size);
+ return 0;
+}
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 420e172..930292f 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -14,3 +14,24 @@
"libhardware_headers",
],
}
+
+cc_benchmark {
+ name: "reverb_benchmark",
+ vendor: true,
+ include_dirs: [
+ "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+ ],
+ srcs: ["reverb_benchmark.cpp"],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "liblog",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+}
diff --git a/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
new file mode 100644
index 0000000..00a7ff2
--- /dev/null
+++ b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <climits>
+#include <cstdlib>
+#include <random>
+#include <vector>
+#include <log/log.h>
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <system/audio.h>
+#include "EffectReverb.h"
+
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+constexpr effect_uuid_t kEffectUuids[] = {
+ {0x172cdf00,
+ 0xa3bc,
+ 0x11df,
+ 0xa72f,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-insert mode
+ {0xf29a1400,
+ 0xa3bb,
+ 0x11df,
+ 0x8ddc,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-aux mode
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+constexpr size_t kFrameCount = 2048;
+
+constexpr int kPresets[] = {
+ REVERB_PRESET_NONE, REVERB_PRESET_SMALLROOM, REVERB_PRESET_MEDIUMROOM,
+ REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+ REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+constexpr int kSampleRate = 44100;
+
+int reverbSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ if (status != 0) {
+ ALOGE("Reverb set config returned an error = %d\n", status);
+ return status;
+ }
+ return reply;
+}
+
+/*******************************************************************
+ * A test result running on Pixel 3 with for comparison.
+ * The first parameter indicates the preset level id.
+ * The second parameter indicates the effect.
+ * 0: preset-insert mode, 1: preset-aux mode
+ * --------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * --------------------------------------------------------
+ * BM_REVERB/0/0 19312 ns 19249 ns 36282
+ * BM_REVERB/0/1 5613 ns 5596 ns 125032
+ * BM_REVERB/1/0 605453 ns 603714 ns 1131
+ * BM_REVERB/1/1 589421 ns 587758 ns 1161
+ * BM_REVERB/2/0 605760 ns 604006 ns 1131
+ * BM_REVERB/2/1 589434 ns 587777 ns 1161
+ * BM_REVERB/3/0 605574 ns 603828 ns 1131
+ * BM_REVERB/3/1 589566 ns 587862 ns 1162
+ * BM_REVERB/4/0 605634 ns 603894 ns 1131
+ * BM_REVERB/4/1 589506 ns 587856 ns 1161
+ * BM_REVERB/5/0 605644 ns 603929 ns 1131
+ * BM_REVERB/5/1 589592 ns 587863 ns 1161
+ * BM_REVERB/6/0 610544 ns 608561 ns 1131
+ * BM_REVERB/6/1 589686 ns 587871 ns 1161
+ *******************************************************************/
+
+static void BM_REVERB(benchmark::State& state) {
+ const size_t chMask = AUDIO_CHANNEL_OUT_STEREO;
+ const size_t preset = kPresets[state.range(0)];
+ const effect_uuid_t uuid = kEffectUuids[state.range(1)];
+ const size_t channelCount = audio_channel_count_from_out_mask(chMask);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(chMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ std::vector<float> input(kFrameCount * channelCount);
+ std::vector<float> output(kFrameCount * channelCount);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ effect_handle_t effectHandle = nullptr;
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&uuid, 1, 1, &effectHandle);
+ status != 0) {
+ ALOGE("create_effect returned an error = %d\n", status);
+ return;
+ }
+
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = chMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ status != 0) {
+ ALOGE("command returned an error = %d\n", status);
+ return;
+ }
+
+ if (int status =
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ status != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return;
+ }
+
+ if (int status = reverbSetConfigParam(REVERB_PARAM_PRESET, preset, effectHandle); status != 0) {
+ ALOGE("Invalid reverb preset. Error %d\n", status);
+ return;
+ }
+
+ // Run the test
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(input.data());
+ benchmark::DoNotOptimize(output.data());
+
+ audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
+ audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
+ (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+ benchmark::ClobberMemory();
+ }
+
+ state.SetComplexityN(state.range(0));
+
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+ ALOGE("release_effect returned an error = %d\n", status);
+ return;
+ }
+}
+
+static void REVERBArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < kNumPresets; i++) {
+ for (int j = 0; j < kNumEffectUuids; ++j) {
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_REVERB)->Apply(REVERBArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index dbe0d62..34cad1f 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -204,10 +204,12 @@
"Reverb/lib",
"Common/lib",
],
-
+ static_libs: [
+ "libaudioutils",
+ ],
cppflags: [
+ "-DBIQUAD_OPT",
"-fvisibility=hidden",
-
"-Wall",
"-Werror",
],
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
index 1f0b459..814280f 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.cpp
@@ -23,6 +23,7 @@
#ifdef BIQUAD_OPT
#include <audio_utils/BiquadFilter.h>
+#include <system/audio.h>
#endif
#include "LVDBE.h"
#include "LVDBE_Private.h"
@@ -114,7 +115,7 @@
std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
LVDBE_HPF_Table[Offset].A0, LVDBE_HPF_Table[Offset].A1, LVDBE_HPF_Table[Offset].A2,
-(LVDBE_HPF_Table[Offset].B1), -(LVDBE_HPF_Table[Offset].B2)};
- pInstance->pBqInstance
+ pInstance->pHPFBiquad
->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
#else
LoadConst_Float(0, /* Clear the history, value 0 */
@@ -128,12 +129,19 @@
/*
* Setup the band pass filter
*/
+#ifdef BIQUAD_OPT
+ coefs = {LVDBE_BPF_Table[Offset].A0, 0.0, -(LVDBE_BPF_Table[Offset].A0),
+ -(LVDBE_BPF_Table[Offset].B1), -(LVDBE_BPF_Table[Offset].B2)};
+ pInstance->pBPFBiquad
+ ->setCoefficients<std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(coefs);
+#else
LoadConst_Float(0, /* Clear the history, value 0 */
(LVM_FLOAT*)&pInstance->pData->BPFTaps, /* Destination */
sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
&pInstance->pData->BPFTaps,
(BP_FLOAT_Coefs_t*)&LVDBE_BPF_Table[Offset]);
+#endif
}
/************************************************************************************/
@@ -290,9 +298,8 @@
/*
* Create biquad instance
*/
- pInstance->pBqInstance.reset(
- new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels));
- pInstance->pBqInstance->clear();
+ pInstance->pHPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
#endif
/*
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
index 611b762..6bdb7fe 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.cpp
@@ -20,8 +20,11 @@
/* Includes */
/* */
/****************************************************************************************/
-#include <stdlib.h>
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
+#include <stdlib.h>
#include "LVDBE.h"
#include "LVDBE_Private.h"
@@ -89,17 +92,18 @@
if (pInstance->pData == NULL) {
return LVDBE_NULLADDRESS;
}
- pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
- if (pInstance->pCoef == NULL) {
- return LVDBE_NULLADDRESS;
- }
-
#ifdef BIQUAD_OPT
/*
* Create biquad instance
*/
- pInstance->pBqInstance.reset(
+ pInstance->pHPFBiquad.reset(
new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ pInstance->pBPFBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1));
+#else
+ pInstance->pCoef = (LVDBE_Coef_FLOAT_t*)calloc(1, sizeof(*(pInstance->pCoef)));
+ if (pInstance->pCoef == NULL) {
+ return LVDBE_NULLADDRESS;
+ }
#endif
/*
@@ -190,10 +194,12 @@
free(pInstance->pData);
pInstance->pData = LVM_NULL;
}
+#ifndef BIQUAD_OPT
if (pInstance->pCoef != LVM_NULL) {
free(pInstance->pCoef);
pInstance->pCoef = LVM_NULL;
}
+#endif
free(pInstance);
*phInstance = LVM_NULL;
}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index fa85638..23be2aa 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -68,21 +68,22 @@
/* Process variables */
#ifndef BIQUAD_OPT
Biquad_2I_Order2_FLOAT_Taps_t HPFTaps; /* High pass filter taps */
-#endif
Biquad_1I_Order2_FLOAT_Taps_t BPFTaps; /* Band pass filter taps */
+#endif
LVMixer3_1St_FLOAT_st BypassVolume; /* Bypass volume scaler */
LVMixer3_2St_FLOAT_st BypassMixer; /* Bypass Mixer for Click Removal */
} LVDBE_Data_FLOAT_t;
+#ifndef BIQUAD_OPT
/* Coefs structure */
typedef struct {
/* Process variables */
-#ifndef BIQUAD_OPT
Biquad_FLOAT_Instance_t HPFInstance; /* High pass filter instance */
-#endif
Biquad_FLOAT_Instance_t BPFInstance; /* Band pass filter instance */
} LVDBE_Coef_FLOAT_t;
+#endif
+
/* Instance structure */
typedef struct {
/* Public parameters */
@@ -91,11 +92,15 @@
/* Data and coefficient pointers */
LVDBE_Data_FLOAT_t* pData; /* Instance data */
+#ifndef BIQUAD_OPT
LVDBE_Coef_FLOAT_t* pCoef; /* Instance coefficients */
+#endif
void* pScratch; /* scratch pointer */
#ifdef BIQUAD_OPT
std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
- pBqInstance; /* Biquad filter instance */
+ pHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pBPFBiquad; /* Biquad filter instance for BPF */
#endif
} LVDBE_Instance_t;
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
index bd04a02..4a72834 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.cpp
@@ -129,7 +129,7 @@
*/
if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) {
#ifdef BIQUAD_OPT
- pInstance->pBqInstance->process(pScratch, pScratch, NrFrames);
+ pInstance->pHPFBiquad->process(pScratch, pScratch, NrFrames);
#else
BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
pScratch, /* Source */
@@ -149,10 +149,14 @@
/*
* Apply the band pass filter
*/
+#ifdef BIQUAD_OPT
+ pInstance->pBPFBiquad->process(pMono, pMono, NrFrames);
+#else
BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
pMono, /* Source */
pMono, /* Destination */
(LVM_INT16)NrFrames);
+#endif
/*
* Apply the AGC and mix
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
index 3118e77..7e8664a 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.cpp
@@ -276,6 +276,16 @@
*/
Offset = (LVM_INT16)(EffectLevel - 1 +
TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVM_TrebleBoostCoefs[Offset].A0, LVM_TrebleBoostCoefs[Offset].A1, 0.0,
+ -(LVM_TrebleBoostCoefs[Offset].B1), 0.0};
+ pInstance->pTEBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(pParams->NrChannels, coefs));
+#else
FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
&pInstance->pTE_Taps->TrebleBoost_Taps,
&LVM_TrebleBoostCoefs[Offset]);
@@ -288,6 +298,7 @@
Cast to void: no dereferencing in function */
(LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) /
sizeof(LVM_FLOAT))); /* Number of words */
+#endif
}
} else {
/*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
index bb962df..bbfa0dc 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.cpp
@@ -174,6 +174,7 @@
/*
* Treble Enhancement
*/
+#ifndef BIQUAD_OPT
pInstance->pTE_Taps = (LVM_TE_Data_t*)calloc(1, sizeof(*(pInstance->pTE_Taps)));
if (pInstance->pTE_Taps == LVM_NULL) {
return LVM_NULLADDRESS;
@@ -182,6 +183,7 @@
if (pInstance->pTE_State == LVM_NULL) {
return LVM_NULLADDRESS;
}
+#endif
pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
pInstance->Params.TE_EffectLevel = 0;
pInstance->TE_Active = LVM_FALSE;
@@ -494,6 +496,7 @@
/*
* Treble Enhancement
*/
+#ifndef BIQUAD_OPT
if (pInstance->pTE_Taps != LVM_NULL) {
free(pInstance->pTE_Taps);
pInstance->pTE_Taps = LVM_NULL;
@@ -502,6 +505,7 @@
free(pInstance->pTE_State);
pInstance->pTE_State = LVM_NULL;
}
+#endif
/*
* Free the default EQNB pre-gain and pointer to the band definitions
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index 90a1f19..56bbfd1 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -33,6 +33,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVM.h" /* LifeVibes */
#include "LVM_Common.h" /* LifeVibes common */
#include "BIQUAD.h" /* Biquad library */
@@ -127,6 +130,7 @@
LVM_INT16 SamplesToOutput; /* Samples to write to the output */
} LVM_Buffer_t;
+#ifndef BIQUAD_OPT
/* Filter taps */
typedef struct {
Biquad_2I_Order1_FLOAT_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
@@ -136,6 +140,7 @@
typedef struct {
Biquad_FLOAT_Instance_t TrebleBoost_State; /* State for the treble boost filter */
} LVM_TE_Coefs_t;
+#endif
typedef struct {
/* Public parameters */
@@ -185,8 +190,13 @@
LVM_INT16 VC_AVLFixedVolume; /* AVL fixed volume */
/* Treble Enhancement */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pTEBiquad; /* Biquad filter instance */
+#else
LVM_TE_Data_t* pTE_Taps; /* Treble boost Taps */
LVM_TE_Coefs_t* pTE_State; /* State for the treble boost filter */
+#endif
LVM_INT16 TE_Active; /* Control flag */
/* Headroom */
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index c94c469..acd594f 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -190,9 +190,13 @@
/*
* Apply the filter
*/
+#ifdef BIQUAD_OPT
+ pInstance->pTEBiquad->process(pProcessed, pProcessed, NrFrames);
+#else
FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
pProcessed, pProcessed, (LVM_INT16)NrFrames,
(LVM_INT16)NrChannels);
+#endif
}
/*
* Volume balance
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
index 8887890..7bcb7d7 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.cpp
@@ -18,7 +18,7 @@
/**********************************************************************************
INCLUDE FILES
***********************************************************************************/
-
+#include <string.h>
#include "VectorArithmetic.h"
/**********************************************************************************
@@ -47,24 +47,7 @@
return;
}
void Copy_Float(const LVM_FLOAT* src, LVM_FLOAT* dst, LVM_INT16 n) {
- LVM_INT16 ii;
-
- if (src > dst) {
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst++;
- src++;
- }
- } else {
- src += n - 1;
- dst += n - 1;
- for (ii = n; ii != 0; ii--) {
- *dst = *src;
- dst--;
- src--;
- }
- }
-
+ memmove(dst, src, n * sizeof(LVM_FLOAT));
return;
}
// Extract out the stereo channel pair from multichannel source.
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
index bccbe86..f4e625f 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.cpp
@@ -21,6 +21,9 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVEQNB.h"
#include "LVEQNB_Private.h"
#include "VectorArithmetic.h"
@@ -179,6 +182,9 @@
LVM_UINT16 i; /* Filter band index */
LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
+#ifdef BIQUAD_OPT
+ pInstance->gain.resize(pInstance->Params.NBands);
+#endif
/*
* Set the coefficients for each band by the init function
*/
@@ -198,8 +204,19 @@
/*
* Set the coefficients
*/
+#ifdef BIQUAD_OPT
+ pInstance->gain[i] = Coefficients.G;
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coefficients.A0, 0.0, -(Coefficients.A0), -(Coefficients.B1),
+ -(Coefficients.B2)};
+ pInstance->eqBiquad[i]
+ .setCoefficients<
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs>>(
+ coefs);
+#else
PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
&pInstance->pEQNB_Taps_Float[i], &Coefficients);
+#endif
break;
}
default:
@@ -220,6 +237,11 @@
/* */
/************************************************************************************/
void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t* pInstance) {
+#ifdef BIQUAD_OPT
+ for (size_t i = 0; i < pInstance->eqBiquad.size(); i++) {
+ pInstance->eqBiquad[i].clear();
+ }
+#else
LVM_FLOAT* pTapAddress;
LVM_INT16 NumTaps;
@@ -233,6 +255,7 @@
pTapAddress, /* Destination */
NumTaps); /* Number of words */
}
+#endif
}
/****************************************************************************************/
/* */
@@ -310,6 +333,16 @@
(OperatingModeSave == LVEQNB_ON && pInstance->bInOperatingModeTransition &&
LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
+#ifdef BIQUAD_OPT
+ /*
+ * Create biquad instance
+ */
+ pInstance->eqBiquad.resize(
+ pParams->NBands, android::audio_utils::BiquadFilter<LVM_FLOAT>(
+ (FCC_1 == pParams->NrChannels) ? FCC_2 : pParams->NrChannels));
+ LVEQNB_ClearFilterHistory(pInstance);
+#endif
+
if (bChange || modeChange) {
/*
* If the sample rate has changed clear the history
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
index 1d2a5f5..57df4db 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.cpp
@@ -62,6 +62,9 @@
pInstance->pScratch = pScratch;
/* Equaliser Biquad Instance */
+#ifdef BIQUAD_OPT
+ LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions));
+#else
LVM_UINT32 MemSize = pCapabilities->MaxBands * sizeof(*(pInstance->pEQNB_FilterState_Float));
pInstance->pEQNB_FilterState_Float = (Biquad_FLOAT_Instance_t*)calloc(1, MemSize);
if (pInstance->pEQNB_FilterState_Float == LVM_NULL) {
@@ -75,6 +78,7 @@
}
MemSize = (pCapabilities->MaxBands * sizeof(*(pInstance->pBandDefinitions)));
+#endif
pInstance->pBandDefinitions = (LVEQNB_BandDef_t*)calloc(1, MemSize);
if (pInstance->pBandDefinitions == LVM_NULL) {
return LVEQNB_NULLADDRESS;
@@ -105,10 +109,11 @@
*/
LVEQNB_SetFilters(pInstance, /* Set the filter types */
&pInstance->Params);
-
+#ifndef BIQUAD_OPT
LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
+#endif
/*
* Initialise the bypass variables
@@ -154,6 +159,7 @@
}
pInstance = (LVEQNB_Instance_t*)*phInstance;
+#ifndef BIQUAD_OPT
/* Equaliser Biquad Instance */
if (pInstance->pEQNB_FilterState_Float != LVM_NULL) {
free(pInstance->pEQNB_FilterState_Float);
@@ -163,6 +169,7 @@
free(pInstance->pEQNB_Taps_Float);
pInstance->pEQNB_Taps_Float = LVM_NULL;
}
+#endif
if (pInstance->pBandDefinitions != LVM_NULL) {
free(pInstance->pBandDefinitions);
pInstance->pBandDefinitions = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 83a3449..32bad29 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -24,6 +24,9 @@
/* */
/****************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVEQNB.h" /* Calling or Application layer definitions */
#include "BIQUAD.h"
#include "LVC_Mixer.h"
@@ -69,8 +72,14 @@
/* Aligned memory pointers */
LVM_FLOAT* pFastTemporary; /* Fast temporary data base address */
+#ifdef BIQUAD_OPT
+ std::vector<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ eqBiquad; /* Biquad filter instances */
+ std::vector<LVM_FLOAT> gain; /* Gain values for all bands*/
+#else
Biquad_2I_Order2_FLOAT_Taps_t* pEQNB_Taps_Float; /* Equaliser Taps */
Biquad_FLOAT_Instance_t* pEQNB_FilterState_Float; /* State for each filter band */
+#endif
/* Filter definitions and call back */
LVM_UINT16 NBands; /* Number of bands */
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
index d2a26db..3f0be7c 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.cpp
@@ -104,19 +104,30 @@
* Check if band is non-zero dB gain
*/
if (pInstance->pBandDefinitions[i].Gain != 0) {
+#ifndef BIQUAD_OPT
/*
* Get the address of the biquad instance
*/
Biquad_FLOAT_Instance_t* pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+#endif
/*
* Select single or double precision as required
*/
switch (pInstance->pBiquadType[i]) {
case LVEQNB_SinglePrecision_Float: {
+#ifdef BIQUAD_OPT
+ LVM_FLOAT* pTemp = pScratch + NrSamples;
+ pInstance->eqBiquad[i].process(pTemp, pScratch, NrFrames);
+ const auto gain = pInstance->gain[i];
+ for (unsigned j = 0; j < NrSamples; ++j) {
+ pScratch[j] += pTemp[j] * gain;
+ }
+#else
PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad, pScratch, pScratch,
(LVM_INT16)NrFrames,
(LVM_INT16)NrChannels);
+#endif
break;
}
default:
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
index 737ef01..be846eb 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ApplyNewSettings.cpp
@@ -20,6 +20,10 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVREV_Private.h"
#include "Filter.h"
@@ -71,10 +75,17 @@
Omega = LVM_GetOmega(pPrivate->NewParams.HPF, pPrivate->NewParams.SampleRate);
LVM_FO_HPF(Omega, &Coeffs);
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->HPCoefs, &pPrivate->pFastData->HPTaps,
&Coeffs);
LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->HPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
}
/*
@@ -99,10 +110,17 @@
LVM_FO_LPF(Omega, &Coeffs);
}
}
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->LPCoefs, &pPrivate->pFastData->LPTaps,
&Coeffs);
LoadConst_Float(0, (LVM_FLOAT*)&pPrivate->pFastData->LPTaps,
sizeof(Biquad_1I_Order1_FLOAT_Taps_t) / sizeof(LVM_FLOAT));
+#endif
}
/*
@@ -231,8 +249,15 @@
Coeffs.A1 = 0;
Coeffs.B1 = 0;
}
+#ifdef BIQUAD_OPT
+ const std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ Coeffs.A0, Coeffs.A1, 0.0, -(Coeffs.B1), 0.0};
+ pPrivate->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
FO_1I_D32F32Cll_TRC_WRA_01_Init(&pPrivate->pFastCoef->RevLPCoefs[i],
&pPrivate->pFastData->RevLPTaps[i], &Coeffs);
+#endif
}
}
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
index 5c83ce5..f542a2b 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_ClearAudioBuffers.cpp
@@ -56,13 +56,24 @@
* Clear all filter tap data, delay-lines and other signal related data
*/
+#ifdef BIQUAD_OPT
+ pLVREV_Private->pRevHPFBiquad->clear();
+ pLVREV_Private->pRevLPFBiquad->clear();
+#else
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->HPTaps, 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->LPTaps, 2);
+#endif
if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays == LVREV_DELAYLINES_4) {
+#ifdef BIQUAD_OPT
+ for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->revLPFBiquad[i]->clear();
+ }
+#else
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[3], 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[2], 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+#endif
LoadConst_Float(0, pLVREV_Private->pDelay_T[3], LVREV_MAX_T3_DELAY);
LoadConst_Float(0, pLVREV_Private->pDelay_T[2], LVREV_MAX_T2_DELAY);
@@ -71,15 +82,25 @@
}
if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_2) {
+#ifdef BIQUAD_OPT
+ for (int i = 0; i < LVREV_DELAYLINES_2; i++) {
+ pLVREV_Private->revLPFBiquad[i]->clear();
+ }
+#else
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[1], 2);
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+#endif
LoadConst_Float(0, pLVREV_Private->pDelay_T[1], LVREV_MAX_T1_DELAY);
LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
}
if ((LVM_UINT16)pLVREV_Private->InstanceParams.NumDelays >= LVREV_DELAYLINES_1) {
+#ifdef BIQUAD_OPT
+ pLVREV_Private->revLPFBiquad[0]->clear();
+#else
LoadConst_Float(0, (LVM_FLOAT*)&pLVREV_Private->pFastData->RevLPTaps[0], 2);
+#endif
LoadConst_Float(0, pLVREV_Private->pDelay_T[0], LVREV_MAX_T0_DELAY);
}
return LVREV_SUCCESS;
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
index b5db23b..6ed0605 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetInstanceHandle.cpp
@@ -134,9 +134,11 @@
/*
* Set the data, coefficient and temporary memory pointers
*/
+#ifndef BIQUAD_OPT
/* Fast data memory base address */
pLVREV_Private->pFastData =
(LVREV_FastData_st*)InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+#endif
if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
pLVREV_Private->pDelay_T[3] =
(LVM_FLOAT*)InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
@@ -194,9 +196,11 @@
pLVREV_Private->T[3] = LVREV_MAX_T3_DELAY;
pLVREV_Private->AB_Selection = 1; /* Select smoothing A to B */
+#ifndef BIQUAD_OPT
/* Fast coefficient memory base address */
pLVREV_Private->pFastCoef =
(LVREV_FastCoef_st*)InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
/* General purpose scratch */
pLVREV_Private->pScratch =
(LVM_FLOAT*)InstAlloc_AddMember(&Temporary, sizeof(LVM_FLOAT) * MaxBlockSize);
@@ -308,6 +312,17 @@
pLVREV_Private->A_DelaySize[3] = LVREV_MAX_AP3_DELAY;
pLVREV_Private->B_DelaySize[3] = LVREV_MAX_AP3_DELAY;
+#ifdef BIQUAD_OPT
+ pLVREV_Private->pRevHPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ pLVREV_Private->pRevLPFBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ for (int i = 0; i < LVREV_DELAYLINES_4; i++) {
+ pLVREV_Private->revLPFBiquad[i].reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(LVM_MAX_CHANNELS));
+ }
+#endif
+
LVREV_ClearAudioBuffers(*phInstance);
return LVREV_SUCCESS;
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
index 2c1e04d..e8b2019 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_GetMemoryTable.cpp
@@ -139,7 +139,9 @@
/*
* Persistent fast data memory
*/
+#ifndef BIQUAD_OPT
InstAlloc_AddMember(&FastData, sizeof(LVREV_FastData_st));
+#endif
if (pInstanceParams->NumDelays == LVREV_DELAYLINES_4) {
InstAlloc_AddMember(&FastData, LVREV_MAX_T3_DELAY * sizeof(LVM_FLOAT));
InstAlloc_AddMember(&FastData, LVREV_MAX_T2_DELAY * sizeof(LVM_FLOAT));
@@ -163,7 +165,9 @@
/*
* Persistent fast coefficient memory
*/
+#ifndef BIQUAD_OPT
InstAlloc_AddMember(&FastCoef, sizeof(LVREV_FastCoef_st));
+#endif
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&FastCoef);
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
index b6edb03..e52a1ca 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Private.h
@@ -23,6 +23,10 @@
/* Includes */
/* */
/****************************************************************************************/
+
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVREV.h"
#include "LVREV_Tables.h"
#include "BIQUAD.h"
@@ -101,12 +105,12 @@
/* */
/****************************************************************************************/
+#ifndef BIQUAD_OPT
/* Fast data structure */
typedef struct {
Biquad_1I_Order1_FLOAT_Taps_t HPTaps; /* High pass filter taps */
Biquad_1I_Order1_FLOAT_Taps_t LPTaps; /* Low pass filter taps */
Biquad_1I_Order1_FLOAT_Taps_t RevLPTaps[4]; /* Reverb low pass filters taps */
-
} LVREV_FastData_st;
/* Fast coefficient structure */
@@ -114,8 +118,9 @@
Biquad_FLOAT_Instance_t HPCoefs; /* High pass filter coefficients */
Biquad_FLOAT_Instance_t LPCoefs; /* Low pass filter coefficients */
Biquad_FLOAT_Instance_t RevLPCoefs[4]; /* Reverb low pass filters coefficients */
-
} LVREV_FastCoef_st;
+#endif
+
typedef struct {
/* General */
LVREV_InstanceParams_st InstanceParams; /* Initialisation time instance parameters */
@@ -134,8 +139,17 @@
processing */
/* Aligned memory pointers */
- LVREV_FastData_st* pFastData; /* Fast data memory base address */
- LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevHPFBiquad; /* Biquad filter instance for HPF */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevLPFBiquad; /* Biquad filter instance for LPF */
+ std::array<std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>, LVREV_DELAYLINES_4>
+ revLPFBiquad; /* Biquad filter instance for Reverb LPF */
+#else
+ LVREV_FastData_st* pFastData; /* Fast data memory base address */
+ LVREV_FastCoef_st* pFastCoef; /* Fast coefficient memory base address */
+#endif
LVM_FLOAT* pScratchDelayLine[4]; /* Delay line scratch memory */
LVM_FLOAT* pScratch; /* Multi ussge scratch */
LVM_FLOAT* pInputSave; /* Reverb block input save for dry/wet
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
index ed3b89c..e4f939f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.cpp
@@ -204,11 +204,20 @@
/*
* High pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->pRevHPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->HPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
+
/*
* Low pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->pRevLPFBiquad->process(pTemp, pTemp, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->LPCoefs, pTemp, pTemp, (LVM_INT16)NumSamples);
+#endif
/*
* Process all delay lines
@@ -253,8 +262,12 @@
/*
* Low pass filter
*/
+#ifdef BIQUAD_OPT
+ pPrivate->revLPFBiquad[j]->process(pDelayLine, pDelayLine, NumSamples);
+#else
FO_1I_D32F32C31_TRC_WRA_01(&pPrivate->pFastCoef->RevLPCoefs[j], pDelayLine, pDelayLine,
(LVM_INT16)NumSamples);
+#endif
}
/*
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
index bad9aef..a5952fb 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.cpp
@@ -21,6 +21,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_Equaliser.h"
@@ -56,14 +59,18 @@
LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficients;
BQ_FLOAT_Coefs_t Coeffs;
+#endif
const BiquadA012B12CoefsSP_t* pEqualiserCoefTable;
+#ifndef BIQUAD_OPT
pData = (LVCS_Data_t*)pInstance->pData;
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* If the sample rate changes re-initialise the filters
*/
@@ -75,6 +82,13 @@
Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1 + LVM_FS_48000)));
pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pEqualiserCoefTable[Offset].A0, pEqualiserCoefTable[Offset].A1,
+ pEqualiserCoefTable[Offset].A2, -(pEqualiserCoefTable[Offset].B1),
+ -(pEqualiserCoefTable[Offset].B2)};
+ pInstance->pEqBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
/* Left and right filters */
/* Convert incoming coefficients to the required format/ordering */
Coeffs.A0 = (LVM_FLOAT)pEqualiserCoefTable[Offset].A0;
@@ -103,6 +117,7 @@
pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
break;
}
+#endif
}
return (LVCS_SUCCESS);
@@ -129,19 +144,25 @@
LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance, LVM_FLOAT* pInputOutput,
LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_Equaliser_t* pConfig = (LVCS_Equaliser_t*)&pInstance->Equaliser;
LVCS_Coefficient_t* pCoefficients;
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* Check if the equaliser is required
*/
if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0) {
/* Apply filter to the left and right channels */
+#ifdef BIQUAD_OPT
+ pInstance->pEqBiquad->process(pInputOutput, pInputOutput, NumSamples);
+#else
(pConfig->pBiquadCallBack)(
(Biquad_FLOAT_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
(LVM_FLOAT*)pInputOutput, (LVM_FLOAT*)pInputOutput, (LVM_INT16)NumSamples);
+#endif
}
return (LVCS_SUCCESS);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
index 5c8f1ae..f23261f 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.cpp
@@ -123,6 +123,7 @@
if (pInstance == LVM_NULL) {
return;
}
+#ifndef BIQUAD_OPT
if (pInstance->pCoeff != LVM_NULL) {
free(pInstance->pCoeff);
pInstance->pCoeff = LVM_NULL;
@@ -131,6 +132,7 @@
free(pInstance->pData);
pInstance->pData = LVM_NULL;
}
+#endif
free(pInstance);
*phInstance = LVM_NULL;
return;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index f9c23b3..a150e90 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -33,6 +33,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <audio_utils/BiquadFilter.h>
+#endif
#include "LVCS.h" /* Calling or Application layer definitions */
#include "LVCS_StereoEnhancer.h" /* Stereo enhancer module definitions */
#include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
@@ -120,12 +123,24 @@
LVM_INT16 bTimerDone; /* Timer completion flag */
LVM_Timer_Params_t TimerParams; /* Timer parameters */
LVM_Timer_Instance_t TimerInstance; /* Timer instance */
+#ifdef BIQUAD_OPT
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pEqBiquad; /* Biquad filter instance for Equaliser */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pRevBiquad; /* Biquad filter instance for Reverberation */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSEMidBiquad; /* Biquad filter instance for Stereo enhancement mid */
+ std::unique_ptr<android::audio_utils::BiquadFilter<LVM_FLOAT>>
+ pSESideBiquad; /* Biquad filter instance for Stereo enhancement side */
+#else
void* pCoeff; /* pointer to buffer for equaliser filter coeffs */
void* pData; /* pointer to buffer for equaliser filter states */
+#endif
void* pScratch; /* Pointer to bundle scratch buffer */
} LVCS_Instance_t;
+#ifndef BIQUAD_OPT
/* Coefficient Structure */
typedef struct {
Biquad_FLOAT_Instance_t EqualiserBiquadInstance;
@@ -141,6 +156,7 @@
Biquad_1I_Order1_FLOAT_Taps_t SEBiquadTapsMid;
Biquad_1I_Order2_FLOAT_Taps_t SEBiquadTapsSide;
} LVCS_Data_t;
+#endif
void LVCS_TimerCallBack(void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam);
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
index f6d2453..82a3a43 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.cpp
@@ -20,6 +20,9 @@
/* Includes */
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include <stdlib.h>
#include "LVCS.h"
#include "LVCS_Private.h"
@@ -62,11 +65,14 @@
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficients;
BQ_FLOAT_Coefs_t Coeffs;
+#endif
const BiquadA012B12CoefsSP_t* pReverbCoefTable;
+#ifndef BIQUAD_OPT
if (pInstance->pData == LVM_NULL) {
pInstance->pData = pData = (LVCS_Data_t*)calloc(1, sizeof(*pData));
if (pData == LVM_NULL) {
@@ -83,6 +89,7 @@
} else {
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
}
+#endif
/*
* Initialise the delay and filters if:
@@ -109,6 +116,14 @@
Offset = (LVM_UINT16)pParams->SampleRate;
pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
+ pReverbCoefTable[Offset].A2, -(pReverbCoefTable[Offset].B1),
+ -(pReverbCoefTable[Offset].B2)};
+ pInstance->pRevBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_2, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
Coeffs.A0 = (LVM_FLOAT)pReverbCoefTable[Offset].A0;
Coeffs.A1 = (LVM_FLOAT)pReverbCoefTable[Offset].A1;
@@ -133,6 +148,7 @@
pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
break;
}
+#endif
/*
* Setup the mixer
@@ -190,10 +206,14 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
+#ifndef BIQUAD_OPT
LVCS_Coefficient_t* pCoefficients;
+#endif
LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
pCoefficients = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
@@ -233,9 +253,13 @@
/*
* Filter the data
*/
+#ifdef BIQUAD_OPT
+ pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
+#else
(pConfig->pBiquadCallBack)((Biquad_FLOAT_Instance_t*)&pCoefficients->ReverbBiquadInstance,
(LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch,
(LVM_INT16)NumSamples);
+#endif
Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
(LVM_INT16)(2 * NumSamples));
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
index ffa9c9b..0e488f5 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.cpp
@@ -21,6 +21,9 @@
/* */
/************************************************************************************/
+#ifdef BIQUAD_OPT
+#include <system/audio.h>
+#endif
#include "LVCS.h"
#include "LVCS_Private.h"
#include "LVCS_StereoEnhancer.h"
@@ -52,15 +55,19 @@
LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
LVM_UINT16 Offset;
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
+#ifndef BIQUAD_OPT
LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
LVCS_Data_t* pData;
LVCS_Coefficient_t* pCoefficient;
FO_FLOAT_Coefs_t CoeffsMid;
BQ_FLOAT_Coefs_t CoeffsSide;
+#endif
const BiquadA012B12CoefsSP_t* pSESideCoefs;
+#ifndef BIQUAD_OPT
pData = (LVCS_Data_t*)pInstance->pData;
pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
/*
* If the sample rate or speaker type has changed update the filters
@@ -73,6 +80,13 @@
/* Mid filter */
Offset = (LVM_UINT16)pParams->SampleRate;
+#ifdef BIQUAD_OPT
+ std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
+ LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
+ -(LVCS_SEMidCoefTable[Offset].B1), 0.0};
+ pInstance->pSEMidBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
CoeffsMid.A0 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A0;
CoeffsMid.A1 = (LVM_FLOAT)LVCS_SEMidCoefTable[Offset].A1;
@@ -91,11 +105,18 @@
if (LVCS_SEMidCoefTable[Offset].Scale == 15) {
pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
}
+#endif
Offset = (LVM_UINT16)(pParams->SampleRate);
pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
/* Side filter */
+#ifdef BIQUAD_OPT
+ coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
+ -(pSESideCoefs[Offset].B1), -(pSESideCoefs[Offset].B2)};
+ pInstance->pSESideBiquad.reset(
+ new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
+#else
/* Convert incoming coefficients to the required format/ordering */
CoeffsSide.A0 = (LVM_FLOAT)pSESideCoefs[Offset].A0;
CoeffsSide.A1 = (LVM_FLOAT)pSESideCoefs[Offset].A1;
@@ -123,6 +144,7 @@
pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
break;
}
+#endif
}
return (LVCS_SUCCESS);
@@ -169,9 +191,13 @@
LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
+#ifndef BIQUAD_OPT
LVCS_Coefficient_t* pCoefficient;
+#endif
LVM_FLOAT* pScratch;
+#ifndef BIQUAD_OPT
pCoefficient = (LVCS_Coefficient_t*)pInstance->pCoeff;
+#endif
pScratch = (LVM_FLOAT*)pInstance->pScratch;
/*
* Check if the Stereo Enhancer is enabled
@@ -186,9 +212,13 @@
* Apply filter to the middle signal
*/
if (pInstance->OutputDevice == LVCS_HEADPHONE) {
+#ifdef BIQUAD_OPT
+ pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
+#else
(pConfig->pBiquadCallBack_Mid)(
(Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
(LVM_FLOAT*)pScratch, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
+#endif
} else {
Mult3s_Float(pScratch, /* Source */
(LVM_FLOAT)pConfig->MidGain, /* Gain */
@@ -201,10 +231,15 @@
* and in all modes for mobile speakers
*/
if (pInstance->Params.SourceFormat == LVCS_STEREO) {
+#ifdef BIQUAD_OPT
+ pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
+ NumSamples);
+#else
(pConfig->pBiquadCallBack_Side)(
(Biquad_FLOAT_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
(LVM_FLOAT*)(pScratch + NumSamples), (LVM_FLOAT*)(pScratch + NumSamples),
(LVM_INT16)NumSamples);
+#endif
}
/*
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index d026ab6..abacc94 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -59,9 +59,12 @@
shared_libs: [
"libaudioutils",
"liblog",
- "libreverbwrapper",
],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
srcs: [
"reverb_test.cpp",
],
diff --git a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
index 86b21ae..627af21 100755
--- a/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
+++ b/media/libeffects/lvm/tests/build_and_run_all_unit_tests_reverb.sh
@@ -61,7 +61,7 @@
do
for chMask in {0..22}
do
- adb shell LD_LIBRARY_PATH=/system/vendor/lib/soundfx $testdir/reverb_test \
+ adb shell $testdir/reverb_test \
--input $testdir/sinesweepraw.raw \
--output $testdir/sinesweep_$((chMask))_$((fs)).raw \
--chMask $chMask $flags --fs $fs --preset $preset_val
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index be60aae..f96928b 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -38,7 +38,7 @@
}
// reverb wrapper
-cc_library_shared {
+cc_library {
name: "libreverbwrapper",
arch: {
diff --git a/media/utils/ServiceUtilities.cpp b/media/utils/ServiceUtilities.cpp
index 7699700..1b1717f 100644
--- a/media/utils/ServiceUtilities.cpp
+++ b/media/utils/ServiceUtilities.cpp
@@ -266,7 +266,7 @@
return NO_ERROR;
}
-sp<content::pm::IPackageManagerNative> MediaPackageManager::retreivePackageManager() {
+sp<content::pm::IPackageManagerNative> MediaPackageManager::retrievePackageManager() {
const sp<IServiceManager> sm = defaultServiceManager();
if (sm == nullptr) {
ALOGW("%s: failed to retrieve defaultServiceManager", __func__);
@@ -283,27 +283,27 @@
std::optional<bool> MediaPackageManager::doIsAllowed(uid_t uid) {
if (mPackageManager == nullptr) {
/** Can not fetch package manager at construction it may not yet be registered. */
- mPackageManager = retreivePackageManager();
+ mPackageManager = retrievePackageManager();
if (mPackageManager == nullptr) {
ALOGW("%s: Playback capture is denied as package manager is not reachable", __func__);
return std::nullopt;
}
}
+ // Retrieve package names for the UID and transform to a std::vector<std::string>.
+ Vector<String16> str16PackageNames;
+ PermissionController{}.getPackagesForUid(uid, str16PackageNames);
std::vector<std::string> packageNames;
- auto status = mPackageManager->getNamesForUids({(int32_t)uid}, &packageNames);
- if (!status.isOk()) {
- ALOGW("%s: Playback capture is denied for uid %u as the package names could not be "
- "retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
- return std::nullopt;
+ for (const auto& str16PackageName : str16PackageNames) {
+ packageNames.emplace_back(String8(str16PackageName).string());
}
if (packageNames.empty()) {
ALOGW("%s: Playback capture for uid %u is denied as no package name could be retrieved "
- "from the package manager: %s", __func__, uid, status.toString8().c_str());
+ "from the package manager.", __func__, uid);
return std::nullopt;
}
std::vector<bool> isAllowed;
- status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
+ auto status = mPackageManager->isAudioPlaybackCaptureAllowed(packageNames, &isAllowed);
if (!status.isOk()) {
ALOGW("%s: Playback capture is denied for uid %u as the manifest property could not be "
"retrieved from the package manager: %s", __func__, uid, status.toString8().c_str());
diff --git a/media/utils/include/mediautils/ServiceUtilities.h b/media/utils/include/mediautils/ServiceUtilities.h
index 431dd7a..c7d49fd 100644
--- a/media/utils/include/mediautils/ServiceUtilities.h
+++ b/media/utils/include/mediautils/ServiceUtilities.h
@@ -110,7 +110,7 @@
private:
static constexpr const char* nativePackageManagerName = "package_native";
std::optional<bool> doIsAllowed(uid_t uid);
- sp<content::pm::IPackageManagerNative> retreivePackageManager();
+ sp<content::pm::IPackageManagerNative> retrievePackageManager();
sp<content::pm::IPackageManagerNative> mPackageManager; // To check apps manifest
uint_t mPackageManagerErrors = 0;
struct Package {