Merge "Snap for 9982369 from 1494f05cc32165eef4c73a6eb6b51fe235bc1d64 to simpleperf-release" into simpleperf-release
diff --git a/apex/TEST_MAPPING b/apex/TEST_MAPPING
index 4b7c019..bb4f089 100644
--- a/apex/TEST_MAPPING
+++ b/apex/TEST_MAPPING
@@ -7,16 +7,16 @@
"presubmit": [
// The following tests validate codec and drm path.
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index b2d4d6e..a9b4b2a 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -2,16 +2,16 @@
"presubmit": [
// The following tests validate codec and drm path.
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
index bc004c8..ce4d730 100644
--- a/drm/libmediadrm/DrmMetricsLogger.cpp
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -41,49 +41,59 @@
DrmMetricsLogger::~DrmMetricsLogger() {}
-int MediaErrorToJavaError(status_t err) {
+int MediaErrorToEnum(status_t err) {
+#define ERROR_BAD_VALUE (BAD_VALUE)
+#define ERROR_DEAD_OBJECT (DEAD_OBJECT)
#define STATUS_CASE(status) \
- case status: \
- return J##status
+ case ERROR_##status: \
+ return ENUM_##status
switch (err) {
- STATUS_CASE(ERROR_DRM_UNKNOWN);
- STATUS_CASE(ERROR_DRM_NO_LICENSE);
- STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
- STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
- STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
- STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
- STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
- STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
- STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
- STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
- STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
- STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
- STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
- STATUS_CASE(ERROR_DRM_GENERIC_OEM);
- STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
- STATUS_CASE(ERROR_DRM_INIT_DATA);
- STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
- STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
- STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
- STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
- STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
- STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
- STATUS_CASE(ERROR_DRM_LICENSE_STATE);
- STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
- STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
- STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
- STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
- STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
- STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
- STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
- STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
- STATUS_CASE(ERROR_DRM_STORAGE_READ);
- STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
- STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+ STATUS_CASE(DRM_UNKNOWN);
+ STATUS_CASE(DRM_NO_LICENSE);
+ STATUS_CASE(DRM_LICENSE_EXPIRED);
+ STATUS_CASE(DRM_RESOURCE_BUSY);
+ STATUS_CASE(DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+ STATUS_CASE(DRM_SESSION_NOT_OPENED);
+ STATUS_CASE(DRM_CANNOT_HANDLE);
+ STATUS_CASE(DRM_INSUFFICIENT_SECURITY);
+ STATUS_CASE(DRM_FRAME_TOO_LARGE);
+ STATUS_CASE(DRM_SESSION_LOST_STATE);
+ STATUS_CASE(DRM_CERTIFICATE_MALFORMED);
+ STATUS_CASE(DRM_CERTIFICATE_MISSING);
+ STATUS_CASE(DRM_CRYPTO_LIBRARY);
+ STATUS_CASE(DRM_GENERIC_OEM);
+ STATUS_CASE(DRM_GENERIC_PLUGIN);
+ STATUS_CASE(DRM_INIT_DATA);
+ STATUS_CASE(DRM_KEY_NOT_LOADED);
+ STATUS_CASE(DRM_LICENSE_PARSE);
+ STATUS_CASE(DRM_LICENSE_POLICY);
+ STATUS_CASE(DRM_LICENSE_RELEASE);
+ STATUS_CASE(DRM_LICENSE_REQUEST_REJECTED);
+ STATUS_CASE(DRM_LICENSE_RESTORE);
+ STATUS_CASE(DRM_LICENSE_STATE);
+ STATUS_CASE(DRM_MEDIA_FRAMEWORK);
+ STATUS_CASE(DRM_PROVISIONING_CERTIFICATE);
+ STATUS_CASE(DRM_PROVISIONING_CONFIG);
+ STATUS_CASE(DRM_PROVISIONING_PARSE);
+ STATUS_CASE(DRM_PROVISIONING_REQUEST_REJECTED);
+ STATUS_CASE(DRM_PROVISIONING_RETRY);
+ STATUS_CASE(DRM_RESOURCE_CONTENTION);
+ STATUS_CASE(DRM_SECURE_STOP_RELEASE);
+ STATUS_CASE(DRM_STORAGE_READ);
+ STATUS_CASE(DRM_STORAGE_WRITE);
+ STATUS_CASE(DRM_ZERO_SUBSAMPLES);
+ STATUS_CASE(DRM_INVALID_STATE);
+ STATUS_CASE(BAD_VALUE);
+ STATUS_CASE(DRM_NOT_PROVISIONED);
+ STATUS_CASE(DRM_DEVICE_REVOKED);
+ STATUS_CASE(DRM_DECRYPT);
+ STATUS_CASE(DEAD_OBJECT);
+#undef ERROR_BAD_VALUE
+#undef ERROR_DEAD_OBJECT
#undef STATUS_CASE
}
- return static_cast<int>(err);
+ return ENUM_DRM_UNKNOWN;
}
int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
@@ -187,12 +197,12 @@
DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
std::vector<uint8_t> sid = toStdVec(sessionId);
- {
+ DrmStatus status = mImpl->closeSession(sessionId);
+ if (status == OK) {
const std::lock_guard<std::mutex> lock(mSessionMapMutex);
mSessionMap.erase(sid);
- }
- DrmStatus status = mImpl->closeSession(sessionId);
- if (status != OK) {
+ } else {
+ // TODO(b/275729711): reclaim sessions that failed to close
reportMediaDrmErrored(status, __func__, sid);
}
return status;
@@ -582,7 +592,7 @@
}
}
mediametrics_setCString(handle, "api", api);
- mediametrics_setInt32(handle, "error_code", MediaErrorToJavaError(error_code));
+ mediametrics_setInt32(handle, "error_code", MediaErrorToEnum(error_code));
mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
mediametrics_setInt32(handle, "error_context", error_code.getContext());
diff --git a/drm/libmediadrm/TEST_MAPPING b/drm/libmediadrm/TEST_MAPPING
index bc15879..8d7be22 100644
--- a/drm/libmediadrm/TEST_MAPPING
+++ b/drm/libmediadrm/TEST_MAPPING
@@ -1,19 +1,19 @@
{
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.MediaDrmTest"
+ "include-filter": "com.google.android.media.wvts.MediaDrmTest"
},
{
- "include-filter": "com.google.android.media.gts.WidevineDashPolicyTests"
+ "include-filter": "com.google.android.media.wvts.WidevineDashPolicyTests"
}
]
}
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
index 7666f04..e72f7f7 100644
--- a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -25,41 +25,49 @@
namespace android {
+// Keep enums in sync with frameworks/proto_logging/stats/enums/media/drm/enums.proto
+
enum {
- JERROR_DRM_UNKNOWN = 0,
- JERROR_DRM_NO_LICENSE = 1,
- JERROR_DRM_LICENSE_EXPIRED = 2,
- JERROR_DRM_RESOURCE_BUSY = 3,
- JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
- JERROR_DRM_SESSION_NOT_OPENED = 5,
- JERROR_DRM_CANNOT_HANDLE = 6,
- JERROR_DRM_INSUFFICIENT_SECURITY = 7,
- JERROR_DRM_FRAME_TOO_LARGE = 8,
- JERROR_DRM_SESSION_LOST_STATE = 9,
- JERROR_DRM_CERTIFICATE_MALFORMED = 10,
- JERROR_DRM_CERTIFICATE_MISSING = 11,
- JERROR_DRM_CRYPTO_LIBRARY = 12,
- JERROR_DRM_GENERIC_OEM = 13,
- JERROR_DRM_GENERIC_PLUGIN = 14,
- JERROR_DRM_INIT_DATA = 15,
- JERROR_DRM_KEY_NOT_LOADED = 16,
- JERROR_DRM_LICENSE_PARSE = 17,
- JERROR_DRM_LICENSE_POLICY = 18,
- JERROR_DRM_LICENSE_RELEASE = 19,
- JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
- JERROR_DRM_LICENSE_RESTORE = 21,
- JERROR_DRM_LICENSE_STATE = 22,
- JERROR_DRM_MEDIA_FRAMEWORK = 23,
- JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
- JERROR_DRM_PROVISIONING_CONFIG = 25,
- JERROR_DRM_PROVISIONING_PARSE = 26,
- JERROR_DRM_PROVISIONING_REQUEST_REJECTED = 27,
- JERROR_DRM_PROVISIONING_RETRY = 28,
- JERROR_DRM_RESOURCE_CONTENTION = 29,
- JERROR_DRM_SECURE_STOP_RELEASE = 30,
- JERROR_DRM_STORAGE_READ = 31,
- JERROR_DRM_STORAGE_WRITE = 32,
- JERROR_DRM_ZERO_SUBSAMPLES = 33,
+ ENUM_DRM_UNKNOWN = 0,
+ ENUM_DRM_NO_LICENSE = 1,
+ ENUM_DRM_LICENSE_EXPIRED = 2,
+ ENUM_DRM_RESOURCE_BUSY = 3,
+ ENUM_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+ ENUM_DRM_SESSION_NOT_OPENED = 5,
+ ENUM_DRM_CANNOT_HANDLE = 6,
+ ENUM_DRM_INSUFFICIENT_SECURITY = 7,
+ ENUM_DRM_FRAME_TOO_LARGE = 8,
+ ENUM_DRM_SESSION_LOST_STATE = 9,
+ ENUM_DRM_CERTIFICATE_MALFORMED = 10,
+ ENUM_DRM_CERTIFICATE_MISSING = 11,
+ ENUM_DRM_CRYPTO_LIBRARY = 12,
+ ENUM_DRM_GENERIC_OEM = 13,
+ ENUM_DRM_GENERIC_PLUGIN = 14,
+ ENUM_DRM_INIT_DATA = 15,
+ ENUM_DRM_KEY_NOT_LOADED = 16,
+ ENUM_DRM_LICENSE_PARSE = 17,
+ ENUM_DRM_LICENSE_POLICY = 18,
+ ENUM_DRM_LICENSE_RELEASE = 19,
+ ENUM_DRM_LICENSE_REQUEST_REJECTED = 20,
+ ENUM_DRM_LICENSE_RESTORE = 21,
+ ENUM_DRM_LICENSE_STATE = 22,
+ ENUM_DRM_MEDIA_FRAMEWORK = 23,
+ ENUM_DRM_PROVISIONING_CERTIFICATE = 24,
+ ENUM_DRM_PROVISIONING_CONFIG = 25,
+ ENUM_DRM_PROVISIONING_PARSE = 26,
+ ENUM_DRM_PROVISIONING_REQUEST_REJECTED = 27,
+ ENUM_DRM_PROVISIONING_RETRY = 28,
+ ENUM_DRM_RESOURCE_CONTENTION = 29,
+ ENUM_DRM_SECURE_STOP_RELEASE = 30,
+ ENUM_DRM_STORAGE_READ = 31,
+ ENUM_DRM_STORAGE_WRITE = 32,
+ ENUM_DRM_ZERO_SUBSAMPLES = 33,
+ ENUM_DRM_INVALID_STATE = 34,
+ ENUM_BAD_VALUE = 35,
+ ENUM_DRM_NOT_PROVISIONED = 36,
+ ENUM_DRM_DEVICE_REVOKED = 37,
+ ENUM_DRM_DECRYPT = 38,
+ ENUM_DEAD_OBJECT = 39,
};
enum {
diff --git a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
deleted file mode 100644
index e03a896..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/AesCtrDecryptor.cpp
+++ /dev/null
@@ -1,86 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearkeyDecryptor"
-#include <utils/Log.h>
-
-#include <openssl/aes.h>
-
-#include "AesCtrDecryptor.h"
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::SubSample;
-using ::android::hardware::drm::V1_0::Status;
-
-static const size_t kBlockBitCount = kBlockSize * 8;
-
-Status AesCtrDecryptor::decrypt(
- const std::vector<uint8_t>& key,
- const Iv iv, const uint8_t* source,
- uint8_t* destination,
- const std::vector<SubSample> subSamples,
- size_t numSubSamples,
- size_t* bytesDecryptedOut) {
- uint32_t blockOffset = 0;
- uint8_t previousEncryptedCounter[kBlockSize];
- memset(previousEncryptedCounter, 0, kBlockSize);
-
- if (key.size() != kBlockSize || (sizeof(Iv) / sizeof(uint8_t)) != kBlockSize) {
- android_errorWriteLog(0x534e4554, "63982768");
- return Status::ERROR_DRM_DECRYPT;
- }
-
- size_t offset = 0;
- AES_KEY opensslKey;
- AES_set_encrypt_key(key.data(), kBlockBitCount, &opensslKey);
- Iv opensslIv;
- memcpy(opensslIv, iv, sizeof(opensslIv));
-
- for (size_t i = 0; i < numSubSamples; ++i) {
- const SubSample& subSample = subSamples[i];
-
- if (subSample.numBytesOfClearData > 0) {
- memcpy(destination + offset, source + offset,
- subSample.numBytesOfClearData);
- offset += subSample.numBytesOfClearData;
- }
-
- if (subSample.numBytesOfEncryptedData > 0) {
- AES_ctr128_encrypt(source + offset, destination + offset,
- subSample.numBytesOfEncryptedData, &opensslKey,
- opensslIv, previousEncryptedCounter,
- &blockOffset);
- offset += subSample.numBytesOfEncryptedData;
- }
- }
-
- *bytesDecryptedOut = offset;
- return Status::OK;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Android.bp b/drm/mediadrm/plugins/clearkey/hidl/Android.bp
deleted file mode 100644
index b82d996..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Android.bp
+++ /dev/null
@@ -1,167 +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.
-//
-
-// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE
-// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
-// DEPENDING ON IT IN YOUR PROJECT. ***
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_av_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // legacy_by_exception_only (by exception only)
- default_applicable_licenses: ["frameworks_av_license"],
-}
-
-cc_defaults {
- name: "clearkey_service_defaults",
- vendor: true,
-
- srcs: [
- "AesCtrDecryptor.cpp",
- "Base64.cpp",
- "Buffer.cpp",
- "CreatePluginFactories.cpp",
- "CryptoFactory.cpp",
- "CryptoPlugin.cpp",
- "DeviceFiles.cpp",
- "DrmFactory.cpp",
- "DrmPlugin.cpp",
- "InitDataParser.cpp",
- "JsonWebKey.cpp",
- "MemoryFileSystem.cpp",
- "Session.cpp",
- "SessionLibrary.cpp",
- ],
-
- relative_install_path: "hw",
-
- cflags: ["-Wall", "-Werror", "-Wthread-safety"],
-
- shared_libs: [
- "android.hardware.drm@1.0",
- "android.hardware.drm@1.1",
- "android.hardware.drm@1.2",
- "android.hardware.drm@1.3",
- "android.hardware.drm@1.4",
- "libbase",
- "libbinder",
- "libcrypto",
- "libhidlbase",
- "libhidlmemory",
- "liblog",
- "libprotobuf-cpp-lite",
- "libutils",
- ],
-
- static_libs: [
- "libclearkeycommon",
- "libclearkeydevicefiles-protos",
- "libjsmn",
- ],
-
- local_include_dirs: ["include"],
-
- export_static_lib_headers: ["libjsmn"],
-
- sanitize: {
- integer_overflow: true,
- },
-}
-cc_library_static {
- name: "libclearkeydevicefiles-protos",
- vendor: true,
-
- proto: {
- export_proto_headers: true,
- type: "lite",
- },
- srcs: ["protos/DeviceFiles.proto"],
-}
-
-cc_library {
- name: "libclearkeyhidl",
- defaults: ["clearkey_service_defaults"],
-}
-
-cc_binary {
- name: "android.hardware.drm@1.2-service.clearkey",
- defaults: ["clearkey_service_defaults"],
- srcs: ["service.cpp"],
- init_rc: ["android.hardware.drm@1.2-service.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
-}
-
-cc_binary {
- name: "android.hardware.drm@1.2-service-lazy.clearkey",
- overrides: ["android.hardware.drm@1.2-service.clearkey"],
- defaults: ["clearkey_service_defaults"],
- srcs: ["serviceLazy.cpp"],
- init_rc: ["android.hardware.drm@1.2-service-lazy.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.2-service.clearkey.xml"],
-}
-
-cc_binary {
- name: "android.hardware.drm@1.4-service.clearkey",
- defaults: ["clearkey_service_defaults"],
- srcs: ["service.cpp"],
- init_rc: ["android.hardware.drm@1.4-service.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
-}
-
-cc_binary {
- name: "android.hardware.drm@1.4-service-lazy.clearkey",
- overrides: ["android.hardware.drm@1.4-service.clearkey"],
- defaults: ["clearkey_service_defaults"],
- srcs: ["serviceLazy.cpp"],
- init_rc: ["android.hardware.drm@1.4-service-lazy.clearkey.rc"],
- vintf_fragments: ["manifest_android.hardware.drm@1.4-service.clearkey.xml"],
-}
-
-cc_fuzz {
- name: "clearkeyV1.4_fuzzer",
- vendor: true,
- srcs: [
- "fuzzer/clearkeyV1.4_fuzzer.cpp",
- ],
- static_libs: [
- "libclearkeyhidl",
- "libclearkeycommon",
- "libclearkeydevicefiles-protos",
- "libjsmn",
- "libprotobuf-cpp-lite",
- ],
- shared_libs: [
- "android.hidl.allocator@1.0",
- "android.hardware.drm@1.0",
- "android.hardware.drm@1.1",
- "android.hardware.drm@1.2",
- "android.hardware.drm@1.3",
- "android.hardware.drm@1.4",
- "libcrypto",
- "libhidlbase",
- "libhidlmemory",
- "liblog",
- "libutils",
- ],
- fuzz_config: {
- cc: [
- "android-media-fuzzing-reports@google.com",
- ],
- componentid: 155276,
- },
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp b/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
deleted file mode 100644
index d81f875..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Base64.cpp
+++ /dev/null
@@ -1,175 +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.
- */
-
-#include "Base64.h"
-
-#include <string>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-sp<Buffer> decodeBase64(const std::string &s) {
- size_t n = s.size();
-
- if ((n % 4) != 0) {
- return nullptr;
- }
-
- size_t padding = 0;
- if (n >= 1 && s.c_str()[n - 1] == '=') {
- padding = 1;
-
- if (n >= 2 && s.c_str()[n - 2] == '=') {
- padding = 2;
-
- if (n >= 3 && s.c_str()[n - 3] == '=') {
- padding = 3;
- }
- }
- }
-
- // We divide first to avoid overflow. It's OK to do this because we
- // already made sure that n % 4 == 0.
- size_t outLen = (n / 4) * 3 - padding;
-
- sp<Buffer> buffer = new Buffer(outLen);
- uint8_t *out = buffer->data();
- if (out == nullptr || buffer->size() < outLen) {
- return nullptr;
- }
-
- size_t j = 0;
- uint32_t accum = 0;
- for (size_t i = 0; i < n; ++i) {
- char c = s.c_str()[i];
- unsigned value;
- if (c >= 'A' && c <= 'Z') {
- value = c - 'A';
- } else if (c >= 'a' && c <= 'z') {
- value = 26 + c - 'a';
- } else if (c >= '0' && c <= '9') {
- value = 52 + c - '0';
- } else if (c == '+' || c == '-') {
- value = 62;
- } else if (c == '/' || c == '_') {
- value = 63;
- } else if (c != '=') {
- return nullptr;
- } else {
- if (i < n - padding) {
- return nullptr;
- }
-
- value = 0;
- }
-
- accum = (accum << 6) | value;
-
- if (((i + 1) % 4) == 0) {
- if (j < outLen) { out[j++] = (accum >> 16); }
- if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
- if (j < outLen) { out[j++] = accum & 0xff; }
-
- accum = 0;
- }
- }
-
- return buffer;
-}
-
-static char encode6Bit(unsigned x) {
- if (x <= 25) {
- return 'A' + x;
- } else if (x <= 51) {
- return 'a' + x - 26;
- } else if (x <= 61) {
- return '0' + x - 52;
- } else if (x == 62) {
- return '+';
- } else {
- return '/';
- }
-}
-
-void encodeBase64(const void *_data, size_t size, std::string *out) {
- out->clear();
-
- const uint8_t *data = (const uint8_t *)_data;
-
- size_t i;
- for (i = 0; i < (size / 3) * 3; i += 3) {
- uint8_t x1 = data[i];
- uint8_t x2 = data[i + 1];
- uint8_t x3 = data[i + 2];
-
- out->push_back(encode6Bit(x1 >> 2));
- out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
- out->push_back(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
- out->push_back(encode6Bit(x3 & 0x3f));
- }
- switch (size % 3) {
- case 0:
- break;
- case 2:
- {
- uint8_t x1 = data[i];
- uint8_t x2 = data[i + 1];
- out->push_back(encode6Bit(x1 >> 2));
- out->push_back(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
- out->push_back(encode6Bit((x2 << 2) & 0x3f));
- out->push_back('=');
- break;
- }
- default:
- {
- uint8_t x1 = data[i];
- out->push_back(encode6Bit(x1 >> 2));
- out->push_back(encode6Bit((x1 << 4) & 0x3f));
- out->append("==");
- break;
- }
- }
-}
-
-void encodeBase64Url(const void *_data, size_t size, std::string *out) {
- encodeBase64(_data, size, out);
-
- if ((std::string::npos != out->find("+")) ||
- (std::string::npos != out->find("/"))) {
- size_t outLen = out->size();
- char *base64url = new char[outLen];
- for (size_t i = 0; i < outLen; ++i) {
- if (out->c_str()[i] == '+')
- base64url[i] = '-';
- else if (out->c_str()[i] == '/')
- base64url[i] = '_';
- else
- base64url[i] = out->c_str()[i];
- }
-
- out->assign(base64url, outLen);
- delete[] base64url;
- }
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp b/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
deleted file mode 100644
index dcb76f4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Buffer.cpp
+++ /dev/null
@@ -1,53 +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.
- */
-
-#include "Buffer.h"
-
-#include <android/hardware/drm/1.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-Buffer::Buffer(size_t capacity)
- : mRangeOffset(0),
- mOwnsData(true) {
- mData = malloc(capacity);
- if (mData == nullptr) {
- mCapacity = 0;
- mRangeLength = 0;
- } else {
- mCapacity = capacity;
- mRangeLength = capacity;
- }
-}
-
-Buffer::~Buffer() {
- if (mOwnsData) {
- if (mData != nullptr) {
- free(mData);
- mData = nullptr;
- }
- }
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp b/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
deleted file mode 100644
index 4ab33d3..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CreatePluginFactories.cpp
+++ /dev/null
@@ -1,44 +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.
- */
-
-#include "CreatePluginFactories.h"
-
-#include "CryptoFactory.h"
-#include "DrmFactory.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-extern "C" {
-
-IDrmFactory* createDrmFactory() {
- return new DrmFactory();
-}
-
-ICryptoFactory* createCryptoFactory() {
- return new CryptoFactory();
-}
-
-} // extern "C"
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
deleted file mode 100644
index 0bebc3b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoFactory.cpp
+++ /dev/null
@@ -1,70 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyCryptoFactory"
-#include <utils/Log.h>
-
-#include "CryptoFactory.h"
-
-#include "ClearKeyUUID.h"
-#include "CryptoPlugin.h"
-#include "TypeConvert.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_4::clearkey::CryptoPlugin;
-
-Return<bool> CryptoFactory::isCryptoSchemeSupported(
- const hidl_array<uint8_t, 16> &uuid)
-{
- return clearkeydrm::isClearKeyUUID(uuid.data());
-}
-
-Return<void> CryptoFactory::createPlugin(
- const hidl_array<uint8_t, 16> &uuid,
- const hidl_vec<uint8_t> &initData,
- createPlugin_cb _hidl_cb) {
-
- if (!isCryptoSchemeSupported(uuid.data())) {
- ALOGE("Clearkey Drm HAL: failed to create clearkey plugin, " \
- "invalid crypto scheme");
- _hidl_cb(Status::BAD_VALUE, nullptr);
- return Void();
- }
-
- CryptoPlugin *cryptoPlugin = new CryptoPlugin(initData);
- Status status = cryptoPlugin->getInitStatus();
- if (status == Status::OK) {
- _hidl_cb(Status::OK, cryptoPlugin);
- } else {
- delete cryptoPlugin;
- _hidl_cb(status, nullptr);
- }
- return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
deleted file mode 100644
index 64a43b0..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ /dev/null
@@ -1,266 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyCryptoPlugin"
-#include <utils/Log.h>
-
-#include "CryptoPlugin.h"
-#include "SessionLibrary.h"
-#include "TypeConvert.h"
-
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::BufferType;
-
-Return<void> CryptoPlugin::setSharedBufferBase(
- const hidl_memory& base, uint32_t bufferId) {
- sp<IMemory> hidlMemory = mapMemory(base);
- ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
-
- std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
-
- // allow mapMemory to return nullptr
- mSharedBufferMap[bufferId] = hidlMemory;
- return Void();
-}
-
-Return<void> CryptoPlugin::decrypt(
- bool secure,
- const hidl_array<uint8_t, 16>& keyId,
- const hidl_array<uint8_t, 16>& iv,
- Mode mode,
- const Pattern& pattern,
- const hidl_vec<SubSample>& subSamples,
- const SharedBuffer& source,
- uint64_t offset,
- const DestinationBuffer& destination,
- decrypt_cb _hidl_cb) {
-
- Status status = Status::ERROR_DRM_UNKNOWN;
- hidl_string detailedError;
- uint32_t bytesWritten = 0;
-
- Return<void> hResult = decrypt_1_2(
- secure, keyId, iv, mode, pattern, subSamples, source, offset, destination,
- [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) {
- status = toStatus_1_0(hStatus);
- bytesWritten = hBytesWritten;
- detailedError = hDetailedError;
- }
- );
-
- status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE;
- _hidl_cb(status, bytesWritten, detailedError);
- return Void();
-}
-
-// Returns negative values for error code and positive values for the size of
-// decrypted data. In theory, the output size can be larger than the input
-// size, but in practice this will never happen for AES-CTR.
-Return<void> CryptoPlugin::decrypt_1_2(
- bool secure,
- const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
- const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
- Mode mode,
- const Pattern& pattern,
- const hidl_vec<SubSample>& subSamples,
- const SharedBuffer& source,
- uint64_t offset,
- const DestinationBuffer& destination,
- decrypt_1_2_cb _hidl_cb) {
- UNUSED(pattern);
-
- if (secure) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "Secure decryption is not supported with ClearKey.");
- return Void();
- }
-
- std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
- if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "source decrypt buffer base not set");
- return Void();
- }
-
- if (destination.type == BufferType::SHARED_MEMORY) {
- const SharedBuffer& dest = destination.nonsecureMemory;
- if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "destination decrypt buffer base not set");
- return Void();
- }
- } else {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "destination type not supported");
- return Void();
- }
-
- sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
- if (sourceBase == nullptr) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
- return Void();
- }
-
- size_t totalSize = 0;
- if (__builtin_add_overflow(source.offset, offset, &totalSize) ||
- __builtin_add_overflow(totalSize, source.size, &totalSize) ||
- totalSize > sourceBase->getSize()) {
- android_errorWriteLog(0x534e4554, "176496160");
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
- return Void();
- }
-
- uint8_t *base = static_cast<uint8_t *>
- (static_cast<void *>(sourceBase->getPointer()));
- uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
- void* destPtr = NULL;
- // destination.type == BufferType::SHARED_MEMORY
- const SharedBuffer& destBuffer = destination.nonsecureMemory;
- sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
- if (destBase == nullptr) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
- return Void();
- }
-
- base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
-
- totalSize = 0;
- if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
- totalSize > destBase->getSize()) {
- android_errorWriteLog(0x534e4554, "176444622");
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "invalid buffer size");
- return Void();
- }
- destPtr = static_cast<void*>(base + destination.nonsecureMemory.offset);
-
- // release mSharedBufferLock
- shared_buffer_lock.unlock();
-
- // Calculate the output buffer size and determine if any subsamples are
- // encrypted.
- size_t destSize = 0;
- size_t srcSize = 0;
- bool haveEncryptedSubsamples = false;
- for (size_t i = 0; i < subSamples.size(); i++) {
- const SubSample &subSample = subSamples[i];
- if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize) ||
- __builtin_add_overflow(srcSize, subSample.numBytesOfClearData, &srcSize)) {
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample clear size overflow");
- return Void();
- }
- if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize) ||
- __builtin_add_overflow(srcSize, subSample.numBytesOfEncryptedData, &srcSize)) {
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample encrypted size overflow");
- return Void();
- }
- if (subSample.numBytesOfEncryptedData > 0) {
- haveEncryptedSubsamples = true;
- }
- }
-
- if (destSize > destBuffer.size || srcSize > source.size) {
- _hidl_cb(Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE, 0, "subsample sum too large");
- return Void();
- }
-
- if (mode == Mode::UNENCRYPTED) {
- if (haveEncryptedSubsamples) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "Encrypted subsamples found in allegedly unencrypted data.");
- return Void();
- }
-
- size_t offset = 0;
- for (size_t i = 0; i < subSamples.size(); ++i) {
- const SubSample& subSample = subSamples[i];
- if (subSample.numBytesOfClearData != 0) {
- memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
- reinterpret_cast<const uint8_t*>(srcPtr) + offset,
- subSample.numBytesOfClearData);
- offset += subSample.numBytesOfClearData;
- }
- }
-
- _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(offset), "");
- return Void();
- } else if (mode == Mode::AES_CTR) {
- size_t bytesDecrypted;
- if (keyId.size() != kBlockSize || iv.size() != kBlockSize) {
- android_errorWriteLog(0x534e4554, "244569759");
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid decrypt parameter size");
- return Void();
- }
- if (!mSession) {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "session not found");
- return Void();
- }
- Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
- static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
- if (res == Status_V1_2::OK) {
- _hidl_cb(Status_V1_2::OK, static_cast<ssize_t>(bytesDecrypted), "");
- return Void();
- } else {
- _hidl_cb(res, 0, "Decryption Error");
- return Void();
- }
- } else {
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0,
- "Selected encryption mode is not supported by the ClearKey DRM Plugin.");
- return Void();
- }
-}
-
-Return<Status> CryptoPlugin::setMediaDrmSession(
- const hidl_vec<uint8_t>& sessionId) {
- if (!sessionId.size()) {
- mSession = nullptr;
- } else {
- mSession = SessionLibrary::get()->findSession(sessionId);
- if (!mSession.get()) {
- return Status::ERROR_DRM_SESSION_NOT_OPENED;
- }
- }
- return Status::OK;
-}
-
-Return<void> CryptoPlugin::getLogMessages(
- getLogMessages_cb _hidl_cb) {
- using std::chrono::duration_cast;
- using std::chrono::milliseconds;
- using std::chrono::system_clock;
-
- auto timeMillis = duration_cast<milliseconds>(
- system_clock::now().time_since_epoch()).count();
-
- std::vector<LogMessage> logs = {
- { timeMillis, LogPriority::ERROR, std::string("Not implemented") }};
- _hidl_cb(drm::V1_4::Status::OK, toHidlVec(logs));
- return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4.
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp b/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
deleted file mode 100644
index 0385d8f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DeviceFiles.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-
-#include <utils/Log.h>
-
-#include <string>
-#include <sys/stat.h>
-
-#include "DeviceFiles.h"
-#include "Utils.h"
-
-#include <openssl/sha.h>
-
-// Protobuf generated classes.
-using android::hardware::drm::V1_2::clearkey::OfflineFile;
-using android::hardware::drm::V1_2::clearkey::HashedFile;
-using android::hardware::drm::V1_2::clearkey::License;
-using android::hardware::drm::V1_2::clearkey::License_LicenseState_ACTIVE;
-using android::hardware::drm::V1_2::clearkey::License_LicenseState_RELEASING;
-
-namespace {
-const char kLicenseFileNameExt[] = ".lic";
-
-bool Hash(const std::string& data, std::string* hash) {
- if (!hash) return false;
-
- hash->resize(SHA256_DIGEST_LENGTH);
-
- const unsigned char* input = reinterpret_cast<const unsigned char*>(data.data());
- unsigned char* output = reinterpret_cast<unsigned char*>(&(*hash)[0]);
- SHA256(input, data.size(), output);
- return true;
-}
-
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-bool DeviceFiles::StoreLicense(
- const std::string& keySetId, LicenseState state,
- const std::string& licenseResponse) {
-
- OfflineFile file;
- file.set_type(OfflineFile::LICENSE);
- file.set_version(OfflineFile::VERSION_1);
-
- License* license = file.mutable_license();
- switch (state) {
- case kLicenseStateActive:
- license->set_state(License_LicenseState_ACTIVE);
- license->set_license(licenseResponse);
- break;
- case kLicenseStateReleasing:
- license->set_state(License_LicenseState_RELEASING);
- license->set_license(licenseResponse);
- break;
- default:
- ALOGW("StoreLicense: Unknown license state: %u", state);
- return false;
- }
-
- std::string serializedFile;
- file.SerializeToString(&serializedFile);
-
- return StoreFileWithHash(keySetId + kLicenseFileNameExt, serializedFile);
-}
-
-bool DeviceFiles::StoreFileWithHash(const std::string& fileName,
- const std::string& serializedFile) {
- std::string hash;
- if (!Hash(serializedFile, &hash)) {
- ALOGE("StoreFileWithHash: Failed to compute hash");
- return false;
- }
-
- HashedFile hashFile;
- hashFile.set_file(serializedFile);
- hashFile.set_hash(hash);
-
- std::string serializedHashFile;
- hashFile.SerializeToString(&serializedHashFile);
-
- return StoreFileRaw(fileName, serializedHashFile);
-}
-
-bool DeviceFiles::StoreFileRaw(const std::string& fileName, const std::string& serializedHashFile) {
- MemoryFileSystem::MemoryFile memFile;
- memFile.setFileName(fileName);
- memFile.setContent(serializedHashFile);
- memFile.setFileSize(serializedHashFile.size());
- size_t len = mFileHandle.Write(fileName, memFile);
-
- if (len != static_cast<size_t>(serializedHashFile.size())) {
- ALOGE("StoreFileRaw: Failed to write %s", fileName.c_str());
- ALOGD("StoreFileRaw: expected=%zd, actual=%zu", serializedHashFile.size(), len);
- return false;
- }
-
- ALOGD("StoreFileRaw: wrote %zu bytes to %s", serializedHashFile.size(), fileName.c_str());
- return true;
-}
-
-bool DeviceFiles::RetrieveLicense(
- const std::string& keySetId, LicenseState* state, std::string* offlineLicense) {
-
- OfflineFile file;
- if (!RetrieveHashedFile(keySetId + kLicenseFileNameExt, &file)) {
- return false;
- }
-
- if (file.type() != OfflineFile::LICENSE) {
- ALOGE("RetrieveLicense: Invalid file type");
- return false;
- }
-
- if (file.version() != OfflineFile::VERSION_1) {
- ALOGE("RetrieveLicense: Invalid file version");
- return false;
- }
-
- if (!file.has_license()) {
- ALOGE("RetrieveLicense: License not present");
- return false;
- }
-
- License license = file.license();
- switch (license.state()) {
- case License_LicenseState_ACTIVE:
- *state = kLicenseStateActive;
- break;
- case License_LicenseState_RELEASING:
- *state = kLicenseStateReleasing;
- break;
- default:
- ALOGW("RetrieveLicense: Unrecognized license state: %u",
- kLicenseStateUnknown);
- *state = kLicenseStateUnknown;
- break;
- }
- *offlineLicense = license.license();
- return true;
-}
-
-bool DeviceFiles::DeleteLicense(const std::string& keySetId) {
- return mFileHandle.RemoveFile(keySetId + kLicenseFileNameExt);
-}
-
-bool DeviceFiles::DeleteAllLicenses() {
- return mFileHandle.RemoveAllFiles();
-}
-
-bool DeviceFiles::LicenseExists(const std::string& keySetId) {
- return mFileHandle.FileExists(keySetId + kLicenseFileNameExt);
-}
-
-std::vector<std::string> DeviceFiles::ListLicenses() const {
- std::vector<std::string> licenses = mFileHandle.ListFiles();
- for (size_t i = 0; i < licenses.size(); i++) {
- std::string& license = licenses[i];
- license = license.substr(0, license.size() - strlen(kLicenseFileNameExt));
- }
- return licenses;
-}
-
-bool DeviceFiles::RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile) {
- if (!deSerializedFile) {
- ALOGE("RetrieveHashedFile: invalid file parameter");
- return false;
- }
-
- if (!FileExists(fileName)) {
- ALOGE("RetrieveHashedFile: %s does not exist", fileName.c_str());
- return false;
- }
-
- ssize_t bytes = GetFileSize(fileName);
- if (bytes <= 0) {
- ALOGE("RetrieveHashedFile: invalid file size: %s", fileName.c_str());
- // Remove the corrupted file so the caller will not get the same error
- // when trying to access the file repeatedly, causing the system to stall.
- RemoveFile(fileName);
- return false;
- }
-
- std::string serializedHashFile;
- serializedHashFile.resize(bytes);
- bytes = mFileHandle.Read(fileName, &serializedHashFile);
-
- if (bytes != static_cast<ssize_t>(serializedHashFile.size())) {
- ALOGE("RetrieveHashedFile: Failed to read from %s", fileName.c_str());
- ALOGV("RetrieveHashedFile: expected: %zd, actual: %zd", serializedHashFile.size(), bytes);
- // Remove the corrupted file so the caller will not get the same error
- // when trying to access the file repeatedly, causing the system to stall.
- RemoveFile(fileName);
- return false;
- }
-
- ALOGV("RetrieveHashedFile: read %zd from %s", bytes, fileName.c_str());
-
- HashedFile hashFile;
- if (!hashFile.ParseFromString(serializedHashFile)) {
- ALOGE("RetrieveHashedFile: Unable to parse hash file");
- // Remove corrupt file.
- RemoveFile(fileName);
- return false;
- }
-
- std::string hash;
- if (!Hash(hashFile.file(), &hash)) {
- ALOGE("RetrieveHashedFile: Hash computation failed");
- return false;
- }
-
- if (hash != hashFile.hash()) {
- ALOGE("RetrieveHashedFile: Hash mismatch");
- // Remove corrupt file.
- RemoveFile(fileName);
- return false;
- }
-
- if (!deSerializedFile->ParseFromString(hashFile.file())) {
- ALOGE("RetrieveHashedFile: Unable to parse file");
- // Remove corrupt file.
- RemoveFile(fileName);
- return false;
- }
-
- return true;
-}
-
-bool DeviceFiles::FileExists(const std::string& fileName) const {
- return mFileHandle.FileExists(fileName);
-}
-
-bool DeviceFiles::RemoveFile(const std::string& fileName) {
- return mFileHandle.RemoveFile(fileName);
-}
-
-ssize_t DeviceFiles::GetFileSize(const std::string& fileName) const {
- return mFileHandle.GetFileSize(fileName);
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
deleted file mode 100644
index 14cb5c1..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmFactory.cpp
+++ /dev/null
@@ -1,111 +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.
- */
-
-//#define LOG_NDEBUG 0
-#include <vector>
-#define LOG_TAG "hidl_ClearKeyDrmFactory"
-#include <utils/Log.h>
-
-#include <utils/Errors.h>
-
-#include "DrmFactory.h"
-
-#include "DrmPlugin.h"
-#include "ClearKeyUUID.h"
-#include "MimeType.h"
-#include "SessionLibrary.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::drm::V1_4::clearkey::DrmPlugin;
-using ::android::hardware::drm::V1_4::clearkey::SessionLibrary;
-using ::android::hardware::Void;
-
-Return<bool> DrmFactory::isCryptoSchemeSupported(
- const hidl_array<uint8_t, 16>& uuid) {
- return clearkeydrm::isClearKeyUUID(uuid.data());
-}
-
-Return<bool> DrmFactory::isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid,
- const hidl_string &mimeType,
- SecurityLevel level) {
- return isCryptoSchemeSupported(uuid) && isContentTypeSupported(mimeType) &&
- level == SecurityLevel::SW_SECURE_CRYPTO;
-}
-
-Return<bool> DrmFactory::isContentTypeSupported(const hidl_string &mimeType) {
- // This should match the mimeTypes handed by InitDataParser.
- return mimeType == kIsoBmffVideoMimeType ||
- mimeType == kIsoBmffAudioMimeType ||
- mimeType == kCencInitDataFormat ||
- mimeType == kWebmVideoMimeType ||
- mimeType == kWebmAudioMimeType ||
- mimeType == kWebmInitDataFormat;
-}
-
-Return<void> DrmFactory::createPlugin(
- const hidl_array<uint8_t, 16>& uuid,
- const hidl_string& appPackageName,
- createPlugin_cb _hidl_cb) {
- UNUSED(appPackageName);
-
- DrmPlugin *plugin = NULL;
- if (!isCryptoSchemeSupported(uuid.data())) {
- ALOGE("Clear key Drm HAL: failed to create drm plugin, " \
- "invalid crypto scheme");
- _hidl_cb(Status::BAD_VALUE, plugin);
- return Void();
- }
-
- plugin = new DrmPlugin(SessionLibrary::get());
- _hidl_cb(Status::OK, plugin);
- return Void();
-}
-
-Return<void> DrmFactory::getSupportedCryptoSchemes(
- getSupportedCryptoSchemes_cb _hidl_cb) {
- std::vector<hidl_array<uint8_t, 16>> schemes;
- for (const auto &scheme : clearkeydrm::getSupportedCryptoSchemes()) {
- schemes.push_back(scheme);
- }
- _hidl_cb(schemes);
- return Void();
-}
-
-Return<void> DrmFactory::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /*args*/) {
- if (fd.getNativeHandle() == nullptr || fd->numFds < 1) {
- ALOGE("%s: missing fd for writing", __FUNCTION__);
- return Void();
- }
-
- FILE* out = fdopen(dup(fd->data[0]), "w");
- uint32_t currentSessions = SessionLibrary::get()->numOpenSessions();
- fprintf(out, "current open sessions: %u\n", currentSessions);
- fclose(out);
- return Void();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
deleted file mode 100644
index e04dd7e..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ /dev/null
@@ -1,964 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeyPlugin"
-#include <utils/Log.h>
-
-#include <chrono>
-#include <stdio.h>
-#include <inttypes.h>
-
-#include "DrmPlugin.h"
-#include "ClearKeyDrmProperties.h"
-#include "Session.h"
-#include "TypeConvert.h"
-#include "Utils.h"
-
-namespace {
-const std::string kKeySetIdPrefix("ckid");
-const int kKeySetIdLength = 16;
-const int kSecureStopIdStart = 100;
-const std::string kOfflineLicense("\"type\":\"persistent-license\"");
-const std::string kStreaming("Streaming");
-const std::string kTemporaryLicense("\"type\":\"temporary\"");
-const std::string kTrue("True");
-
-const std::string kQueryKeyLicenseType("LicenseType");
- // Value: "Streaming" or "Offline"
-const std::string kQueryKeyPlayAllowed("PlayAllowed");
- // Value: "True" or "False"
-const std::string kQueryKeyRenewAllowed("RenewAllowed");
- // Value: "True" or "False"
-
-const int kSecureStopIdSize = 10;
-
-std::vector<uint8_t> uint32ToVector(uint32_t value) {
- // 10 bytes to display max value 4294967295 + one byte null terminator
- char buffer[kSecureStopIdSize];
- memset(buffer, 0, kSecureStopIdSize);
- snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
- return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
-}
-
-}; // unnamed namespace
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) {
- switch (keyRequestType) {
- case KeyRequestType_V1_1::NONE:
- case KeyRequestType_V1_1::UPDATE:
- return KeyRequestType::UNKNOWN;
- default:
- return static_cast<KeyRequestType>(keyRequestType);
- }
-}
-
-DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
- : mSessionLibrary(sessionLibrary),
- mOpenSessionOkCount(0),
- mCloseSessionOkCount(0),
- mCloseSessionNotOpenedCount(0),
- mNextSecureStopId(kSecureStopIdStart),
- mMockError(Status_V1_2::OK) {
- mPlayPolicy.clear();
- initProperties();
- mSecureStops.clear();
- mReleaseKeysMap.clear();
- std::srand(std::time(nullptr));
-}
-
-void DrmPlugin::initProperties() {
- mStringProperties.clear();
- mStringProperties[kVendorKey] = kVendorValue;
- mStringProperties[kVersionKey] = kVersionValue;
- mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
- mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
- mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
- mStringProperties[kDrmErrorTestKey] = kDrmErrorTestValue;
-
- std::vector<uint8_t> valueVector;
- valueVector.clear();
- valueVector.insert(valueVector.end(),
- kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
- mByteArrayProperties[kDeviceIdKey] = valueVector;
-
- valueVector.clear();
- valueVector.insert(valueVector.end(),
- kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
- mByteArrayProperties[kMetricsKey] = valueVector;
-}
-
-// The secure stop in ClearKey implementation is not installed securely.
-// This function merely creates a test environment for testing secure stops APIs.
-// The content in this secure stop is implementation dependent, the clearkey
-// secureStop does not serve as a reference implementation.
-void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
- Mutex::Autolock lock(mSecureStopLock);
-
- ClearkeySecureStop clearkeySecureStop;
- clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
- clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
-
- mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
- clearkeySecureStop.id, clearkeySecureStop));
-}
-
-Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
- sp<Session> session = mSessionLibrary->createSession();
- processMockError(session);
- std::vector<uint8_t> sessionId = session->sessionId();
-
- Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
- _hidl_cb(status, toHidlVec(sessionId));
- mOpenSessionOkCount++;
- return Void();
-}
-
-Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
- openSession_1_1_cb _hidl_cb) {
- sp<Session> session = mSessionLibrary->createSession();
- processMockError(session);
- std::vector<uint8_t> sessionId = session->sessionId();
-
- Status status = setSecurityLevel(sessionId, securityLevel);
- if (status == Status::OK) {
- mOpenSessionOkCount++;
- } else {
- mSessionLibrary->destroySession(session);
- sessionId.clear();
- }
- _hidl_cb(status, toHidlVec(sessionId));
- return Void();
-}
-
-Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
- if (sessionId.size() == 0) {
- return Status::BAD_VALUE;
- }
-
- sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
- if (session.get()) {
- mSessionLibrary->destroySession(session);
- if (session->getMockError() != Status_V1_2::OK) {
- sendSessionLostState(sessionId);
- return Status::ERROR_DRM_INVALID_STATE;
- }
- mCloseSessionOkCount++;
- return Status::OK;
- }
- mCloseSessionNotOpenedCount++;
- return Status::ERROR_DRM_SESSION_NOT_OPENED;
-}
-
-Status_V1_2 DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- std::vector<uint8_t> *request,
- KeyRequestType_V1_1 *keyRequestType,
- std::string *defaultUrl) {
- UNUSED(optionalParameters);
-
- // GetKeyRequestOfflineKeyTypeNotSupported() in vts 1.0 and 1.1 expects
- // KeyType::OFFLINE to return ERROR_DRM_CANNOT_HANDLE in clearkey plugin.
- // Those tests pass in an empty initData, we use the empty initData to
- // signal such specific use case.
- if (keyType == KeyType::OFFLINE && 0 == initData.size()) {
- return Status_V1_2::ERROR_DRM_CANNOT_HANDLE;
- }
-
- *defaultUrl = "https://default.url";
- *keyRequestType = KeyRequestType_V1_1::UNKNOWN;
- *request = std::vector<uint8_t>();
-
- if (scope.size() == 0 ||
- (keyType != KeyType::STREAMING &&
- keyType != KeyType::OFFLINE &&
- keyType != KeyType::RELEASE)) {
- return Status_V1_2::BAD_VALUE;
- }
-
- const std::vector<uint8_t> scopeId = toVector(scope);
- sp<Session> session;
- if (keyType == KeyType::STREAMING || keyType == KeyType::OFFLINE) {
- std::vector<uint8_t> sessionId(scopeId.begin(), scopeId.end());
- session = mSessionLibrary->findSession(sessionId);
- if (!session.get()) {
- return Status_V1_2::ERROR_DRM_SESSION_NOT_OPENED;
- } else if (session->getMockError() != Status_V1_2::OK) {
- return session->getMockError();
- }
-
- *keyRequestType = KeyRequestType_V1_1::INITIAL;
- }
-
- Status_V1_2 status = static_cast<Status_V1_2>(
- session->getKeyRequest(initData, mimeType, keyType, request));
-
- if (keyType == KeyType::RELEASE) {
- std::vector<uint8_t> keySetId(scopeId.begin(), scopeId.end());
- std::string requestString(request->begin(), request->end());
- if (requestString.find(kOfflineLicense) != std::string::npos) {
- std::string emptyResponse;
- std::string keySetIdString(keySetId.begin(), keySetId.end());
- if (!mFileHandle.StoreLicense(keySetIdString,
- DeviceFiles::kLicenseStateReleasing,
- emptyResponse)) {
- ALOGE("Problem releasing offline license");
- return Status_V1_2::ERROR_DRM_UNKNOWN;
- }
- if (mReleaseKeysMap.find(keySetIdString) == mReleaseKeysMap.end()) {
- sp<Session> session = mSessionLibrary->createSession();
- mReleaseKeysMap[keySetIdString] = session->sessionId();
- } else {
- ALOGI("key is in use, ignore release request");
- }
- } else {
- ALOGE("Offline license not found, nothing to release");
- }
- *keyRequestType = KeyRequestType_V1_1::RELEASE;
- }
- return status;
-}
-
-Return<void> DrmPlugin::getKeyRequest(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_cb _hidl_cb) {
- UNUSED(optionalParameters);
-
- KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
- std::string defaultUrl("");
- std::vector<uint8_t> request;
- Status_V1_2 status = getKeyRequestCommon(
- scope, initData, mimeType, keyType, optionalParameters,
- &request, &keyRequestType, &defaultUrl);
-
- _hidl_cb(toStatus_1_0(status), toHidlVec(request),
- toKeyRequestType_V1_0(keyRequestType),
- hidl_string(defaultUrl));
- return Void();
-}
-
-Return<void> DrmPlugin::getKeyRequest_1_1(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_1_1_cb _hidl_cb) {
- UNUSED(optionalParameters);
-
- KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
- std::string defaultUrl("");
- std::vector<uint8_t> request;
- Status_V1_2 status = getKeyRequestCommon(
- scope, initData, mimeType, keyType, optionalParameters,
- &request, &keyRequestType, &defaultUrl);
-
- _hidl_cb(toStatus_1_0(status), toHidlVec(request),
- keyRequestType, hidl_string(defaultUrl));
- return Void();
-}
-
-Return<void> DrmPlugin::getKeyRequest_1_2(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_1_2_cb _hidl_cb) {
- UNUSED(optionalParameters);
-
- KeyRequestType_V1_1 keyRequestType = KeyRequestType_V1_1::UNKNOWN;
- std::string defaultUrl("");
- std::vector<uint8_t> request;
- Status_V1_2 status = getKeyRequestCommon(
- scope, initData, mimeType, keyType, optionalParameters,
- &request, &keyRequestType, &defaultUrl);
-
- _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
- return Void();
-}
-
-void DrmPlugin::setPlayPolicy() {
- android::Mutex::Autolock lock(mPlayPolicyLock);
- mPlayPolicy.clear();
-
- KeyValue policy;
- policy.key = kQueryKeyLicenseType;
- policy.value = kStreaming;
- mPlayPolicy.push_back(policy);
-
- policy.key = kQueryKeyPlayAllowed;
- policy.value = kTrue;
- mPlayPolicy.push_back(policy);
-
- policy.key = kQueryKeyRenewAllowed;
- mPlayPolicy.push_back(policy);
-}
-
-bool DrmPlugin::makeKeySetId(std::string* keySetId) {
- if (!keySetId) {
- ALOGE("keySetId destination not provided");
- return false;
- }
- std::vector<uint8_t> ksid(kKeySetIdPrefix.begin(), kKeySetIdPrefix.end());
- ksid.resize(kKeySetIdLength);
- std::vector<uint8_t> randomData((kKeySetIdLength - kKeySetIdPrefix.size()) / 2, 0);
-
- while (keySetId->empty()) {
- for (auto itr = randomData.begin(); itr != randomData.end(); ++itr) {
- *itr = std::rand() % 0xff;
- }
- *keySetId = kKeySetIdPrefix + ByteArrayToHexString(
- reinterpret_cast<const uint8_t*>(randomData.data()), randomData.size());
- if (mFileHandle.LicenseExists(*keySetId)) {
- // collision, regenerate
- ALOGV("Retry generating KeySetId");
- keySetId->clear();
- }
- }
- return true;
-}
-
-Return<void> DrmPlugin::provideKeyResponse(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& response,
- provideKeyResponse_cb _hidl_cb) {
- if (scope.size() == 0 || response.size() == 0) {
- // Returns empty keySetId
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
- return Void();
- }
-
- std::string responseString(
- reinterpret_cast<const char*>(response.data()), response.size());
- const std::vector<uint8_t> scopeId = toVector(scope);
- std::vector<uint8_t> sessionId;
- std::string keySetId;
-
- Status status = Status::OK;
- bool isOfflineLicense = responseString.find(kOfflineLicense) != std::string::npos;
- if (scopeId.size() < kKeySetIdPrefix.size()) {
- android_errorWriteLog(0x534e4554, "144507096");
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
- return Void();
- }
- bool isRelease = (memcmp(scopeId.data(), kKeySetIdPrefix.data(), kKeySetIdPrefix.size()) == 0);
- if (isRelease) {
- keySetId.assign(scopeId.begin(), scopeId.end());
-
- auto iter = mReleaseKeysMap.find(std::string(keySetId.begin(), keySetId.end()));
- if (iter != mReleaseKeysMap.end()) {
- sessionId.assign(iter->second.begin(), iter->second.end());
- }
- } else {
- sessionId.assign(scopeId.begin(), scopeId.end());
- // non offline license returns empty keySetId
- keySetId.clear();
- }
-
- sp<Session> session = mSessionLibrary->findSession(sessionId);
- if (!session.get()) {
- _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
- return Void();
- }
- setPlayPolicy();
-
- status = session->provideKeyResponse(response);
- if (status == Status::OK) {
- if (isOfflineLicense) {
- if (isRelease) {
- mFileHandle.DeleteLicense(keySetId);
- mSessionLibrary->destroySession(session);
- } else {
- if (!makeKeySetId(&keySetId)) {
- _hidl_cb(Status::ERROR_DRM_UNKNOWN, hidl_vec<uint8_t>());
- return Void();
- }
-
- bool ok = mFileHandle.StoreLicense(
- keySetId,
- DeviceFiles::kLicenseStateActive,
- std::string(response.begin(), response.end()));
- if (!ok) {
- ALOGE("Failed to store offline license");
- }
- }
- }
-
- // Test calling AMediaDrm listeners.
- sendEvent(EventType::VENDOR_DEFINED, sessionId, sessionId);
-
- sendExpirationUpdate(sessionId, 100);
-
- std::vector<KeyStatus_V1_2> keysStatus;
- KeyStatus_V1_2 keyStatus;
-
- std::vector<uint8_t> keyId1 = { 0xA, 0xB, 0xC };
- keyStatus.keyId = keyId1;
- keyStatus.type = V1_2::KeyStatusType::USABLE;
- keysStatus.push_back(keyStatus);
-
- std::vector<uint8_t> keyId2 = { 0xD, 0xE, 0xF };
- keyStatus.keyId = keyId2;
- keyStatus.type = V1_2::KeyStatusType::EXPIRED;
- keysStatus.push_back(keyStatus);
-
- std::vector<uint8_t> keyId3 = { 0x0, 0x1, 0x2 };
- keyStatus.keyId = keyId3;
- keyStatus.type = V1_2::KeyStatusType::USABLEINFUTURE;
- keysStatus.push_back(keyStatus);
-
- sendKeysChange_1_2(sessionId, keysStatus, true);
-
- installSecureStop(sessionId);
- } else {
- ALOGE("provideKeyResponse returns error=%d", status);
- }
-
- std::vector<uint8_t> keySetIdVec(keySetId.begin(), keySetId.end());
- _hidl_cb(status, toHidlVec(keySetIdVec));
- return Void();
-}
-
-Return<Status> DrmPlugin::restoreKeys(
- const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& keySetId) {
- if (sessionId.size() == 0 || keySetId.size() == 0) {
- return Status::BAD_VALUE;
- }
-
- DeviceFiles::LicenseState licenseState;
- std::string offlineLicense;
- Status status = Status::OK;
- if (!mFileHandle.RetrieveLicense(std::string(keySetId.begin(), keySetId.end()),
- &licenseState, &offlineLicense)) {
- ALOGE("Failed to restore offline license");
- return Status::ERROR_DRM_NO_LICENSE;
- }
-
- if (DeviceFiles::kLicenseStateUnknown == licenseState ||
- DeviceFiles::kLicenseStateReleasing == licenseState) {
- ALOGE("Invalid license state=%d", licenseState);
- return Status::ERROR_DRM_NO_LICENSE;
- }
-
- sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
- if (!session.get()) {
- return Status::ERROR_DRM_SESSION_NOT_OPENED;
- }
- status = session->provideKeyResponse(std::vector<uint8_t>(offlineLicense.begin(),
- offlineLicense.end()));
- if (status != Status::OK) {
- ALOGE("Failed to restore keys");
- }
- return status;
-}
-
-Return<void> DrmPlugin::getPropertyString(
- const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
- std::string name(propertyName.c_str());
- std::string value;
-
- if (name == kVendorKey) {
- value = mStringProperties[kVendorKey];
- } else if (name == kVersionKey) {
- value = mStringProperties[kVersionKey];
- } else if (name == kPluginDescriptionKey) {
- value = mStringProperties[kPluginDescriptionKey];
- } else if (name == kAlgorithmsKey) {
- value = mStringProperties[kAlgorithmsKey];
- } else if (name == kListenerTestSupportKey) {
- value = mStringProperties[kListenerTestSupportKey];
- } else if (name == kDrmErrorTestKey) {
- value = mStringProperties[kDrmErrorTestKey];
- } else {
- ALOGE("App requested unknown string property %s", name.c_str());
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
- return Void();
- }
- _hidl_cb(Status::OK, value.c_str());
- return Void();
-}
-
-Return<void> DrmPlugin::getPropertyByteArray(
- const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
- std::map<std::string, std::vector<uint8_t> >::iterator itr =
- mByteArrayProperties.find(std::string(propertyName.c_str()));
- if (itr == mByteArrayProperties.end()) {
- ALOGE("App requested unknown property: %s", propertyName.c_str());
- _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::OK, itr->second);
- return Void();
-
-}
-
-Return<Status> DrmPlugin::setPropertyString(
- const hidl_string& name, const hidl_string& value) {
- std::string immutableKeys;
- immutableKeys.append(kAlgorithmsKey + ",");
- immutableKeys.append(kPluginDescriptionKey + ",");
- immutableKeys.append(kVendorKey + ",");
- immutableKeys.append(kVersionKey + ",");
-
- std::string key = std::string(name.c_str());
- if (immutableKeys.find(key) != std::string::npos) {
- ALOGD("Cannot set immutable property: %s", key.c_str());
- return Status::BAD_VALUE;
- }
-
- std::map<std::string, std::string>::iterator itr =
- mStringProperties.find(key);
- if (itr == mStringProperties.end()) {
- ALOGE("Cannot set undefined property string, key=%s", key.c_str());
- return Status::BAD_VALUE;
- }
-
- if (name == kDrmErrorTestKey) {
- if (value == kResourceContentionValue) {
- mMockError = Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION;
- } else if (value == kLostStateValue) {
- mMockError = Status_V1_2::ERROR_DRM_SESSION_LOST_STATE;
- } else if (value == kFrameTooLargeValue) {
- mMockError = Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE;
- } else if (value == kInvalidStateValue) {
- mMockError = Status_V1_2::ERROR_DRM_INVALID_STATE;
- } else {
- mMockError = Status_V1_2::ERROR_DRM_UNKNOWN;
- }
- }
-
- mStringProperties[key] = std::string(value.c_str());
- return Status::OK;
-}
-
-Return<Status> DrmPlugin::setPropertyByteArray(
- const hidl_string& name, const hidl_vec<uint8_t>& value) {
- UNUSED(value);
- if (name == kDeviceIdKey) {
- ALOGD("Cannot set immutable property: %s", name.c_str());
- return Status::BAD_VALUE;
- } else if (name == kClientIdKey) {
- mByteArrayProperties[kClientIdKey] = toVector(value);
- return Status::OK;
- }
-
- // Setting of undefined properties is not supported
- ALOGE("Failed to set property byte array, key=%s", name.c_str());
- return Status::ERROR_DRM_CANNOT_HANDLE;
-}
-
-Return<void> DrmPlugin::queryKeyStatus(
- const hidl_vec<uint8_t>& sessionId,
- queryKeyStatus_cb _hidl_cb) {
- if (sessionId.size() == 0) {
- // Returns empty key status KeyValue pair
- _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
- return Void();
- }
-
- std::vector<KeyValue> infoMapVec;
- infoMapVec.clear();
-
- mPlayPolicyLock.lock();
- KeyValue keyValuePair;
- for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
- keyValuePair.key = mPlayPolicy[i].key;
- keyValuePair.value = mPlayPolicy[i].value;
- infoMapVec.push_back(keyValuePair);
- }
- mPlayPolicyLock.unlock();
- _hidl_cb(Status::OK, toHidlVec(infoMapVec));
- return Void();
-}
-
-Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
- uint32_t currentSessions = mSessionLibrary->numOpenSessions();
- uint32_t maxSessions = 10;
- _hidl_cb(Status::OK, currentSessions, maxSessions);
- return Void();
-}
-
-Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
- getSecurityLevel_cb _hidl_cb) {
- if (sessionId.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
- return Void();
- }
-
- std::vector<uint8_t> sid = toVector(sessionId);
- sp<Session> session = mSessionLibrary->findSession(sid);
- if (!session.get()) {
- _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
- return Void();
- }
-
- Mutex::Autolock lock(mSecurityLevelLock);
- std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
- mSecurityLevel.find(sid);
- if (itr == mSecurityLevel.end()) {
- ALOGE("Session id not found");
- _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
- return Void();
- }
-
- _hidl_cb(Status::OK, itr->second);
- return Void();
-}
-
-Return<void> DrmPlugin::getLogMessages(
- getLogMessages_cb _hidl_cb) {
- using std::chrono::duration_cast;
- using std::chrono::milliseconds;
- using std::chrono::system_clock;
-
- auto timeMillis = duration_cast<milliseconds>(
- system_clock::now().time_since_epoch()).count();
-
- std::vector<LogMessage> logs = {
- { timeMillis, LogPriority::ERROR, std::string("Not implemented") }};
- _hidl_cb(drm::V1_4::Status::OK, toHidlVec(logs));
- return Void();
-}
-
-Return<bool> DrmPlugin::requiresSecureDecoder(
- const hidl_string& mime, SecurityLevel level) {
- UNUSED(mime);
- UNUSED(level);
- return false;
-}
-
-Return<bool> DrmPlugin::requiresSecureDecoderDefault(const hidl_string& mime) {
- UNUSED(mime);
- // Clearkey only supports SW_SECURE_CRYPTO, so we always returns false
- // regardless of mime type.
- return false;
-}
-
-Return<Status> DrmPlugin::setPlaybackId(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_string& playbackId) {
- if (sessionId.size() == 0) {
- ALOGE("Invalid empty session id");
- return Status::BAD_VALUE;
- }
-
- std::vector<uint8_t> sid = toVector(sessionId);
- mPlaybackId[sid] = playbackId;
- return Status::OK;
-}
-
-Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
- SecurityLevel level) {
- if (sessionId.size() == 0) {
- ALOGE("Invalid empty session id");
- return Status::BAD_VALUE;
- }
-
- if (level > SecurityLevel::SW_SECURE_CRYPTO) {
- ALOGE("Cannot set security level > max");
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- std::vector<uint8_t> sid = toVector(sessionId);
- sp<Session> session = mSessionLibrary->findSession(sid);
- if (!session.get()) {
- return Status::ERROR_DRM_SESSION_NOT_OPENED;
- }
-
- Mutex::Autolock lock(mSecurityLevelLock);
- std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
- mSecurityLevel.find(sid);
- if (itr != mSecurityLevel.end()) {
- mSecurityLevel[sid] = level;
- } else {
- if (!mSecurityLevel.insert(
- std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
- ALOGE("Failed to set security level");
- return Status::ERROR_DRM_INVALID_STATE;
- }
- }
- return Status::OK;
-}
-
-Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
- // Set the open session count metric.
- DrmMetricGroup::Attribute openSessionOkAttribute = {
- "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
- };
- DrmMetricGroup::Value openSessionMetricValue = {
- "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
- };
- DrmMetricGroup::Metric openSessionMetric = {
- "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
- };
-
- // Set the close session count metric.
- DrmMetricGroup::Attribute closeSessionOkAttribute = {
- "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
- };
- DrmMetricGroup::Value closeSessionMetricValue = {
- "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
- };
- DrmMetricGroup::Metric closeSessionMetric = {
- "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
- };
-
- // Set the close session, not opened metric.
- DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
- "status", DrmMetricGroup::ValueType::INT64_TYPE,
- (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
- };
- DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
- "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
- };
- DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
- "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
- };
-
- // Set the setPlaybackId metric.
- std::vector<DrmMetricGroup::Attribute> sids;
- std::vector<DrmMetricGroup::Value> playbackIds;
- for (const auto&[key, value] : mPlaybackId) {
- std::string sid(key.begin(), key.end());
- DrmMetricGroup::Attribute sessionIdAttribute = {
- "sid", DrmMetricGroup::ValueType::STRING_TYPE, 0, 0, sid };
- sids.push_back(sessionIdAttribute);
-
- DrmMetricGroup::Value playbackIdMetricValue = {
- "playbackId", DrmMetricGroup::ValueType::STRING_TYPE, 0, 0, value };
- playbackIds.push_back(playbackIdMetricValue);
- }
- DrmMetricGroup::Metric setPlaybackIdMetric = {
- "set_playback_id", { sids }, { playbackIds }};
-
- DrmMetricGroup metrics = {
- { openSessionMetric, closeSessionMetric,
- closeSessionNotOpenedMetric, setPlaybackIdMetric }};
- _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
- return Void();
-}
-
-Return<void> DrmPlugin::getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) {
- std::vector<std::string> licenseNames = mFileHandle.ListLicenses();
- std::vector<KeySetId> keySetIds;
- if (mMockError != Status_V1_2::OK) {
- _hidl_cb(toStatus_1_0(mMockError), keySetIds);
- return Void();
- }
- for (const auto& name : licenseNames) {
- std::vector<uint8_t> keySetId(name.begin(), name.end());
- keySetIds.push_back(keySetId);
- }
- _hidl_cb(Status::OK, keySetIds);
- return Void();
-}
-
-
-Return<Status> DrmPlugin::removeOfflineLicense(const KeySetId& keySetId) {
- if (mMockError != Status_V1_2::OK) {
- return toStatus_1_0(mMockError);
- }
- std::string licenseName(keySetId.begin(), keySetId.end());
- if (mFileHandle.DeleteLicense(licenseName)) {
- return Status::OK;
- }
- return Status::BAD_VALUE;
-}
-
-Return<void> DrmPlugin::getOfflineLicenseState(const KeySetId& keySetId,
- getOfflineLicenseState_cb _hidl_cb) {
- std::string licenseName(keySetId.begin(), keySetId.end());
- DeviceFiles::LicenseState state;
- std::string license;
- OfflineLicenseState hLicenseState;
- if (mMockError != Status_V1_2::OK) {
- _hidl_cb(toStatus_1_0(mMockError), OfflineLicenseState::UNKNOWN);
- } else if (mFileHandle.RetrieveLicense(licenseName, &state, &license)) {
- switch (state) {
- case DeviceFiles::kLicenseStateActive:
- hLicenseState = OfflineLicenseState::USABLE;
- break;
- case DeviceFiles::kLicenseStateReleasing:
- hLicenseState = OfflineLicenseState::INACTIVE;
- break;
- case DeviceFiles::kLicenseStateUnknown:
- hLicenseState = OfflineLicenseState::UNKNOWN;
- break;
- }
- _hidl_cb(Status::OK, hLicenseState);
- } else {
- _hidl_cb(Status::BAD_VALUE, OfflineLicenseState::UNKNOWN);
- }
- return Void();
-}
-
-Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
- mSecureStopLock.lock();
- std::vector<SecureStop> stops;
- for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
- ClearkeySecureStop clearkeyStop = itr->second;
- std::vector<uint8_t> stopVec;
- stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
- stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
-
- SecureStop stop;
- stop.opaqueData = toHidlVec(stopVec);
- stops.push_back(stop);
- }
- mSecureStopLock.unlock();
-
- _hidl_cb(Status::OK, stops);
- return Void();
-}
-
-Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
- getSecureStop_cb _hidl_cb) {
- std::vector<uint8_t> stopVec;
-
- mSecureStopLock.lock();
- auto itr = mSecureStops.find(toVector(secureStopId));
- if (itr != mSecureStops.end()) {
- ClearkeySecureStop clearkeyStop = itr->second;
- stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
- stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
- }
- mSecureStopLock.unlock();
-
- SecureStop stop;
- if (!stopVec.empty()) {
- stop.opaqueData = toHidlVec(stopVec);
- _hidl_cb(Status::OK, stop);
- } else {
- _hidl_cb(Status::BAD_VALUE, stop);
- }
- return Void();
-}
-
-Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
- return removeSecureStop(secureStopId);
-}
-
-Return<Status> DrmPlugin::releaseAllSecureStops() {
- return removeAllSecureStops();
-}
-
-Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
- mSecureStopLock.lock();
- std::vector<SecureStopId> ids;
- for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
- ids.push_back(itr->first);
- }
- mSecureStopLock.unlock();
-
- _hidl_cb(Status::OK, toHidlVec(ids));
- return Void();
-}
-
-Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
- // OpaqueData starts with 4 byte decimal integer string
- const size_t kFourBytesOffset = 4;
- if (ssRelease.opaqueData.size() < kFourBytesOffset) {
- ALOGE("Invalid secureStopRelease length");
- return Status::BAD_VALUE;
- }
-
- Status status = Status::OK;
- std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
-
- if (input.size() < kSecureStopIdSize + kFourBytesOffset) {
- // The minimum size of SecureStopRelease has to contain
- // a 4 bytes count and one secureStop id
- ALOGE("Total size of secureStops is too short");
- return Status::BAD_VALUE;
- }
-
- // The format of opaqueData is shared between the server
- // and the drm service. The clearkey implementation consists of:
- // count - number of secure stops
- // list of fixed length secure stops
- size_t countBufferSize = sizeof(uint32_t);
- if (input.size() < countBufferSize) {
- // SafetyNet logging
- android_errorWriteLog(0x534e4554, "144766455");
- return Status::BAD_VALUE;
- }
- uint32_t count = 0;
- sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
-
- // Avoid divide by 0 below.
- if (count == 0) {
- ALOGE("Invalid 0 secureStop count");
- return Status::BAD_VALUE;
- }
-
- // Computes the fixed length secureStop size
- size_t secureStopSize = (input.size() - kFourBytesOffset) / count;
- if (secureStopSize < kSecureStopIdSize) {
- // A valid secureStop contains the id plus data
- ALOGE("Invalid secureStop size");
- return Status::BAD_VALUE;
- }
- uint8_t* buffer = new uint8_t[secureStopSize];
- size_t offset = kFourBytesOffset; // skip the count
- for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
- memcpy(buffer, input.data() + offset, secureStopSize);
-
- // A secureStop contains id+data, we only use the id for removal
- std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
- status = removeSecureStop(toHidlVec(id));
- if (Status::OK != status) break;
- }
-
- delete[] buffer;
- return status;
-}
-
-Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
- Mutex::Autolock lock(mSecureStopLock);
-
- if (1 != mSecureStops.erase(toVector(secureStopId))) {
- return Status::BAD_VALUE;
- }
- return Status::OK;
-}
-
-Return<Status> DrmPlugin::removeAllSecureStops() {
- Mutex::Autolock lock(mSecureStopLock);
-
- mSecureStops.clear();
- mNextSecureStopId = kSecureStopIdStart;
- return Status::OK;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
deleted file mode 100644
index eccc843..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/InitDataParser.cpp
+++ /dev/null
@@ -1,186 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_InitDataParser"
-
-#include <algorithm>
-#include <utils/Log.h>
-
-#include "InitDataParser.h"
-
-#include "Base64.h"
-
-#include "ClearKeyUUID.h"
-#include "MimeType.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace {
- const size_t kKeyIdSize = 16;
- const size_t kSystemIdSize = 16;
-}
-
-std::vector<uint8_t> StrToVector(const std::string& str) {
- std::vector<uint8_t> vec(str.begin(), str.end());
- return vec;
-}
-
-Status InitDataParser::parse(const std::vector<uint8_t>& initData,
- const std::string& mimeType,
- V1_0::KeyType keyType,
- std::vector<uint8_t>* licenseRequest) {
- // Build a list of the key IDs
- std::vector<const uint8_t*> keyIds;
-
- if (mimeType == kIsoBmffVideoMimeType.c_str() ||
- mimeType == kIsoBmffAudioMimeType.c_str() ||
- mimeType == kCencInitDataFormat.c_str()) {
- Status res = parsePssh(initData, &keyIds);
- if (res != Status::OK) {
- return res;
- }
- } else if (mimeType == kWebmVideoMimeType.c_str() ||
- mimeType == kWebmAudioMimeType.c_str() ||
- mimeType == kWebmInitDataFormat.c_str()) {
- // WebM "init data" is just a single key ID
- if (initData.size() != kKeyIdSize) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
- keyIds.push_back(initData.data());
- } else {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- if (keyType == V1_0::KeyType::RELEASE) {
- // restore key
- }
-
- // Build the request
- std::string requestJson = generateRequest(keyType, keyIds);
- std::vector<uint8_t> requestJsonVec = StrToVector(requestJson);
-
- licenseRequest->clear();
- licenseRequest->insert(licenseRequest->end(), requestJsonVec.begin(), requestJsonVec.end());
- return Status::OK;
-}
-
-Status InitDataParser::parsePssh(const std::vector<uint8_t>& initData,
- std::vector<const uint8_t*>* keyIds) {
- // Description of PSSH format:
- // https://w3c.github.io/encrypted-media/format-registry/initdata/cenc.html
- size_t readPosition = 0;
-
- uint32_t expectedSize = initData.size();
- const char psshIdentifier[4] = {'p', 's', 's', 'h'};
- const uint8_t psshVersion1[4] = {1, 0, 0, 0};
- uint32_t keyIdCount = 0;
- size_t headerSize = sizeof(expectedSize) + sizeof(psshIdentifier) +
- sizeof(psshVersion1) + kSystemIdSize + sizeof(keyIdCount);
- if (initData.size() < headerSize) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- // Validate size field
- expectedSize = htonl(expectedSize);
- if (memcmp(&initData[readPosition], &expectedSize,
- sizeof(expectedSize)) != 0) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
- readPosition += sizeof(expectedSize);
-
- // Validate PSSH box identifier
- if (memcmp(&initData[readPosition], psshIdentifier,
- sizeof(psshIdentifier)) != 0) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
- readPosition += sizeof(psshIdentifier);
-
- // Validate EME version number
- if (memcmp(&initData[readPosition], psshVersion1,
- sizeof(psshVersion1)) != 0) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
- readPosition += sizeof(psshVersion1);
-
- // Validate system ID
- if (!clearkeydrm::isClearKeyUUID(&initData[readPosition])) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
- readPosition += kSystemIdSize;
-
- // Read key ID count
- memcpy(&keyIdCount, &initData[readPosition], sizeof(keyIdCount));
- keyIdCount = ntohl(keyIdCount);
- readPosition += sizeof(keyIdCount);
-
- uint64_t psshSize = 0;
- if (__builtin_mul_overflow(keyIdCount, kKeyIdSize, &psshSize) ||
- __builtin_add_overflow(readPosition, psshSize, &psshSize) ||
- psshSize != initData.size() - sizeof(uint32_t) /* DataSize(0) */) {
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- // Calculate the key ID offsets
- for (uint32_t i = 0; i < keyIdCount; ++i) {
- size_t keyIdPosition = readPosition + (i * kKeyIdSize);
- keyIds->push_back(&initData[keyIdPosition]);
- }
- return Status::OK;
-}
-
-std::string InitDataParser::generateRequest(V1_0::KeyType keyType,
- const std::vector<const uint8_t*>& keyIds) {
- const std::string kRequestPrefix("{\"kids\":[");
- const std::string kTemporarySession("],\"type\":\"temporary\"}");
- const std::string kPersistentSession("],\"type\":\"persistent-license\"}");
-
- std::string request(kRequestPrefix);
- std::string encodedId;
- for (size_t i = 0; i < keyIds.size(); ++i) {
- encodedId.clear();
- encodeBase64Url(keyIds[i], kKeyIdSize, &encodedId);
- if (i != 0) {
- request.append(",");
- }
- request.push_back('\"');
- request.append(encodedId);
- request.push_back('\"');
- }
- if (keyType == V1_0::KeyType::STREAMING) {
- request.append(kTemporarySession);
- } else if (keyType == V1_0::KeyType::OFFLINE ||
- keyType == V1_0::KeyType::RELEASE) {
- request.append(kPersistentSession);
- }
-
- // Android's Base64 encoder produces padding. EME forbids padding.
- const char kBase64Padding = '=';
- request.erase(std::remove(request.begin(), request.end(), kBase64Padding), request.end());
-
- return request;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
deleted file mode 100644
index 45cc775..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/JsonWebKey.cpp
+++ /dev/null
@@ -1,278 +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.
- */
-#define LOG_TAG "hidl_JsonWebKey"
-
-#include <utils/Log.h>
-
-#include "JsonWebKey.h"
-
-#include "Base64.h"
-
-namespace {
-const std::string kBase64Padding("=");
-const std::string kKeysTag("keys");
-const std::string kKeyTypeTag("kty");
-const std::string kKeyTag("k");
-const std::string kKeyIdTag("kid");
-const std::string kMediaSessionType("type");
-const std::string kPersistentLicenseSession("persistent-license");
-const std::string kSymmetricKeyValue("oct");
-const std::string kTemporaryLicenseSession("temporary");
-}
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-JsonWebKey::JsonWebKey() {
-}
-
-JsonWebKey::~JsonWebKey() {
-}
-
-/*
- * Parses a JSON Web Key Set string, initializes a KeyMap with key id:key
- * pairs from the JSON Web Key Set. Both key ids and keys are base64url
- * encoded. The KeyMap contains base64url decoded key id:key pairs.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
- KeyMap* keys) {
-
- keys->clear();
-
- if (!parseJsonWebKeySet(jsonWebKeySet, &mJsonObjects)) {
- return false;
- }
-
- // mJsonObjects[0] contains the entire JSON Web Key Set, including
- // all the base64 encoded keys. Each key is also stored separately as
- // a JSON object in mJsonObjects[1..n] where n is the total
- // number of keys in the set.
- if (mJsonObjects.size() == 0 || !isJsonWebKeySet(mJsonObjects[0])) {
- return false;
- }
-
- std::string encodedKey, encodedKeyId;
- std::vector<uint8_t> decodedKey, decodedKeyId;
-
- // mJsonObjects[1] contains the first JSON Web Key in the set
- for (size_t i = 1; i < mJsonObjects.size(); ++i) {
- encodedKeyId.clear();
- encodedKey.clear();
-
- if (!parseJsonObject(mJsonObjects[i], &mTokens))
- return false;
-
- if (findKey(mJsonObjects[i], &encodedKeyId, &encodedKey)) {
- if (encodedKeyId.empty() || encodedKey.empty()) {
- ALOGE("Must have both key id and key in the JsonWebKey set.");
- continue;
- }
-
- if (!decodeBase64String(encodedKeyId, &decodedKeyId)) {
- ALOGE("Failed to decode key id(%s)", encodedKeyId.c_str());
- continue;
- }
-
- if (!decodeBase64String(encodedKey, &decodedKey)) {
- ALOGE("Failed to decode key(%s)", encodedKey.c_str());
- continue;
- }
-
- keys->insert(std::pair<std::vector<uint8_t>,
- std::vector<uint8_t> >(decodedKeyId, decodedKey));
- }
- }
- return true;
-}
-
-bool JsonWebKey::decodeBase64String(const std::string& encodedText,
- std::vector<uint8_t>* decodedText) {
-
- decodedText->clear();
-
- // encodedText should not contain padding characters as per EME spec.
- if (encodedText.find(kBase64Padding) != std::string::npos) {
- return false;
- }
-
- // Since decodeBase64() requires padding characters,
- // add them so length of encodedText is exactly a multiple of 4.
- int remainder = encodedText.length() % 4;
- std::string paddedText(encodedText);
- if (remainder > 0) {
- for (int i = 0; i < 4 - remainder; ++i) {
- paddedText.append(kBase64Padding);
- }
- }
-
- sp<Buffer> buffer = decodeBase64(paddedText);
- if (buffer == nullptr) {
- ALOGE("Malformed base64 encoded content found.");
- return false;
- }
-
- decodedText->insert(decodedText->end(), buffer->base(), buffer->base() + buffer->size());
- return true;
-}
-
-bool JsonWebKey::findKey(const std::string& jsonObject, std::string* keyId,
- std::string* encodedKey) {
-
- std::string key, value;
-
- // Only allow symmetric key, i.e. "kty":"oct" pair.
- if (jsonObject.find(kKeyTypeTag) != std::string::npos) {
- findValue(kKeyTypeTag, &value);
- if (0 != value.compare(kSymmetricKeyValue))
- return false;
- }
-
- if (jsonObject.find(kKeyIdTag) != std::string::npos) {
- findValue(kKeyIdTag, keyId);
- }
-
- if (jsonObject.find(kKeyTag) != std::string::npos) {
- findValue(kKeyTag, encodedKey);
- }
- return true;
-}
-
-void JsonWebKey::findValue(const std::string &key, std::string* value) {
- value->clear();
- const char* valueToken;
- for (std::vector<std::string>::const_iterator nextToken = mTokens.begin();
- nextToken != mTokens.end(); ++nextToken) {
- if (0 == (*nextToken).compare(key)) {
- if (nextToken + 1 == mTokens.end())
- break;
- valueToken = (*(nextToken + 1)).c_str();
- value->assign(valueToken);
- nextToken++;
- break;
- }
- }
-}
-
-bool JsonWebKey::isJsonWebKeySet(const std::string& jsonObject) const {
- if (jsonObject.find(kKeysTag) == std::string::npos) {
- ALOGE("JSON Web Key does not contain keys.");
- return false;
- }
- return true;
-}
-
-/*
- * Parses a JSON objects string and initializes a vector of tokens.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::parseJsonObject(const std::string& jsonObject,
- std::vector<std::string>* tokens) {
- jsmn_parser parser;
-
- jsmn_init(&parser);
- int numTokens = jsmn_parse(&parser,
- jsonObject.c_str(), jsonObject.size(), nullptr, 0);
- if (numTokens < 0) {
- ALOGE("Parser returns error code=%d", numTokens);
- return false;
- }
-
- unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
- mJsmnTokens.clear();
- mJsmnTokens.resize(jsmnTokensSize);
-
- jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonObject.c_str(),
- jsonObject.size(), mJsmnTokens.data(), numTokens);
- if (status < 0) {
- ALOGE("Parser returns error code=%d", status);
- return false;
- }
-
- tokens->clear();
- std::string token;
- const char *pjs;
- for (int j = 0; j < numTokens; ++j) {
- pjs = jsonObject.c_str() + mJsmnTokens[j].start;
- if (mJsmnTokens[j].type == JSMN_STRING ||
- mJsmnTokens[j].type == JSMN_PRIMITIVE) {
- token.assign(pjs, mJsmnTokens[j].end - mJsmnTokens[j].start);
- tokens->push_back(token);
- }
- }
- return true;
-}
-
-/*
- * Parses JSON Web Key Set string and initializes a vector of JSON objects.
- *
- * @return Returns false for errors, true for success.
- */
-bool JsonWebKey::parseJsonWebKeySet(const std::string& jsonWebKeySet,
- std::vector<std::string>* jsonObjects) {
- if (jsonWebKeySet.empty()) {
- ALOGE("Empty JSON Web Key");
- return false;
- }
-
- // The jsmn parser only supports unicode encoding.
- jsmn_parser parser;
-
- // Computes number of tokens. A token marks the type, offset in
- // the original string.
- jsmn_init(&parser);
- int numTokens = jsmn_parse(&parser,
- jsonWebKeySet.c_str(), jsonWebKeySet.size(), nullptr, 0);
- if (numTokens < 0) {
- ALOGE("Parser returns error code=%d", numTokens);
- return false;
- }
-
- unsigned int jsmnTokensSize = numTokens * sizeof(jsmntok_t);
- mJsmnTokens.resize(jsmnTokensSize);
-
- jsmn_init(&parser);
- int status = jsmn_parse(&parser, jsonWebKeySet.c_str(),
- jsonWebKeySet.size(), mJsmnTokens.data(), numTokens);
- if (status < 0) {
- ALOGE("Parser returns error code=%d", status);
- return false;
- }
-
- std::string token;
- const char *pjs;
- for (int i = 0; i < numTokens; ++i) {
- pjs = jsonWebKeySet.c_str() + mJsmnTokens[i].start;
- if (mJsmnTokens[i].type == JSMN_OBJECT) {
- token.assign(pjs, mJsmnTokens[i].end - mJsmnTokens[i].start);
- jsonObjects->push_back(token);
- }
- }
- return true;
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp b/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
deleted file mode 100644
index 56910be..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/MemoryFileSystem.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-
-#include <utils/Log.h>
-#include <string>
-
-#include "MemoryFileSystem.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-std::string MemoryFileSystem::GetFileName(const std::string& path) {
- size_t index = path.find_last_of('/');
- if (index != std::string::npos) {
- return path.substr(index+1);
- } else {
- return path;
- }
-}
-
-bool MemoryFileSystem::FileExists(const std::string& fileName) const {
- auto result = mMemoryFileSystem.find(fileName);
- return result != mMemoryFileSystem.end();
-}
-
-ssize_t MemoryFileSystem::GetFileSize(const std::string& fileName) const {
- auto result = mMemoryFileSystem.find(fileName);
- if (result != mMemoryFileSystem.end()) {
- return static_cast<ssize_t>(result->second.getFileSize());
- } else {
- ALOGE("Failed to get size for %s", fileName.c_str());
- return -1;
- }
-}
-
-std::vector<std::string> MemoryFileSystem::ListFiles() const {
- std::vector<std::string> list;
- for (const auto& filename : mMemoryFileSystem) {
- list.push_back(filename.first);
- }
- return list;
-}
-
-size_t MemoryFileSystem::Read(const std::string& path, std::string* buffer) {
- std::string key = GetFileName(path);
- auto result = mMemoryFileSystem.find(key);
- if (result != mMemoryFileSystem.end()) {
- std::string serializedHashFile = result->second.getContent();
- buffer->assign(serializedHashFile);
- return buffer->size();
- } else {
- ALOGE("Failed to read from %s", path.c_str());
- return -1;
- }
-}
-
-size_t MemoryFileSystem::Write(const std::string& path, const MemoryFile& memoryFile) {
- std::string key = GetFileName(path);
- auto result = mMemoryFileSystem.find(key);
- if (result != mMemoryFileSystem.end()) {
- mMemoryFileSystem.erase(key);
- }
- mMemoryFileSystem.insert(std::pair<std::string, MemoryFile>(key, memoryFile));
- return memoryFile.getFileSize();
-}
-
-bool MemoryFileSystem::RemoveFile(const std::string& fileName) {
- auto result = mMemoryFileSystem.find(fileName);
- if (result != mMemoryFileSystem.end()) {
- mMemoryFileSystem.erase(result);
- return true;
- } else {
- ALOGE("Cannot find license to remove: %s", fileName.c_str());
- return false;
- }
-}
-
-bool MemoryFileSystem::RemoveAllFiles() {
- mMemoryFileSystem.clear();
- return mMemoryFileSystem.empty();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp b/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
deleted file mode 100644
index cf668d4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/Session.cpp
+++ /dev/null
@@ -1,101 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeySession"
-#include <utils/Log.h>
-
-#include "Session.h"
-#include "Utils.h"
-
-#include "AesCtrDecryptor.h"
-#include "InitDataParser.h"
-#include "JsonWebKey.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
-using ::android::hardware::Return;
-using ::android::sp;
-
-using android::Mutex;
-
-Status Session::getKeyRequest(
- const std::vector<uint8_t>& initData,
- const std::string& mimeType,
- V1_0::KeyType keyType,
- std::vector<uint8_t>* keyRequest) const {
- InitDataParser parser;
- return parser.parse(initData, mimeType, keyType, keyRequest);
-}
-
-Status Session::provideKeyResponse(const std::vector<uint8_t>& response) {
- std::string responseString(
- reinterpret_cast<const char*>(response.data()), response.size());
- KeyMap keys;
-
- Mutex::Autolock lock(mMapLock);
- JsonWebKey parser;
- if (parser.extractKeysFromJsonWebKeySet(responseString, &keys)) {
- for (auto &key : keys) {
- std::string first(key.first.begin(), key.first.end());
- std::string second(key.second.begin(), key.second.end());
- mKeyMap.insert(std::pair<std::vector<uint8_t>,
- std::vector<uint8_t> >(key.first, key.second));
- }
- return Status::OK;
- } else {
- return Status::ERROR_DRM_UNKNOWN;
- }
-}
-
-Status_V1_2 Session::decrypt(
- const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
- uint8_t* destPtr, const std::vector<SubSample> subSamples,
- size_t* bytesDecryptedOut) {
- Mutex::Autolock lock(mMapLock);
-
- if (getMockError() != Status_V1_2::OK) {
- return getMockError();
- }
-
- std::vector<uint8_t> keyIdVector;
- keyIdVector.clear();
- keyIdVector.insert(keyIdVector.end(), keyId, keyId + kBlockSize);
- std::map<std::vector<uint8_t>, std::vector<uint8_t> >::iterator itr;
- itr = mKeyMap.find(keyIdVector);
- if (itr == mKeyMap.end()) {
- return Status_V1_2::ERROR_DRM_NO_LICENSE;
- }
-
- AesCtrDecryptor decryptor;
- Status status = decryptor.decrypt(
- itr->second /*key*/, iv, srcPtr, destPtr, subSamples,
- subSamples.size(), bytesDecryptedOut);
- return static_cast<Status_V1_2>(status);
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp b/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
deleted file mode 100644
index 88afcc4..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/SessionLibrary.cpp
+++ /dev/null
@@ -1,92 +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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "hidl_ClearKeySessionLibrary"
-#include <utils/Log.h>
-
-#include "SessionLibrary.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::sp;
-
-Mutex SessionLibrary::sSingletonLock;
-SessionLibrary* SessionLibrary::sSingleton = NULL;
-
-SessionLibrary* SessionLibrary::get() {
- Mutex::Autolock lock(sSingletonLock);
-
- if (sSingleton == NULL) {
- ALOGD("Instantiating Session Library Singleton.");
- sSingleton = new SessionLibrary();
- }
-
- return sSingleton;
-}
-
-sp<Session> SessionLibrary::createSession() {
- Mutex::Autolock lock(mSessionsLock);
-
- char sessionIdRaw[16];
- snprintf(sessionIdRaw, sizeof(sessionIdRaw), "%u", mNextSessionId);
-
- mNextSessionId += 1;
-
- std::vector<uint8_t> sessionId;
- sessionId.insert(sessionId.end(), sessionIdRaw,
- sessionIdRaw + sizeof(sessionIdRaw) / sizeof(uint8_t));
-
- mSessions.insert(std::pair<std::vector<uint8_t>,
- sp<Session> >(sessionId, new Session(sessionId)));
- std::map<std::vector<uint8_t>, sp<Session> >::iterator itr =
- mSessions.find(sessionId);
- if (itr != mSessions.end()) {
- return itr->second;
- } else {
- return nullptr;
- }
-}
-
-sp<Session> SessionLibrary::findSession(
- const std::vector<uint8_t>& sessionId) {
- Mutex::Autolock lock(mSessionsLock);
- std::map<std::vector<uint8_t>, sp<Session> >::iterator itr =
- mSessions.find(sessionId);
- if (itr != mSessions.end()) {
- return itr->second;
- } else {
- return nullptr;
- }
-}
-
-void SessionLibrary::destroySession(const sp<Session>& session) {
- Mutex::Autolock lock(mSessionsLock);
- mSessions.erase(session->sessionId());
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
deleted file mode 100644
index ec4517d..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service-lazy.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- disabled
- oneshot
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
deleted file mode 100644
index 3b48cf2..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.2-service.clearkey.rc
+++ /dev/null
@@ -1,13 +0,0 @@
-service vendor.drm-clearkey-hal-1-2 /vendor/bin/hw/android.hardware.drm@1.2-service.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- disabled
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
deleted file mode 100644
index 6e64978..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,16 +0,0 @@
-service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service-lazy.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- interface android.hardware.drm@1.3::ICryptoFactory clearkey
- interface android.hardware.drm@1.3::IDrmFactory clearkey
- disabled
- oneshot
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
deleted file mode 100644
index e302e1b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.3-service.clearkey.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-service vendor.drm-clearkey-hal-1-3 /vendor/bin/hw/android.hardware.drm@1.3-service.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- interface android.hardware.drm@1.3::ICryptoFactory clearkey
- interface android.hardware.drm@1.3::IDrmFactory clearkey
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
deleted file mode 100644
index 84a63a1..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service-lazy.clearkey.rc
+++ /dev/null
@@ -1,18 +0,0 @@
-service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service-lazy.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- interface android.hardware.drm@1.3::ICryptoFactory clearkey
- interface android.hardware.drm@1.3::IDrmFactory clearkey
- interface android.hardware.drm@1.4::ICryptoFactory clearkey
- interface android.hardware.drm@1.4::IDrmFactory clearkey
- disabled
- oneshot
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc b/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
deleted file mode 100644
index 649599e..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/android.hardware.drm@1.4-service.clearkey.rc
+++ /dev/null
@@ -1,16 +0,0 @@
-service vendor.drm-clearkey-hal-1-4 /vendor/bin/hw/android.hardware.drm@1.4-service.clearkey
- interface android.hardware.drm@1.0::ICryptoFactory clearkey
- interface android.hardware.drm@1.0::IDrmFactory clearkey
- interface android.hardware.drm@1.1::ICryptoFactory clearkey
- interface android.hardware.drm@1.1::IDrmFactory clearkey
- interface android.hardware.drm@1.2::ICryptoFactory clearkey
- interface android.hardware.drm@1.2::IDrmFactory clearkey
- interface android.hardware.drm@1.3::ICryptoFactory clearkey
- interface android.hardware.drm@1.3::IDrmFactory clearkey
- interface android.hardware.drm@1.4::ICryptoFactory clearkey
- interface android.hardware.drm@1.4::IDrmFactory clearkey
- class hal
- user media
- group media mediadrm
- ioprio rt 4
- task_profiles ProcessCapacityHigh
diff --git a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md b/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md
deleted file mode 100644
index cb45460..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Fuzzer for android.hardware.drm@1.4-service.clearkey
-
-## Plugin Design Considerations
-The fuzzer plugin for android.hardware.drm@1.4-service.clearkey is designed based on the understanding of the
-source code 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.
-
-android.hardware.drm@1.4-service.clearkey 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.`SecurityLevel::UNKNOWN` 1.`SecurityLevel::SW_SECURE_CRYPTO` 2.`SecurityLevel::SW_SECURE_DECODE` 3.`SecurityLevel::HW_SECURE_CRYPTO` 4.`SecurityLevel::HW_SECURE_DECODE` 5.`SecurityLevel::HW_SECURE_ALL`| Value obtained from FuzzedDataProvider in the range 0 to 5|
-| `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.`audio/webm` 14.`video/webm` 15.`webm` 16.`cenc` 17.`video/unknown` 18.`audio/unknown`| Value obtained from FuzzedDataProvider in the range 0 to 18|
-| `keyType` | 0.`KeyType::OFFLINE` 1.`KeyType::STREAMING` 2.`KeyType::RELEASE` | Value obtained from FuzzedDataProvider in the range 0 to 2|
-| `cryptoMode` | 0.`Mode::UNENCRYPTED` 1.`Mode::AES_CTR` 2.`Mode::AES_CBC_CTS` 3.`Mode::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 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 clearkeyV1.4_fuzzer binary.
-
-### Android
-
-#### Steps to build
-Build the fuzzer
-```
- $ mm -j$(nproc) clearkeyV1.4_fuzzer
-```
-#### Steps to run
-To run on device
-```
- $ adb sync data
- $ adb shell /data/fuzz/${TARGET_ARCH}/clearkeyV1.4_fuzzer/vendor/hw/clearkeyV1.4_fuzzer
-```
-
-## References:
- * http://llvm.org/docs/LibFuzzer.html
- * https://github.com/google/oss-fuzz
diff --git a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp b/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp
deleted file mode 100644
index afe0e6c..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/fuzzer/clearkeyV1.4_fuzzer.cpp
+++ /dev/null
@@ -1,719 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <include/CreatePluginFactories.h>
-
-#include <android/hidl/allocator/1.0/IAllocator.h>
-#include <fuzzer/FuzzedDataProvider.h>
-#include <hidlmemory/mapping.h>
-#include <include/ClearKeyDrmProperties.h>
-#include <include/CryptoFactory.h>
-#include <include/CryptoPlugin.h>
-#include <include/DrmPlugin.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-namespace drm = ::android::hardware::drm;
-using namespace std;
-using namespace android;
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hidl::allocator::V1_0::IAllocator;
-using ::android::hidl::memory::V1_0::IMemory;
-using drm::V1_0::BufferType;
-using drm::V1_0::DestinationBuffer;
-using drm::V1_0::EventType;
-using drm::V1_0::ICryptoPlugin;
-using drm::V1_0::IDrmPlugin;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_0::KeyedVector;
-using drm::V1_0::KeyStatus;
-using drm::V1_0::KeyStatusType;
-using drm::V1_0::KeyType;
-using drm::V1_0::Mode;
-using drm::V1_0::Pattern;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-using drm::V1_1::DrmMetricGroup;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::OfflineLicenseState;
-using drm::V1_4::clearkey::ICryptoFactory;
-using drm::V1_4::clearkey::IDrmFactory;
-using drm::V1_4::clearkey::kAlgorithmsKey;
-using drm::V1_4::clearkey::kClientIdKey;
-using drm::V1_4::clearkey::kDeviceIdKey;
-using drm::V1_4::clearkey::kDrmErrorTestKey;
-using drm::V1_4::clearkey::kListenerTestSupportKey;
-using drm::V1_4::clearkey::kMetricsKey;
-using drm::V1_4::clearkey::kPluginDescriptionKey;
-using drm::V1_4::clearkey::kVendorKey;
-using drm::V1_4::clearkey::kVersionKey;
-
-typedef ::android::hardware::hidl_vec<uint8_t> SessionId;
-typedef ::android::hardware::hidl_vec<uint8_t> SecureStopId;
-
-static const uint8_t kInvalidUUID[] = {0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
- 0x70, 0x80, 0x10, 0x20, 0x30, 0x40,
- 0x50, 0x60, 0x70, 0x80};
-
-static const uint8_t kClearKeyUUID[] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85,
- 0xB3, 0xC9, 0x78, 0x1A, 0xB0, 0x30,
- 0xAF, 0x78, 0xD3, 0x0E};
-
-const SecurityLevel kSecurityLevel[] = {
- SecurityLevel::UNKNOWN, SecurityLevel::SW_SECURE_CRYPTO,
- SecurityLevel::SW_SECURE_DECODE, SecurityLevel::HW_SECURE_CRYPTO,
- SecurityLevel::HW_SECURE_DECODE, SecurityLevel::HW_SECURE_ALL};
-
-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", "audio/webm", "video/webm",
- "webm", "cenc", "video/unknown", "audio/unknown"};
-
-const char *kCipherAlgorithm[] = {"AES/CBC/NoPadding", ""};
-
-const char *kMacAlgorithm[] = {"HmacSHA256", ""};
-
-const char *kRSAAlgorithm[] = {"RSASSA-PSS-SHA1", ""};
-
-const std::string kProperty[] = {kVendorKey,
- kVersionKey,
- kPluginDescriptionKey,
- kAlgorithmsKey,
- kListenerTestSupportKey,
- kDrmErrorTestKey,
- kDeviceIdKey,
- kClientIdKey,
- kMetricsKey,
- "placeholder"};
-
-const KeyType kKeyType[] = {KeyType::OFFLINE, KeyType::STREAMING,
- KeyType::RELEASE};
-
-const Mode kCryptoMode[] = {Mode::UNENCRYPTED, Mode::AES_CTR, Mode::AES_CBC_CTS,
- Mode::AES_CBC};
-
-const hidl_vec<uint8_t> validInitData = {
- // BMFF box header (4 bytes size + 'pssh')
- 0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68,
- // full box header (version = 1 flags = 0)
- 0x01, 0x00, 0x00, 0x00,
- // system id
- 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e,
- 0x52, 0xe2, 0xfb, 0x4b,
- // number of key ids
- 0x00, 0x00, 0x00, 0x01,
- // key id
- 0x60, 0x06, 0x1e, 0x01, 0x7e, 0x47, 0x7e, 0x87, 0x7e, 0x57, 0xd0, 0x0d,
- 0x1e, 0xd0, 0x0d, 0x1e,
- // size of data, must be zero
- 0x00, 0x00, 0x00, 0x00};
-
-const hidl_vec<uint8_t> validKeyResponse = {
- 0x7b, 0x22, 0x6b, 0x65, 0x79, 0x73, 0x22, 0x3a, 0x5b, 0x7b, 0x22,
- 0x6b, 0x74, 0x79, 0x22, 0x3a, 0x22, 0x6f, 0x63, 0x74, 0x22, 0x2c,
- 0x22, 0x6b, 0x69, 0x64, 0x22, 0x3a, 0x22, 0x59, 0x41, 0x59, 0x65,
- 0x41, 0x58, 0x35, 0x48, 0x66, 0x6f, 0x64, 0x2d, 0x56, 0x39, 0x41,
- 0x4e, 0x48, 0x74, 0x41, 0x4e, 0x48, 0x67, 0x22, 0x2c, 0x22, 0x6b,
- 0x22, 0x3a, 0x22, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x54, 0x65,
- 0x73, 0x74, 0x4b, 0x65, 0x79, 0x42, 0x61, 0x73, 0x65, 0x36, 0x34,
- 0x67, 0x67, 0x67, 0x22, 0x7d, 0x5d, 0x7d, 0x0a};
-
-const size_t kAESBlockSize = 16;
-const size_t kMaxStringLength = 100;
-const size_t kMaxSubSamples = 10;
-const size_t kMaxNumBytes = 1000;
-const size_t kSegmentIndex = 0;
-
-template <typename T, size_t size>
-T getValueFromArray(FuzzedDataProvider *fdp, const T (&arr)[size]) {
- return arr[fdp->ConsumeIntegralInRange<int32_t>(0, size - 1)];
-}
-
-class TestDrmPluginListener : public IDrmPluginListener {
-public:
- TestDrmPluginListener() {}
- virtual ~TestDrmPluginListener() {}
-
- virtual Return<void> sendEvent(EventType /*eventType*/,
- const hidl_vec<uint8_t> & /*sessionId*/,
- const hidl_vec<uint8_t> & /*data*/) override {
- return Return<void>();
- }
-
- virtual Return<void>
- sendExpirationUpdate(const hidl_vec<uint8_t> & /*sessionId*/,
- int64_t /*expiryTimeInMS*/) override {
- return Return<void>();
- }
-
- virtual Return<void>
- sendKeysChange(const hidl_vec<uint8_t> & /*sessionId*/,
- const hidl_vec<KeyStatus> & /*keyStatusList*/,
- bool /*hasNewUsableKey*/) override {
- return Return<void>();
- }
-};
-
-class ClearKeyFuzzer {
-public:
- ~ClearKeyFuzzer() { deInit(); }
- bool init();
- void process(const uint8_t *data, size_t size);
-
-private:
- void deInit();
- void invokeDrmPlugin(const uint8_t *data, size_t size);
- void invokeCryptoPlugin(const uint8_t *data);
- void invokeDrm(const uint8_t *data, size_t size);
- void invokeCrypto(const uint8_t *data);
- void invokeDrmDecryptEncryptAPI(const uint8_t *data, size_t size);
- bool invokeDrmFactory();
- bool invokeCryptoFactory();
- void invokeDrmV1_4API();
- void invokeDrmSetAlgorithmAPI();
- void invokeDrmPropertyAPI();
- void invokeDrmSecureStopAPI();
- void invokeDrmOfflineLicenseAPI(const uint8_t *data, size_t size);
- SessionId getSessionId();
- SecureStopRelease makeSecureRelease(const SecureStop &stop);
- sp<IDrmFactory> mDrmFactory = nullptr;
- sp<ICryptoFactory> mCryptoFactory = nullptr;
- sp<IDrmPlugin> mDrmPlugin = nullptr;
- sp<drm::V1_1::IDrmPlugin> mDrmPluginV1_1 = nullptr;
- sp<drm::V1_2::IDrmPlugin> mDrmPluginV1_2 = nullptr;
- sp<drm::V1_4::IDrmPlugin> mDrmPluginV1_4 = nullptr;
- sp<drm::V1_4::ICryptoPlugin> mCryptoPluginV1_4 = nullptr;
- sp<ICryptoPlugin> mCryptoPlugin = nullptr;
- FuzzedDataProvider *mFDP = nullptr;
- SessionId mSessionId = {};
- SessionId mSessionIdV1 = {};
-};
-
-void ClearKeyFuzzer::deInit() {
- if (mDrmPluginV1_1) {
- mDrmPluginV1_1->closeSession(mSessionIdV1);
- }
- if (mDrmPluginV1_2) {
- mDrmPluginV1_2->closeSession(mSessionId);
- }
- mDrmFactory.clear();
- mCryptoFactory.clear();
- mDrmPlugin.clear();
- mDrmPluginV1_1.clear();
- mDrmPluginV1_2.clear();
- mDrmPluginV1_4.clear();
- mCryptoPlugin.clear();
- mCryptoPluginV1_4.clear();
- mSessionId = {};
- mSessionIdV1 = {};
-}
-
-void ClearKeyFuzzer::invokeDrmV1_4API() {
- mDrmPluginV1_4->requiresSecureDecoderDefault(
- getValueFromArray(mFDP, kMimeType));
- mDrmPluginV1_4->requiresSecureDecoder(
- getValueFromArray(mFDP, kMimeType),
- getValueFromArray(mFDP, kSecurityLevel));
- mDrmPluginV1_4->setPlaybackId(
- mSessionId, mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
- drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
- [&]([[maybe_unused]] drm::V1_4::Status status,
- [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
- mDrmPluginV1_4->getLogMessages(cb);
-}
-
-void ClearKeyFuzzer::invokeDrmSetAlgorithmAPI() {
- const hidl_string cipherAlgo =
- mFDP->ConsumeBool()
- ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
- : hidl_string(kCipherAlgorithm[mFDP->ConsumeBool()]);
- mDrmPluginV1_2->setCipherAlgorithm(mSessionId, cipherAlgo);
-
- const hidl_string macAlgo =
- mFDP->ConsumeBool()
- ? mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str()
- : hidl_string(kMacAlgorithm[mFDP->ConsumeBool()]);
- mDrmPluginV1_2->setMacAlgorithm(mSessionId, macAlgo);
-}
-
-void ClearKeyFuzzer::invokeDrmPropertyAPI() {
- mDrmPluginV1_2->setPropertyString(
- hidl_string(getValueFromArray(mFDP, kProperty)), hidl_string("value"));
-
- hidl_string stringValue;
- mDrmPluginV1_2->getPropertyString(
- getValueFromArray(mFDP, kProperty),
- [&](Status status, const hidl_string &hValue) {
- if (status == Status::OK) {
- stringValue = hValue;
- }
- });
-
- hidl_vec<uint8_t> value = {};
- mDrmPluginV1_2->setPropertyByteArray(
- hidl_string(getValueFromArray(mFDP, kProperty)), value);
-
- hidl_vec<uint8_t> byteValue;
- mDrmPluginV1_2->getPropertyByteArray(
- getValueFromArray(mFDP, kProperty),
- [&](Status status, const hidl_vec<uint8_t> &hValue) {
- if (status == Status::OK) {
- byteValue = hValue;
- }
- });
-}
-
-SessionId ClearKeyFuzzer::getSessionId() {
- SessionId emptySessionId = {};
- return mFDP->ConsumeBool() ? mSessionId : emptySessionId;
-}
-
-void ClearKeyFuzzer::invokeDrmDecryptEncryptAPI(const uint8_t *data,
- size_t size) {
- uint32_t currSessions, maximumSessions;
- mDrmPluginV1_2->getNumberOfSessions(
- [&](Status status, uint32_t hCurrentSessions, uint32_t hMaxSessions) {
- if (status == Status::OK) {
- currSessions = hCurrentSessions;
- maximumSessions = hMaxSessions;
- }
- });
-
- HdcpLevel connected, maximum;
- mDrmPluginV1_2->getHdcpLevels([&](Status status,
- const HdcpLevel &hConnectedLevel,
- const HdcpLevel &hMaxLevel) {
- if (status == Status::OK) {
- connected = hConnectedLevel;
- maximum = hMaxLevel;
- }
- });
-
- drm::V1_2::HdcpLevel connectedV1_2, maximumV1_2;
- mDrmPluginV1_2->getHdcpLevels_1_2(
- [&](drm::V1_2::Status status, const drm::V1_2::HdcpLevel &connectedLevel,
- const drm::V1_2::HdcpLevel &maxLevel) {
- if (status == drm::V1_2::Status::OK) {
- connectedV1_2 = connectedLevel;
- maximumV1_2 = maxLevel;
- }
- });
-
- SecurityLevel securityLevel;
- mDrmPluginV1_2->getSecurityLevel(mSessionId,
- [&](Status status, SecurityLevel hLevel) {
- if (status == Status::OK) {
- securityLevel = hLevel;
- }
- });
-
- hidl_vec<DrmMetricGroup> metrics;
- mDrmPluginV1_2->getMetrics(
- [&](Status status, hidl_vec<DrmMetricGroup> hMetricGroups) {
- if (status == Status::OK) {
- metrics = hMetricGroups;
- }
- });
-
- hidl_string certificateType;
- hidl_string certificateAuthority;
- mDrmPluginV1_2->getProvisionRequest(certificateType, certificateAuthority,
- [&]([[maybe_unused]] Status status,
- const hidl_vec<uint8_t> &,
- const hidl_string &) {});
-
- mDrmPluginV1_2->getProvisionRequest_1_2(
- certificateType, certificateAuthority,
- [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
- const hidl_string &) {});
-
- hidl_vec<uint8_t> response;
- mDrmPluginV1_2->provideProvisionResponse(
- response, [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &,
- const hidl_vec<uint8_t> &) {});
-
- hidl_vec<uint8_t> initData = {};
- if (mFDP->ConsumeBool()) {
- initData = validInitData;
- } else {
- initData.setToExternal(const_cast<uint8_t *>(data), kAESBlockSize);
- }
- hidl_string mimeType = getValueFromArray(mFDP, kMimeType);
- KeyType keyType = mFDP->ConsumeBool()
- ? static_cast<KeyType>(mFDP->ConsumeIntegral<size_t>())
- : getValueFromArray(mFDP, kKeyType);
- KeyedVector optionalParameters;
- mDrmPluginV1_2->getKeyRequest_1_2(
- mSessionId, initData, mimeType, keyType, optionalParameters,
- [&]([[maybe_unused]] drm::V1_2::Status status, const hidl_vec<uint8_t> &,
- drm::V1_1::KeyRequestType, const hidl_string &) {});
- mDrmPluginV1_1->getKeyRequest_1_1(
- mSessionIdV1, initData, mimeType, keyType, optionalParameters,
- [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
- drm::V1_1::KeyRequestType, const hidl_string &) {});
- hidl_vec<uint8_t> emptyInitData = {};
- mDrmPlugin->getKeyRequest(
- mSessionId, mFDP->ConsumeBool() ? initData : emptyInitData, mimeType,
- keyType, optionalParameters,
- [&]([[maybe_unused]] drm::V1_0::Status status, const hidl_vec<uint8_t> &,
- drm::V1_0::KeyRequestType, const hidl_string &) {});
-
- hidl_vec<uint8_t> keyResponse = {};
- if (mFDP->ConsumeBool()) {
- keyResponse = validKeyResponse;
- } else {
- keyResponse.setToExternal(const_cast<uint8_t *>(data), size);
- }
- hidl_vec<uint8_t> keySetId;
- hidl_vec<uint8_t> emptyKeyResponse = {};
- mDrmPluginV1_2->provideKeyResponse(
- getSessionId(), mFDP->ConsumeBool() ? keyResponse : emptyKeyResponse,
- [&](Status status, const hidl_vec<uint8_t> &hKeySetId) {
- if (status == Status::OK) {
- keySetId = hKeySetId;
- }
- });
-
- mDrmPluginV1_2->restoreKeys(getSessionId(), keySetId);
-
- mDrmPluginV1_2->queryKeyStatus(
- getSessionId(),
- [&]([[maybe_unused]] Status status, KeyedVector /* info */) {});
-
- hidl_vec<uint8_t> keyId, input, iv;
- keyId.setToExternal(const_cast<uint8_t *>(data), size);
- input.setToExternal(const_cast<uint8_t *>(data), size);
- iv.setToExternal(const_cast<uint8_t *>(data), size);
- mDrmPluginV1_2->encrypt(
- getSessionId(), keyId, input, iv,
- [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
- mDrmPluginV1_2->decrypt(
- getSessionId(), keyId, input, iv,
- [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
- hidl_vec<uint8_t> message;
- message.setToExternal(const_cast<uint8_t *>(data), size);
- mDrmPluginV1_2->sign(
- getSessionId(), keyId, message,
- [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
- hidl_vec<uint8_t> signature;
- signature.setToExternal(const_cast<uint8_t *>(data), size);
- mDrmPluginV1_2->verify(getSessionId(), keyId, message, signature,
- [&]([[maybe_unused]] Status status, bool) {});
-
- hidl_vec<uint8_t> wrappedKey;
- signature.setToExternal(const_cast<uint8_t *>(data), size);
- mDrmPluginV1_2->signRSA(
- getSessionId(), kRSAAlgorithm[mFDP->ConsumeBool()], message, wrappedKey,
- [&]([[maybe_unused]] Status status, const hidl_vec<uint8_t> &) {});
-
- mDrmPluginV1_2->removeKeys(getSessionId());
-}
-
-/**
- * Helper function to create a secure release message for
- * a secure stop. The clearkey secure stop release format
- * is just a count followed by the secure stop opaque data.
- */
-SecureStopRelease ClearKeyFuzzer::makeSecureRelease(const SecureStop &stop) {
- std::vector<uint8_t> stopData = stop.opaqueData;
- std::vector<uint8_t> buffer;
- std::string count = "0001";
-
- auto it = buffer.insert(buffer.begin(), count.begin(), count.end());
- buffer.insert(it + count.size(), stopData.begin(), stopData.end());
- SecureStopRelease release = {.opaqueData = hidl_vec<uint8_t>(buffer)};
- return release;
-}
-
-void ClearKeyFuzzer::invokeDrmSecureStopAPI() {
- SecureStopId ssid;
- mDrmPluginV1_2->getSecureStop(
- ssid, [&]([[maybe_unused]] Status status, const SecureStop &) {});
-
- mDrmPluginV1_2->getSecureStopIds(
- [&]([[maybe_unused]] Status status,
- [[maybe_unused]] const hidl_vec<SecureStopId> &secureStopIds) {});
-
- SecureStopRelease release;
- mDrmPluginV1_2->getSecureStops(
- [&]([[maybe_unused]] Status status, const hidl_vec<SecureStop> &stops) {
- if (stops.size() > 0) {
- release = makeSecureRelease(
- stops[mFDP->ConsumeIntegralInRange<size_t>(0, stops.size() - 1)]);
- }
- });
-
- mDrmPluginV1_2->releaseSecureStops(release);
-
- mDrmPluginV1_2->removeSecureStop(ssid);
-
- mDrmPluginV1_2->removeAllSecureStops();
-
- mDrmPluginV1_2->releaseSecureStop(ssid);
-
- mDrmPluginV1_2->releaseAllSecureStops();
-}
-
-void ClearKeyFuzzer::invokeDrmOfflineLicenseAPI(const uint8_t *data,
- size_t size) {
- hidl_vec<KeySetId> keySetIds = {};
- mDrmPluginV1_2->getOfflineLicenseKeySetIds(
- [&](Status status, const hidl_vec<KeySetId> &hKeySetIds) {
- if (status == Status::OK) {
- keySetIds = hKeySetIds;
- }
- });
-
- OfflineLicenseState licenseState;
- KeySetId keySetId = {};
- if (keySetIds.size() > 0) {
- keySetId = keySetIds[mFDP->ConsumeIntegralInRange<size_t>(
- 0, keySetIds.size() - 1)];
- } else {
- keySetId.setToExternal(const_cast<uint8_t *>(data), size);
- }
- mDrmPluginV1_2->getOfflineLicenseState(
- keySetId, [&](Status status, OfflineLicenseState hLicenseState) {
- if (status == Status::OK) {
- licenseState = hLicenseState;
- }
- });
-
- mDrmPluginV1_2->removeOfflineLicense(keySetId);
-}
-
-void ClearKeyFuzzer::invokeDrmPlugin(const uint8_t *data, size_t size) {
- SecurityLevel secLevel =
- mFDP->ConsumeBool()
- ? getValueFromArray(mFDP, kSecurityLevel)
- : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
- mDrmPluginV1_1->openSession_1_1(
- secLevel, [&]([[maybe_unused]] Status status, const SessionId &id) {
- mSessionIdV1 = id;
- });
- mDrmPluginV1_2->openSession([&]([[maybe_unused]] Status status,
- const SessionId &id) { mSessionId = id; });
-
- sp<TestDrmPluginListener> listener = new TestDrmPluginListener();
- mDrmPluginV1_2->setListener(listener);
- const hidl_vec<KeyStatus> keyStatusList = {
- {{1}, KeyStatusType::USABLE},
- {{2}, KeyStatusType::EXPIRED},
- {{3}, KeyStatusType::OUTPUTNOTALLOWED},
- {{4}, KeyStatusType::STATUSPENDING},
- {{5}, KeyStatusType::INTERNALERROR},
- };
- mDrmPluginV1_2->sendKeysChange(mSessionId, keyStatusList, true);
-
- invokeDrmV1_4API();
- invokeDrmSetAlgorithmAPI();
- invokeDrmPropertyAPI();
- invokeDrmDecryptEncryptAPI(data, size);
- invokeDrmSecureStopAPI();
- invokeDrmOfflineLicenseAPI(data, size);
-}
-
-void ClearKeyFuzzer::invokeCryptoPlugin(const uint8_t *data) {
- mCryptoPlugin->requiresSecureDecoderComponent(
- getValueFromArray(mFDP, kMimeType));
-
- const uint32_t width = mFDP->ConsumeIntegral<uint32_t>();
- const uint32_t height = mFDP->ConsumeIntegral<uint32_t>();
- mCryptoPlugin->notifyResolution(width, height);
-
- mCryptoPlugin->setMediaDrmSession(mSessionId);
-
- size_t totalSize = 0;
- const size_t numSubSamples =
- mFDP->ConsumeIntegralInRange<size_t>(1, kMaxSubSamples);
-
- const Pattern pattern = {0, 0};
- hidl_vec<SubSample> subSamples;
- subSamples.resize(numSubSamples);
-
- for (size_t i = 0; i < numSubSamples; ++i) {
- const uint32_t clearBytes =
- mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
- const uint32_t encryptedBytes =
- mFDP->ConsumeIntegralInRange<uint32_t>(0, kMaxNumBytes);
- subSamples[i].numBytesOfClearData = clearBytes;
- subSamples[i].numBytesOfEncryptedData = encryptedBytes;
- totalSize += subSamples[i].numBytesOfClearData;
- totalSize += subSamples[i].numBytesOfEncryptedData;
- }
-
- // The first totalSize bytes of shared memory is the encrypted
- // input, the second totalSize bytes is the decrypted output.
- size_t memoryBytes = totalSize * 2;
-
- sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
- if (!ashmemAllocator.get()) {
- return;
- }
-
- hidl_memory hidlMemory;
- ashmemAllocator->allocate(memoryBytes, [&]([[maybe_unused]] bool success,
- const hidl_memory &memory) {
- mCryptoPlugin->setSharedBufferBase(memory, kSegmentIndex);
- hidlMemory = memory;
- });
-
- sp<IMemory> mappedMemory = mapMemory(hidlMemory);
- if (!mappedMemory.get()) {
- return;
- }
- mCryptoPlugin->setSharedBufferBase(hidlMemory, kSegmentIndex);
-
- uint32_t srcBufferId =
- mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
- const SharedBuffer sourceBuffer = {
- .bufferId = srcBufferId, .offset = 0, .size = totalSize};
-
- BufferType type = mFDP->ConsumeBool() ? BufferType::SHARED_MEMORY
- : BufferType::NATIVE_HANDLE;
- uint32_t destBufferId =
- mFDP->ConsumeBool() ? kSegmentIndex : mFDP->ConsumeIntegral<uint32_t>();
- const DestinationBuffer destBuffer = {
- .type = type,
- {.bufferId = destBufferId, .offset = totalSize, .size = totalSize},
- .secureMemory = nullptr};
-
- const uint64_t offset = 0;
- uint32_t bytesWritten = 0;
- hidl_array<uint8_t, kAESBlockSize> keyId =
- hidl_array<uint8_t, kAESBlockSize>(data);
- hidl_array<uint8_t, kAESBlockSize> iv =
- hidl_array<uint8_t, kAESBlockSize>(data);
- Mode mode = getValueFromArray(mFDP, kCryptoMode);
- mCryptoPlugin->decrypt(
- mFDP->ConsumeBool(), keyId, iv, mode, pattern, subSamples, sourceBuffer,
- offset, destBuffer,
- [&]([[maybe_unused]] Status status, uint32_t count,
- [[maybe_unused]] string detailedError) { bytesWritten = count; });
- drm::V1_4::IDrmPlugin::getLogMessages_cb cb =
- [&]([[maybe_unused]] drm::V1_4::Status status,
- [[maybe_unused]] hidl_vec<drm::V1_4::LogMessage> logs) {};
- mCryptoPluginV1_4->getLogMessages(cb);
-}
-
-bool ClearKeyFuzzer::invokeDrmFactory() {
- hidl_string packageName(
- mFDP->ConsumeRandomLengthString(kMaxStringLength).c_str());
- hidl_string mimeType(getValueFromArray(mFDP, kMimeType));
- SecurityLevel securityLevel =
- mFDP->ConsumeBool()
- ? getValueFromArray(mFDP, kSecurityLevel)
- : static_cast<SecurityLevel>(mFDP->ConsumeIntegral<uint32_t>());
- const hidl_array<uint8_t, 16> uuid =
- mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
- mDrmFactory->isCryptoSchemeSupported_1_2(uuid, mimeType, securityLevel);
- mDrmFactory->createPlugin(
- uuid, packageName, [&](Status status, const sp<IDrmPlugin> &plugin) {
- if (status == Status::OK) {
- mDrmPlugin = plugin.get();
- mDrmPluginV1_1 = drm::V1_1::IDrmPlugin::castFrom(mDrmPlugin);
- mDrmPluginV1_2 = drm::V1_2::IDrmPlugin::castFrom(mDrmPlugin);
- mDrmPluginV1_4 = drm::V1_4::IDrmPlugin::castFrom(mDrmPlugin);
- }
- });
-
- std::vector<hidl_array<uint8_t, 16>> supportedSchemes;
- mDrmFactory->getSupportedCryptoSchemes(
- [&](const hidl_vec<hidl_array<uint8_t, 16>> &schemes) {
- for (const auto &scheme : schemes) {
- supportedSchemes.push_back(scheme);
- }
- });
-
- if (!(mDrmPlugin && mDrmPluginV1_1 && mDrmPluginV1_2 && mDrmPluginV1_4)) {
- return false;
- }
- return true;
-}
-
-bool ClearKeyFuzzer::invokeCryptoFactory() {
- const hidl_array<uint8_t, 16> uuid =
- mFDP->ConsumeBool() ? kClearKeyUUID : kInvalidUUID;
- mCryptoFactory->createPlugin(
- uuid, mSessionId, [this](Status status, const sp<ICryptoPlugin> &plugin) {
- if (status == Status::OK) {
- mCryptoPlugin = plugin;
- mCryptoPluginV1_4 = drm::V1_4::ICryptoPlugin::castFrom(mCryptoPlugin);
- }
- });
-
- if (!mCryptoPlugin && !mCryptoPluginV1_4) {
- return false;
- }
- return true;
-}
-
-void ClearKeyFuzzer::invokeDrm(const uint8_t *data, size_t size) {
- if (!invokeDrmFactory()) {
- return;
- }
- invokeDrmPlugin(data, size);
-}
-
-void ClearKeyFuzzer::invokeCrypto(const uint8_t *data) {
- if (!invokeCryptoFactory()) {
- return;
- }
- invokeCryptoPlugin(data);
-}
-
-void ClearKeyFuzzer::process(const uint8_t *data, size_t size) {
- mFDP = new FuzzedDataProvider(data, size);
- invokeDrm(data, size);
- invokeCrypto(data);
- delete mFDP;
-}
-
-bool ClearKeyFuzzer::init() {
- mCryptoFactory =
- android::hardware::drm::V1_4::clearkey::createCryptoFactory();
- mDrmFactory = android::hardware::drm::V1_4::clearkey::createDrmFactory();
- if (!mDrmFactory && !mCryptoFactory) {
- return false;
- }
- return true;
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
- if (size < kAESBlockSize) {
- return 0;
- }
- ClearKeyFuzzer clearKeyFuzzer;
- if (clearKeyFuzzer.init()) {
- clearKeyFuzzer.process(data, size);
- }
- return 0;
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
deleted file mode 100644
index 97794f7..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/AesCtrDecryptor.h
+++ /dev/null
@@ -1,50 +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.
- */
-
-#ifndef CLEARKEY_AES_CTR_DECRYPTOR_H_
-#define CLEARKEY_AES_CTR_DECRYPTOR_H_
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-using ::android::hardware::drm::V1_0::SubSample;
-
-class AesCtrDecryptor {
-public:
- AesCtrDecryptor() {}
-
- Status decrypt(const std::vector<uint8_t>& key, const Iv iv,
- const uint8_t* source, uint8_t* destination,
- const std::vector<SubSample> subSamples, size_t numSubSamples,
- size_t* bytesDecryptedOut);
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(AesCtrDecryptor);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_AES_CTR_DECRYPTOR_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h b/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
deleted file mode 100644
index 2349f23..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Base64.h
+++ /dev/null
@@ -1,46 +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.
- */
-
-#ifndef BASE_64_H_
-
-#define BASE_64_H_
-
-#include <android/hardware/drm/1.0/types.h>
-
-#include "Buffer.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-struct Buffer;
-
-sp<Buffer> decodeBase64(const std::string &s);
-void encodeBase64(const void *data, size_t size, std::string *out);
-
-void encodeBase64Url(const void *data, size_t size, std::string *out);
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // BASE_64_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h b/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
deleted file mode 100644
index 66aaa73..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Buffer.h
+++ /dev/null
@@ -1,62 +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.
- */
-
-#ifndef BUFFER_H_
-#define BUFFER_H_
-
-#include <android/hardware/drm/1.0/types.h>
-#include <utils/RefBase.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-struct Buffer : public RefBase {
- explicit Buffer(size_t capacity);
-
- uint8_t *base() { return reinterpret_cast<uint8_t *>(mData); }
- uint8_t *data() { return reinterpret_cast<uint8_t *>(mData) + mRangeOffset; }
- size_t capacity() const { return mCapacity; }
- size_t size() const { return mRangeLength; }
- size_t offset() const { return mRangeOffset; }
-
-protected:
- virtual ~Buffer();
-
-private:
- void *mData;
- size_t mCapacity;
- size_t mRangeOffset;
- size_t mRangeLength;
-
- bool mOwnsData;
-
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Buffer);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // BUFFER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
deleted file mode 100644
index 8e47c45..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyDrmProperties.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef CLEARKEY_DRM_PROPERTIES_H_
-#define CLEARKEY_DRM_PROPERTIES_H_
-
-#include <string.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-static const std::string kVendorKey("vendor");
-static const std::string kVendorValue("Google");
-static const std::string kVersionKey("version");
-static const std::string kVersionValue("1.2");
-static const std::string kPluginDescriptionKey("description");
-static const std::string kPluginDescriptionValue("ClearKey CDM");
-static const std::string kAlgorithmsKey("algorithms");
-static const std::string kAlgorithmsValue("");
-static const std::string kListenerTestSupportKey("listenerTestSupport");
-static const std::string kListenerTestSupportValue("true");
-static const std::string kDrmErrorTestKey("drmErrorTest");
-static const std::string kDrmErrorTestValue("");
-static const std::string kResourceContentionValue("resourceContention");
-static const std::string kLostStateValue("lostState");
-static const std::string kFrameTooLargeValue("frameTooLarge");
-static const std::string kInvalidStateValue("invalidState");
-
-static const std::string kDeviceIdKey("deviceId");
-static const uint8_t kTestDeviceIdData[] =
- {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
- 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
-
-// settable byte array property
-static const std::string kClientIdKey("clientId");
-
-// TODO stub out metrics for nw
-static const std::string kMetricsKey("metrics");
-static const uint8_t kMetricsData[] = { 0 };
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_PROPERTIES_H_
-
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h b/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
deleted file mode 100644
index cd18029..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/ClearKeyTypes.h
+++ /dev/null
@@ -1,56 +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.
- */
-
-#ifndef CLEARKEY_MACROS_H_
-#define CLEARKEY_MACROS_H_
-
-#include <android/hardware/drm/1.2/types.h>
-
-#include <map>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::KeyValue;
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::hidl_vec;
-
-const uint8_t kBlockSize = 16; //AES_BLOCK_SIZE;
-typedef uint8_t KeyId[kBlockSize];
-typedef uint8_t Iv[kBlockSize];
-
-typedef ::android::hardware::drm::V1_0::SubSample SubSample;
-typedef std::map<std::vector<uint8_t>, std::vector<uint8_t> > KeyMap;
-
-#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&) = delete; \
- void operator=(const TypeName&) = delete;
-
-#define CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(TypeName) \
- TypeName() = delete; \
- TypeName(const TypeName&) = delete; \
- void operator=(const TypeName&) = delete;
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_MACROS_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h b/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
deleted file mode 100644
index d4a8a17..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CreatePluginFactories.h
+++ /dev/null
@@ -1,42 +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.
- */
-
-#ifndef CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
-#define CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
-
-#include <android/hardware/drm/1.4/ICryptoFactory.h>
-#include <android/hardware/drm/1.4/IDrmFactory.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_4::ICryptoFactory;
-using ::android::hardware::drm::V1_4::IDrmFactory;
-
-extern "C" {
- IDrmFactory* createDrmFactory();
- ICryptoFactory* createCryptoFactory();
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-#endif // CLEARKEY_CREATE_PLUGIN_FACTORIES_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
deleted file mode 100644
index e6b541f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoFactory.h
+++ /dev/null
@@ -1,60 +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.
- */
-
-#ifndef CLEARKEY_CRYPTO_FACTORY_H_
-#define CLEARKEY_CRYPTO_FACTORY_H_
-
-#include <android/hardware/drm/1.0/ICryptoPlugin.h>
-#include <android/hardware/drm/1.4/ICryptoFactory.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_4::ICryptoFactory;
-using ::android::hardware::drm::V1_0::ICryptoPlugin;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_string;
-using ::android::hardware::Return;
-
-struct CryptoFactory : public ICryptoFactory {
- CryptoFactory() {}
- virtual ~CryptoFactory() {}
-
- Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
- override;
-
- Return<void> createPlugin(
- const hidl_array<uint8_t, 16>& uuid,
- const hidl_vec<uint8_t>& initData,
- createPlugin_cb _hidl_cb) override;
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoFactory);
-
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_CRYPTO_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
deleted file mode 100644
index b272a83..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/CryptoPlugin.h
+++ /dev/null
@@ -1,124 +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.
- */
-
-#ifndef CLEARKEY_CRYPTO_PLUGIN_H_
-#define CLEARKEY_CRYPTO_PLUGIN_H_
-
-#include <android/hardware/drm/1.4/ICryptoPlugin.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-
-#include <mutex>
-
-#include "ClearKeyTypes.h"
-#include "Session.h"
-#include "Utils.h"
-
-namespace {
- static const size_t KEY_ID_SIZE = 16;
- static const size_t KEY_IV_SIZE = 16;
-}
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::DestinationBuffer;
-using drm::V1_0::Mode;
-using drm::V1_0::Pattern;
-using drm::V1_0::SharedBuffer;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::sp;
-
-typedef drm::V1_2::Status Status_V1_2;
-
-struct CryptoPlugin : public drm::V1_4::ICryptoPlugin {
- explicit CryptoPlugin(const hidl_vec<uint8_t>& sessionId) {
- mInitStatus = setMediaDrmSession(sessionId);
- }
- virtual ~CryptoPlugin() {}
-
- Return<bool> requiresSecureDecoderComponent(const hidl_string& mime) {
- UNUSED(mime);
- return false;
- }
-
- Return<void> notifyResolution(uint32_t width, uint32_t height) {
- UNUSED(width);
- UNUSED(height);
- return Void();
- }
-
- Return<void> decrypt(
- bool secure,
- const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
- const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
- Mode mode,
- const Pattern& pattern,
- const hidl_vec<SubSample>& subSamples,
- const SharedBuffer& source,
- uint64_t offset,
- const DestinationBuffer& destination,
- decrypt_cb _hidl_cb);
-
- Return<void> decrypt_1_2(
- bool secure,
- const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
- const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
- Mode mode,
- const Pattern& pattern,
- const hidl_vec<SubSample>& subSamples,
- const SharedBuffer& source,
- uint64_t offset,
- const DestinationBuffer& destination,
- decrypt_1_2_cb _hidl_cb) NO_THREAD_SAFETY_ANALYSIS; // use unique_lock
-
- Return<void> setSharedBufferBase(const hidl_memory& base,
- uint32_t bufferId);
-
- Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId);
-
- Return<Status> getInitStatus() const { return mInitStatus; }
-
- Return<void> getLogMessages(
- getLogMessages_cb _hidl_cb);
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(CryptoPlugin);
-
- std::mutex mSharedBufferLock;
- std::map<uint32_t, sp<IMemory>> mSharedBufferMap GUARDED_BY(mSharedBufferLock);
- sp<Session> mSession;
- Status mInitStatus;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_CRYPTO_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h b/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
deleted file mode 100644
index 6466ac3..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DeviceFiles.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-#ifndef CLEARKEY_DEVICE_FILES_H_
-#define CLEARKEY_DEVICE_FILES_H_
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "protos/DeviceFiles.pb.h"
-#include "ClearKeyTypes.h"
-#include "MemoryFileSystem.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_2::clearkey::OfflineFile;
-
-class DeviceFiles {
- public:
- typedef enum {
- kLicenseStateUnknown,
- kLicenseStateActive,
- kLicenseStateReleasing,
- } LicenseState;
-
- DeviceFiles() {};
- virtual ~DeviceFiles() {};
-
- virtual bool StoreLicense(const std::string& keySetId, LicenseState state,
- const std::string& keyResponse);
-
- virtual bool RetrieveLicense(
- const std::string& key_set_id, LicenseState* state, std::string* offlineLicense);
-
- virtual bool LicenseExists(const std::string& keySetId);
-
- virtual std::vector<std::string> ListLicenses() const;
-
- virtual bool DeleteLicense(const std::string& keySetId);
-
- virtual bool DeleteAllLicenses();
-
- private:
- bool FileExists(const std::string& path) const;
- ssize_t GetFileSize(const std::string& fileName) const;
- bool RemoveFile(const std::string& fileName);
-
- bool RetrieveHashedFile(const std::string& fileName, OfflineFile* deSerializedFile);
- bool StoreFileRaw(const std::string& fileName, const std::string& serializedFile);
- bool StoreFileWithHash(const std::string& fileName, const std::string& serializedFile);
-
- MemoryFileSystem mFileHandle;
-
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DeviceFiles);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DEVICE_FILES_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
deleted file mode 100644
index fea1ec8..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmFactory.h
+++ /dev/null
@@ -1,71 +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.
- */
-
-#ifndef CLEARKEY_DRM_FACTORY_H_
-#define CLEARKEY_DRM_FACTORY_H_
-
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.4/IDrmFactory.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_1::SecurityLevel;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_handle;
-using ::android::hardware::hidl_string;
-using ::android::hardware::Return;
-
-struct DrmFactory : public IDrmFactory {
- DrmFactory() {}
- virtual ~DrmFactory() {}
-
- Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
- override;
-
- Return<bool> isCryptoSchemeSupported_1_2(const hidl_array<uint8_t, 16>& uuid,
- const hidl_string& mimeType,
- SecurityLevel level) override;
-
- Return<bool> isContentTypeSupported(const hidl_string &mimeType)
- override;
-
- Return<void> createPlugin(
- const hidl_array<uint8_t, 16>& uuid,
- const hidl_string& appPackageName,
- createPlugin_cb _hidl_cb) override;
-
- Return<void> getSupportedCryptoSchemes(
- getSupportedCryptoSchemes_cb _hidl_cb) override;
-
- Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args);
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(DrmFactory);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_FACTORY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
deleted file mode 100644
index 1019520..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ /dev/null
@@ -1,449 +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.
- */
-
-#ifndef CLEARKEY_DRM_PLUGIN_H_
-#define CLEARKEY_DRM_PLUGIN_H_
-
-#include <android/hardware/drm/1.4/IDrmPlugin.h>
-#include <android/hardware/drm/1.2/IDrmPluginListener.h>
-
-#include <map>
-#include <stdio.h>
-
-#include <utils/List.h>
-
-#include "DeviceFiles.h"
-#include "SessionLibrary.h"
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::EventType;
-using drm::V1_0::IDrmPluginListener;
-using drm::V1_0::KeyRequestType;
-using drm::V1_0::KeyStatus;
-using drm::V1_0::KeyType;
-using drm::V1_0::KeyValue;
-using drm::V1_0::SecureStop;
-using drm::V1_0::SecureStopId;
-using drm::V1_0::SessionId;
-using drm::V1_0::Status;
-using drm::V1_1::DrmMetricGroup;
-using drm::V1_1::HdcpLevel;
-using drm::V1_1::SecureStopRelease;
-using drm::V1_1::SecurityLevel;
-using drm::V1_2::KeySetId;
-using drm::V1_2::OfflineLicenseState;
-using drm::V1_4::clearkey::DeviceFiles;
-using drm::V1_4::clearkey::Session;
-using drm::V1_4::clearkey::SessionLibrary;
-using drm::V1_4::IDrmPlugin;
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::sp;
-
-typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
-typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
-typedef drm::V1_2::KeyStatus KeyStatus_V1_2;
-typedef drm::V1_2::Status Status_V1_2;
-typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;
-
-struct DrmPlugin : public IDrmPlugin {
- explicit DrmPlugin(SessionLibrary* sessionLibrary);
-
- virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); }
-
- Return<void> openSession(openSession_cb _hidl_cb) override;
- Return<void> openSession_1_1(SecurityLevel securityLevel,
- openSession_cb _hidl_cb) override;
-
- Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
-
- Return<void> getKeyRequest(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_cb _hidl_cb) override;
-
- Return<void> getKeyRequest_1_1(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_1_1_cb _hidl_cb) override;
-
- Return<void> getKeyRequest_1_2(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- getKeyRequest_1_2_cb _hidl_cb) override;
-
- Return<void> provideKeyResponse(
- const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& response,
- provideKeyResponse_cb _hidl_cb) override;
-
- Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) {
- if (sessionId.size() == 0) {
- return Status::BAD_VALUE;
- }
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<Status> restoreKeys(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& keySetId) override;
-
- Return<void> queryKeyStatus(
- const hidl_vec<uint8_t>& sessionId,
- queryKeyStatus_cb _hidl_cb) override;
-
- Return<void> getProvisionRequest(
- const hidl_string& certificateType,
- const hidl_string& certificateAuthority,
- getProvisionRequest_cb _hidl_cb) {
- UNUSED(certificateType);
- UNUSED(certificateAuthority);
-
- hidl_string defaultUrl;
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
- return Void();
- }
-
- Return<void> getProvisionRequest_1_2(
- const hidl_string& certificateType,
- const hidl_string& certificateAuthority,
- getProvisionRequest_1_2_cb _hidl_cb) {
- UNUSED(certificateType);
- UNUSED(certificateAuthority);
-
- hidl_string defaultUrl;
- _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
- return Void();
- }
-
- Return<void> provideProvisionResponse(
- const hidl_vec<uint8_t>& response,
- provideProvisionResponse_cb _hidl_cb) {
-
- if (response.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
- return Void();
- }
-
- Return<void> getHdcpLevels(getHdcpLevels_cb _hidl_cb) {
- HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE;
- HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
- _hidl_cb(Status::OK, connectedLevel, maxLevel);
- return Void();
- }
-
- Return<void> getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) {
- HdcpLevel_V1_2 connectedLevel = HdcpLevel_V1_2::HDCP_NONE;
- HdcpLevel_V1_2 maxLevel = HdcpLevel_V1_2::HDCP_NO_OUTPUT;
- _hidl_cb(Status_V1_2::OK, connectedLevel, maxLevel);
- return Void();
- }
-
- Return<void> getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override;
-
- Return<void> getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
- getSecurityLevel_cb _hidl_cb) override;
-
- Return<void> getMetrics(getMetrics_cb _hidl_cb) override;
-
- Return<void> getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) override;
-
- Return<Status> removeOfflineLicense(const KeySetId &keySetId) override;
-
- Return<void> getOfflineLicenseState(const KeySetId &keySetId,
- getOfflineLicenseState_cb _hidl_cb) override;
-
- Return<void> getPropertyString(
- const hidl_string& name,
- getPropertyString_cb _hidl_cb) override;
-
- Return<void> getPropertyByteArray(
- const hidl_string& name,
- getPropertyByteArray_cb _hidl_cb) override;
-
- Return<Status> setPropertyString(
- const hidl_string& name, const hidl_string& value) override;
-
- Return<Status> setPropertyByteArray(
- const hidl_string& name, const hidl_vec<uint8_t>& value) override;
-
- Return<void> getLogMessages(
- getLogMessages_cb _hidl_cb) override;
-
- Return<Status> setPlaybackId(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_string& playbackId) override;
-
- Return<bool> requiresSecureDecoder(
- const hidl_string& mime, SecurityLevel level) override;
-
- Return<bool> requiresSecureDecoderDefault(const hidl_string& mime) override;
-
- Return<Status> setCipherAlgorithm(
- const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
- if (sessionId.size() == 0 || algorithm.size() == 0) {
- return Status::BAD_VALUE;
- }
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<Status> setMacAlgorithm(
- const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
- if (sessionId.size() == 0 || algorithm.size() == 0) {
- return Status::BAD_VALUE;
- }
- return Status::ERROR_DRM_CANNOT_HANDLE;
- }
-
- Return<void> encrypt(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& keyId,
- const hidl_vec<uint8_t>& input,
- const hidl_vec<uint8_t>& iv,
- encrypt_cb _hidl_cb) {
- if (sessionId.size() == 0 || keyId.size() == 0 ||
- input.size() == 0 || iv.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
- return Void();
- }
-
- Return<void> decrypt(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& keyId,
- const hidl_vec<uint8_t>& input,
- const hidl_vec<uint8_t>& iv,
- decrypt_cb _hidl_cb) {
- if (sessionId.size() == 0 || keyId.size() == 0 ||
- input.size() == 0 || iv.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
- return Void();
- }
-
- Return<void> sign(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& keyId,
- const hidl_vec<uint8_t>& message,
- sign_cb _hidl_cb) {
- if (sessionId.size() == 0 || keyId.size() == 0 ||
- message.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
- return Void();
- }
-
- Return<void> verify(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& keyId,
- const hidl_vec<uint8_t>& message,
- const hidl_vec<uint8_t>& signature,
- verify_cb _hidl_cb) {
-
- if (sessionId.size() == 0 || keyId.size() == 0 ||
- message.size() == 0 || signature.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, false);
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, false);
- return Void();
- }
-
- Return<void> signRSA(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_string& algorithm,
- const hidl_vec<uint8_t>& message,
- const hidl_vec<uint8_t>& wrappedKey,
- signRSA_cb _hidl_cb) {
- if (sessionId.size() == 0 || algorithm.size() == 0 ||
- message.size() == 0 || wrappedKey.size() == 0) {
- _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
- return Void();
- }
- _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
- return Void();
- }
-
- Return<void> setListener(const sp<IDrmPluginListener>& listener) {
- mListener = listener;
- mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener);
- return Void();
- };
-
- Return<void> sendEvent(
- EventType eventType,
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<uint8_t>& data) {
- if (mListenerV1_2 != NULL) {
- mListenerV1_2->sendEvent(eventType, sessionId, data);
- } else if (mListener != NULL) {
- mListener->sendEvent(eventType, sessionId, data);
- } else {
- ALOGE("Null event listener, event not sent");
- }
- return Void();
- }
-
- Return<void> sendExpirationUpdate(
- const hidl_vec<uint8_t>& sessionId,
- int64_t expiryTimeInMS) {
- if (mListenerV1_2 != NULL) {
- mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS);
- } else if (mListener != NULL) {
- mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
- } else {
- ALOGE("Null event listener, event not sent");
- }
- return Void();
- }
-
- Return<void> sendKeysChange(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
- if (mListenerV1_2 != NULL) {
- mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
- } else if (mListener != NULL) {
- mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
- } else {
- ALOGE("Null event listener, event not sent");
- }
- return Void();
- }
-
- Return<void> sendKeysChange_1_2(
- const hidl_vec<uint8_t>& sessionId,
- const hidl_vec<KeyStatus_V1_2>& keyStatusList, bool hasNewUsableKey) {
- if (mListenerV1_2 != NULL) {
- mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey);
- }
- return Void();
- }
-
- Return<void> sendSessionLostState(
- const hidl_vec<uint8_t>& sessionId) {
- if (mListenerV1_2 != NULL) {
- mListenerV1_2->sendSessionLostState(sessionId);
- }
- return Void();
- }
-
- Return<void> getSecureStops(getSecureStops_cb _hidl_cb);
-
- Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
- getSecureStop_cb _hidl_cb);
-
- Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& ssRelease);
-
- Return<Status> releaseAllSecureStops();
-
- Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb);
-
- Return<Status> releaseSecureStops(const SecureStopRelease& ssRelease);
-
- Return<Status> removeSecureStop(const hidl_vec<uint8_t>& secureStopId);
-
- Return<Status> removeAllSecureStops();
-
-private:
- void initProperties();
- void installSecureStop(const hidl_vec<uint8_t>& sessionId);
- bool makeKeySetId(std::string* keySetId);
- void setPlayPolicy();
-
- Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
- SecurityLevel level);
-
- Status_V1_2 getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
- const hidl_vec<uint8_t>& initData,
- const hidl_string& mimeType,
- KeyType keyType,
- const hidl_vec<KeyValue>& optionalParameters,
- std::vector<uint8_t> *request,
- KeyRequestType_V1_1 *getKeyRequestType,
- std::string *defaultUrl);
-
- struct ClearkeySecureStop {
- std::vector<uint8_t> id;
- std::vector<uint8_t> data;
- };
-
- std::map<std::vector<uint8_t>, ClearkeySecureStop> mSecureStops;
- std::vector<KeyValue> mPlayPolicy;
- std::map<std::string, std::string> mStringProperties;
- std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
- std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
- std::map<std::vector<uint8_t>, std::string> mPlaybackId;
- std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel
- GUARDED_BY(mSecurityLevelLock);
- sp<IDrmPluginListener> mListener;
- sp<IDrmPluginListener_V1_2> mListenerV1_2;
- SessionLibrary *mSessionLibrary;
- int64_t mOpenSessionOkCount;
- int64_t mCloseSessionOkCount;
- int64_t mCloseSessionNotOpenedCount;
- uint32_t mNextSecureStopId;
- android::Mutex mPlayPolicyLock;
-
- // set by property to mock error scenarios
- Status_V1_2 mMockError;
-
- void processMockError(const sp<Session> &session) {
- session->setMockError(mMockError);
- mMockError = Status_V1_2::OK;
- }
-
- DeviceFiles mFileHandle;
- Mutex mSecureStopLock;
- Mutex mSecurityLevelLock;
-
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_DRM_PLUGIN_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h b/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
deleted file mode 100644
index 59338c9..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/InitDataParser.h
+++ /dev/null
@@ -1,57 +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.
- */
-
-#ifndef CLEARKEY_INIT_DATA_PARSER_H_
-#define CLEARKEY_INIT_DATA_PARSER_H_
-
-#include <android/hardware/drm/1.0/types.h>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::drm::V1_0::Status;
-
-class InitDataParser {
-public:
- InitDataParser() {}
-
- Status parse(const std::vector<uint8_t>& initData,
- const std::string& mimeType,
- V1_0::KeyType keyType,
- std::vector<uint8_t>* licenseRequest);
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(InitDataParser);
-
- Status parsePssh(const std::vector<uint8_t>& initData,
- std::vector<const uint8_t*>* keyIds);
-
- std::string generateRequest(V1_0::KeyType keyType,
- const std::vector<const uint8_t*>& keyIds);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_INIT_DATA_PARSER_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h b/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
deleted file mode 100644
index 40a2d74..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/JsonWebKey.h
+++ /dev/null
@@ -1,62 +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.
- */
-#ifndef CLEARKEY_JSON_WEB_KEY_H_
-#define CLEARKEY_JSON_WEB_KEY_H_
-
-#include "jsmn.h"
-#include "Utils.h"
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-class JsonWebKey {
- public:
- JsonWebKey();
- virtual ~JsonWebKey();
-
- bool extractKeysFromJsonWebKeySet(const std::string& jsonWebKeySet,
- KeyMap* keys);
-
- private:
- std::vector<jsmntok_t> mJsmnTokens;
- std::vector<std::string> mJsonObjects;
- std::vector<std::string> mTokens;
-
- bool decodeBase64String(const std::string& encodedText,
- std::vector<uint8_t>* decodedText);
- bool findKey(const std::string& jsonObject, std::string* keyId,
- std::string* encodedKey);
- void findValue(const std::string &key, std::string* value);
- bool isJsonWebKeySet(const std::string& jsonObject) const;
- bool parseJsonObject(const std::string& jsonObject,
- std::vector<std::string>* tokens);
- bool parseJsonWebKeySet(const std::string& jsonWebKeySet,
- std::vector<std::string>* jsonObjects);
-
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(JsonWebKey);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_JSON_WEB_KEY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h b/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
deleted file mode 100644
index 1d98860..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/MemoryFileSystem.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-#ifndef CLEARKEY_MEMORY_FILE_SYSTEM_H_
-#define CLEARKEY_MEMORY_FILE_SYSTEM_H_
-
-#include <map>
-#include <string>
-
-#include "ClearKeyTypes.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-// Using android file system requires clearkey plugin to update
-// its sepolicy. However, we are unable to update sepolicy for
-// older vendor partitions. To provide backward compatibility,
-// clearkey plugin implements a very simple file system in memory.
-// This memory file system does not support directory structure.
-class MemoryFileSystem {
- public:
- struct MemoryFile {
- std::string fileName; // excludes path
- std::string content;
- size_t fileSize;
-
- std::string getContent() const { return content; }
- size_t getFileSize() const { return fileSize; }
- void setContent(const std::string& file) { content = file; }
- void setFileName(const std::string& name) { fileName = name; }
- void setFileSize(size_t size) {
- content.resize(size); fileSize = size;
- }
- };
-
- MemoryFileSystem() {};
- virtual ~MemoryFileSystem() {};
-
- bool FileExists(const std::string& fileName) const;
- ssize_t GetFileSize(const std::string& fileName) const;
- std::vector<std::string> ListFiles() const;
- size_t Read(const std::string& pathName, std::string* buffer);
- bool RemoveAllFiles();
- bool RemoveFile(const std::string& fileName);
- size_t Write(const std::string& pathName, const MemoryFile& memoryFile);
-
- private:
- // License file name is made up of a unique keySetId, therefore,
- // the filename can be used as the key to locate licenses in the
- // memory file system.
- std::map<std::string, MemoryFile> mMemoryFileSystem;
-
- std::string GetFileName(const std::string& path);
-
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(MemoryFileSystem);
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_MEMORY_FILE_SYSTEM_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h b/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
deleted file mode 100644
index 05cb8c8..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/Session.h
+++ /dev/null
@@ -1,81 +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.
- */
-
-#ifndef CLEARKEY_SESSION_H_
-#define CLEARKEY_SESSION_H_
-
-#include <utils/Mutex.h>
-#include <utils/RefBase.h>
-#include <vector>
-
-#include "ClearKeyTypes.h"
-
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-namespace drm = ::android::hardware::drm;
-using drm::V1_0::Status;
-using drm::V1_0::SubSample;
-
-typedef drm::V1_2::Status Status_V1_2;
-
-class Session : public RefBase {
-public:
- explicit Session(const std::vector<uint8_t>& sessionId)
- : mSessionId(sessionId), mMockError(Status_V1_2::OK) {}
- virtual ~Session() {}
-
- const std::vector<uint8_t>& sessionId() const { return mSessionId; }
-
- Status getKeyRequest(
- const std::vector<uint8_t>& initDataType,
- const std::string& mimeType,
- V1_0::KeyType keyType,
- std::vector<uint8_t>* keyRequest) const;
-
- Status provideKeyResponse(
- const std::vector<uint8_t>& response);
-
- Status_V1_2 decrypt(
- const KeyId keyId, const Iv iv, const uint8_t* srcPtr,
- uint8_t* dstPtr, const std::vector<SubSample> subSamples,
- size_t* bytesDecryptedOut);
-
- void setMockError(Status_V1_2 error) {mMockError = error;}
- Status_V1_2 getMockError() const {return mMockError;}
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(Session);
-
- const std::vector<uint8_t> mSessionId;
- KeyMap mKeyMap;
- Mutex mMapLock;
-
- // For mocking error return scenarios
- Status_V1_2 mMockError;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_SESSION_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h b/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
deleted file mode 100644
index 5e77438..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/SessionLibrary.h
+++ /dev/null
@@ -1,66 +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.
- */
-
-#ifndef CLEARKEY_SESSION_LIBRARY_H_
-#define CLEARKEY_SESSION_LIBRARY_H_
-
-#include <utils/RefBase.h>
-#include <utils/Mutex.h>
-
-#include "ClearKeyTypes.h"
-#include "Session.h"
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::sp;
-
-class SessionLibrary : public RefBase {
-public:
- static SessionLibrary* get();
-
- sp<Session> createSession();
-
- sp<Session> findSession(
- const std::vector<uint8_t>& sessionId);
-
- void destroySession(const sp<Session>& session);
-
- size_t numOpenSessions() const { return mSessions.size(); }
-
-private:
- CLEARKEY_DISALLOW_COPY_AND_ASSIGN(SessionLibrary);
-
- SessionLibrary() : mNextSessionId(1) {}
-
- static Mutex sSingletonLock;
- static SessionLibrary* sSingleton;
-
- Mutex mSessionsLock;
- uint32_t mNextSessionId;
- std::map<std::vector<uint8_t>, sp<Session> > mSessions;
-};
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_SESSION_LIBRARY_H_
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h b/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
deleted file mode 100644
index 22eeccd..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/include/TypeConvert.h
+++ /dev/null
@@ -1,88 +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.
- */
-
-#ifndef CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
-#define CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
-
-#include <vector>
-
-#include <android/hardware/drm/1.0/types.h>
-
-namespace android {
-namespace hardware {
-namespace drm {
-namespace V1_4 {
-namespace clearkey {
-
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_vec;
-
-template<typename T> const hidl_vec<T> toHidlVec(const std::vector<T> &vec) {
- hidl_vec<T> hVec;
- hVec.setToExternal(const_cast<T *>(vec.data()), vec.size());
- return hVec;
-}
-
-template<typename T> hidl_vec<T> toHidlVec(std::vector<T> &vec) {
- hidl_vec<T> hVec;
- hVec.setToExternal(vec.data(), vec.size());
- return hVec;
-}
-
-template<typename T> const std::vector<T> toVector(const hidl_vec<T> &hVec) {
- std::vector<T> vec;
- vec.assign(hVec.data(), hVec.data() + hVec.size());
- return *const_cast<const std::vector<T> *>(&vec);
-}
-
-template<typename T> std::vector<T> toVector(hidl_vec<T> &hVec) {
- std::vector<T> vec;
- vec.assign(hVec.data(), hVec.data() + hVec.size());
- return vec;
-}
-
-template<typename T, size_t SIZE> const std::vector<T> toVector(
- const hidl_array<T, SIZE> &hArray) {
- std::vector<T> vec;
- vec.assign(hArray.data(), hArray.data() + hArray.size());
- return vec;
-}
-
-template<typename T, size_t SIZE> std::vector<T> toVector(
- hidl_array<T, SIZE> &hArray) {
- std::vector<T> vec;
- vec.assign(hArray.data(), hArray.data() + hArray.size());
- return vec;
-}
-
-inline Status toStatus_1_0(Status_V1_2 status) {
- switch (status) {
- case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY:
- case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE:
- case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE:
- return Status::ERROR_DRM_UNKNOWN;
- default:
- return static_cast<Status>(status);
- }
-}
-
-} // namespace clearkey
-} // namespace V1_4
-} // namespace drm
-} // namespace hardware
-} // namespace android
-
-#endif // CLEARKEY_ANDROID_HARDWARE_DRM_V1_4_TYPECONVERT
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
deleted file mode 100644
index 16cba11..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.2-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.drm</name>
- <transport>hwbinder</transport>
- <fqname>@1.2::ICryptoFactory/clearkey</fqname>
- <fqname>@1.2::IDrmFactory/clearkey</fqname>
- </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
deleted file mode 100644
index 229ee96..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.3-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.drm</name>
- <transport>hwbinder</transport>
- <fqname>@1.3::ICryptoFactory/clearkey</fqname>
- <fqname>@1.3::IDrmFactory/clearkey</fqname>
- </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml b/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
deleted file mode 100644
index 31ddb5f..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/manifest_android.hardware.drm@1.4-service.clearkey.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.drm</name>
- <transport>hwbinder</transport>
- <fqname>@1.4::ICryptoFactory/clearkey</fqname>
- <fqname>@1.4::IDrmFactory/clearkey</fqname>
- </hal>
-</manifest>
diff --git a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto b/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
deleted file mode 100644
index 3e11f0b..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/protos/DeviceFiles.proto
+++ /dev/null
@@ -1,47 +0,0 @@
-// ----------------------------------------------------------------------------
-// device_files.proto
-// ----------------------------------------------------------------------------
-// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
-// source code may only be used and distributed under the Widevine Master
-// License Agreement.
-//
-// Description:
-// Format of various files stored at the device.
-//
-syntax = "proto2";
-
-package android.hardware.drm.V1_2.clearkey;
-
-// need this if we are using libprotobuf-cpp-2.3.0-lite
-option optimize_for = LITE_RUNTIME;
-
-message License {
- enum LicenseState {
- ACTIVE = 1;
- RELEASING = 2;
- }
-
- optional LicenseState state = 1;
- optional bytes license = 2;
-}
-
-message OfflineFile {
- enum FileType {
- LICENSE = 1;
- }
-
- enum FileVersion {
- VERSION_1 = 1;
- }
-
- optional FileType type = 1;
- optional FileVersion version = 2 [default = VERSION_1];
- optional License license = 3;
-
-}
-
-message HashedFile {
- optional bytes file = 1;
- // A raw (not hex-encoded) SHA256, taken over the bytes of 'file'.
- optional bytes hash = 2;
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/service.cpp b/drm/mediadrm/plugins/clearkey/hidl/service.cpp
deleted file mode 100644
index d3d6905..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/service.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 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.
- */
-#include <CryptoFactory.h>
-#include <DrmFactory.h>
-
-#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <hidl/HidlLazyUtils.h>
-#include <hidl/HidlTransportSupport.h>
-
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::sp;
-
-using android::hardware::drm::V1_4::ICryptoFactory;
-using android::hardware::drm::V1_4::IDrmFactory;
-using android::hardware::drm::V1_4::clearkey::CryptoFactory;
-using android::hardware::drm::V1_4::clearkey::DrmFactory;
-
-int main(int /* argc */, char** /* argv */) {
- sp<IDrmFactory> drmFactory = new DrmFactory;
- sp<ICryptoFactory> cryptoFactory = new CryptoFactory;
-
- configureRpcThreadpool(8, true /* callerWillJoin */);
-
- // Setup hwbinder service
- CHECK_EQ(drmFactory->registerAsService("clearkey"), android::NO_ERROR)
- << "Failed to register Clearkey Factory HAL";
- CHECK_EQ(cryptoFactory->registerAsService("clearkey"), android::NO_ERROR)
- << "Failed to register Clearkey Crypto HAL";
-
- joinRpcThreadpool();
-}
diff --git a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp b/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
deleted file mode 100644
index 358b5cc..0000000
--- a/drm/mediadrm/plugins/clearkey/hidl/serviceLazy.cpp
+++ /dev/null
@@ -1,50 +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 <CryptoFactory.h>
-#include <DrmFactory.h>
-
-#include <android-base/logging.h>
-#include <binder/ProcessState.h>
-#include <hidl/HidlLazyUtils.h>
-#include <hidl/HidlTransportSupport.h>
-
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::sp;
-
-using android::hardware::drm::V1_4::ICryptoFactory;
-using android::hardware::drm::V1_4::IDrmFactory;
-using android::hardware::drm::V1_4::clearkey::CryptoFactory;
-using android::hardware::drm::V1_4::clearkey::DrmFactory;
-using android::hardware::LazyServiceRegistrar;
-
-int main(int /* argc */, char** /* argv */) {
- sp<IDrmFactory> drmFactory = new DrmFactory;
- sp<ICryptoFactory> cryptoFactory = new CryptoFactory;
-
- configureRpcThreadpool(8, true /* callerWillJoin */);
-
- // Setup hwbinder service
- auto serviceRegistrar = LazyServiceRegistrar::getInstance();
-
- // Setup hwbinder service
- CHECK_EQ(serviceRegistrar.registerService(drmFactory, "clearkey"), android::NO_ERROR)
- << "Failed to register Clearkey Factory HAL";
- CHECK_EQ(serviceRegistrar.registerService(cryptoFactory, "clearkey"), android::NO_ERROR)
- << "Failed to register Clearkey Crypto HAL";
-
- joinRpcThreadpool();
-}
diff --git a/include/drm/TEST_MAPPING b/include/drm/TEST_MAPPING
index 74fa50d..8595f12 100644
--- a/include/drm/TEST_MAPPING
+++ b/include/drm/TEST_MAPPING
@@ -1,16 +1,16 @@
{
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
]
}
diff --git a/include/media/Interpolator.h b/include/media/Interpolator.h
index 71e7604..0ee8779 100644
--- a/include/media/Interpolator.h
+++ b/include/media/Interpolator.h
@@ -122,7 +122,7 @@
// monotonic computation.
// we use lazy computation here - if we precompute in
// a single pass, duplicate secant computations may be avoided.
- S sec, sec0, sec1;
+ S sec{}, sec0{}, sec1{}; // initialization not needed, used for clang-tidy
if (!catmullRom || monotonic) {
sec = (high->second - low->second) / interval;
sec0 = low2 != this->end()
@@ -269,7 +269,7 @@
// Note: We don't need to check size is within some bounds as
// the Parcel read will fail if size is incorrectly specified too large.
- float lastx;
+ float lastx = 0.f; // initialization not needed, used for clang tidy
for (uint32_t i = 0; i < size; ++i) {
float x = config.xy[i * 2];
float y = config.xy[i * 2 + 1];
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 9aa896c..87256c8 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -21,16 +21,16 @@
],
"presubmit": [
{
- "name": "GtsMediaTestCases",
+ "name": "WvtsDeviceTestCases",
"options" : [
{
"include-annotation": "android.platform.test.annotations.Presubmit"
},
{
- "include-filter": "com.google.android.media.gts.WidevineGenericOpsTests"
+ "include-filter": "com.google.android.media.wvts.WidevineGenericOpsTests"
},
{
- "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
+ "include-filter": "com.google.android.media.wvts.WidevineH264PlaybackTests"
}
],
"file_patterns": ["(?i)drm|crypto"]
diff --git a/media/audioaidlconversion/AidlConversionCore.cpp b/media/audioaidlconversion/AidlConversionCore.cpp
new file mode 100644
index 0000000..948e35d
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCore.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AidlConversionCore"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <media/AidlConversionCore.h>
+#include <media/AidlConversionCppNdk.h>
+
+namespace aidl {
+namespace android {
+
+using MicrophoneDirection = hardware::audio::core::IStreamIn::MicrophoneDirection;
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::status_t;
+using ::android::base::unexpected;
+
+ConversionResult<audio_microphone_direction_t>
+aidl2legacy_MicrophoneDirection_audio_microphone_direction_t(MicrophoneDirection aidl) {
+ switch (aidl) {
+ case MicrophoneDirection::UNSPECIFIED:
+ return MIC_DIRECTION_UNSPECIFIED;
+ case MicrophoneDirection::FRONT:
+ return MIC_DIRECTION_FRONT;
+ case MicrophoneDirection::BACK:
+ return MIC_DIRECTION_BACK;
+ case MicrophoneDirection::EXTERNAL:
+ return MIC_DIRECTION_EXTERNAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+ConversionResult<MicrophoneDirection>
+legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(audio_microphone_direction_t legacy) {
+ switch (legacy) {
+ case MIC_DIRECTION_UNSPECIFIED:
+ return MicrophoneDirection::UNSPECIFIED;
+ case MIC_DIRECTION_FRONT:
+ return MicrophoneDirection::FRONT;
+ case MIC_DIRECTION_BACK:
+ return MicrophoneDirection::BACK;
+ case MIC_DIRECTION_EXTERNAL:
+ return MicrophoneDirection::EXTERNAL;
+ }
+ return unexpected(BAD_VALUE);
+}
+
+} // namespace android
+} // aidl
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 8c2b940..0cfd128 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <stdio.h>
+
#include <algorithm>
#include <map>
#include <utility>
@@ -570,7 +572,6 @@
GET_DEVICE_DESC_CONNECTION(BT_LE));
return pairs;
}();
-#undef GET_DEVICE_DESC_CONNECTION
return pairs;
}
@@ -998,55 +999,161 @@
}
}
+AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& description) {
+ using Tag = AudioDeviceAddress::Tag;
+ if (std::string connection = description.connection;
+ connection == GET_DEVICE_DESC_CONNECTION(BT_A2DP) ||
+ // Note: BT LE Broadcast uses a "group id".
+ (description.type != AudioDeviceType::OUT_BROADCAST &&
+ connection == GET_DEVICE_DESC_CONNECTION(BT_LE)) ||
+ connection == GET_DEVICE_DESC_CONNECTION(BT_SCO) ||
+ connection == GET_DEVICE_DESC_CONNECTION(WIRELESS)) {
+ return Tag::mac;
+ } else if (connection == GET_DEVICE_DESC_CONNECTION(IP_V4)) {
+ return Tag::ipv4;
+ } else if (connection == GET_DEVICE_DESC_CONNECTION(USB)) {
+ return Tag::alsa;
+ }
+ return Tag::id;
+}
+
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, char* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- return aidl2legacy_string(
- aidl.address.get<AudioDeviceAddress::id>(),
- legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+ std::string stringAddress;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl, legacyType, &stringAddress));
+ return aidl2legacy_string(stringAddress, legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
}
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, String8* legacyAddress) {
- *legacyType = VALUE_OR_RETURN_STATUS(
- aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
- aidl.address.get<AudioDeviceAddress::id>()));
+ std::string stringAddress;
+ RETURN_STATUS_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+ aidl, legacyType, &stringAddress));
+ *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(stringAddress));
return OK;
}
::android::status_t aidl2legacy_AudioDevice_audio_device(
const AudioDevice& aidl,
audio_devices_t* legacyType, std::string* legacyAddress) {
+ using Tag = AudioDeviceAddress::Tag;
*legacyType = VALUE_OR_RETURN_STATUS(
aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
- *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+ char addressBuffer[AUDIO_DEVICE_MAX_ADDRESS_LEN]{};
+ // 'aidl.address' can be empty even when the connection type is not.
+ // This happens for device ports that act as "blueprints". In this case
+ // we pass an empty string using the 'id' variant.
+ switch (aidl.address.getTag()) {
+ case Tag::mac: {
+ const std::vector<uint8_t>& mac = aidl.address.get<AudioDeviceAddress::mac>();
+ if (mac.size() != 6) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ } break;
+ case Tag::ipv4: {
+ const std::vector<uint8_t>& ipv4 = aidl.address.get<AudioDeviceAddress::ipv4>();
+ if (ipv4.size() != 4) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "%u.%u.%u.%u",
+ ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
+ } break;
+ case Tag::ipv6: {
+ const std::vector<int32_t>& ipv6 = aidl.address.get<AudioDeviceAddress::ipv6>();
+ if (ipv6.size() != 8) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN,
+ "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
+ ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7]);
+ } break;
+ case Tag::alsa: {
+ const std::vector<int32_t>& alsa = aidl.address.get<AudioDeviceAddress::alsa>();
+ if (alsa.size() != 2) return BAD_VALUE;
+ snprintf(addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN, "card=%d;device=%d",
+ alsa[0], alsa[1]);
+ } break;
+ case Tag::id: {
+ RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidl.address.get<AudioDeviceAddress::id>(),
+ addressBuffer, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+ } break;
+ }
+ *legacyAddress = addressBuffer;
return OK;
}
ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const char* legacyAddress) {
- AudioDevice aidl;
- aidl.type = VALUE_OR_RETURN(
- legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
+ const std::string stringAddress = VALUE_OR_RETURN(
legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
- return aidl;
+ return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
}
ConversionResult<AudioDevice>
legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const String8& legacyAddress) {
+ const std::string stringAddress = VALUE_OR_RETURN(legacy2aidl_String8_string(legacyAddress));
+ return legacy2aidl_audio_device_AudioDevice(legacyType, stringAddress);
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const std::string& legacyAddress) {
+ using Tag = AudioDeviceAddress::Tag;
AudioDevice aidl;
aidl.type = VALUE_OR_RETURN(
legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
- const std::string aidl_id = VALUE_OR_RETURN(
- legacy2aidl_String8_string(legacyAddress));
- aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+ // 'legacyAddress' can be empty even when the connection type is not.
+ // This happens for device ports that act as "blueprints". In this case
+ // we pass an empty string using the 'id' variant.
+ if (!legacyAddress.empty()) {
+ switch (suggestDeviceAddressTag(aidl.type)) {
+ case Tag::mac: {
+ std::vector<uint8_t> mac(6);
+ int status = sscanf(legacyAddress.c_str(), "%hhX:%hhX:%hhX:%hhX:%hhX:%hhX",
+ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+ if (status != mac.size()) {
+ ALOGE("%s: malformed MAC address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::mac>(std::move(mac));
+ } break;
+ case Tag::ipv4: {
+ std::vector<uint8_t> ipv4(4);
+ int status = sscanf(legacyAddress.c_str(), "%hhu.%hhu.%hhu.%hhu",
+ &ipv4[0], &ipv4[1], &ipv4[2], &ipv4[3]);
+ if (status != ipv4.size()) {
+ ALOGE("%s: malformed IPv4 address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv4>(std::move(ipv4));
+ } break;
+ case Tag::ipv6: {
+ std::vector<int32_t> ipv6(8);
+ int status = sscanf(legacyAddress.c_str(), "%X:%X:%X:%X:%X:%X:%X:%X",
+ &ipv6[0], &ipv6[1], &ipv6[2], &ipv6[3], &ipv6[4], &ipv6[5], &ipv6[6],
+ &ipv6[7]);
+ if (status != ipv6.size()) {
+ ALOGE("%s: malformed IPv6 address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::ipv6>(std::move(ipv6));
+ } break;
+ case Tag::alsa: {
+ std::vector<int32_t> alsa(2);
+ int status = sscanf(legacyAddress.c_str(), "card=%d;device=%d", &alsa[0], &alsa[1]);
+ if (status != alsa.size()) {
+ ALOGE("%s: malformed ALSA address: \"%s\"", __func__, legacyAddress.c_str());
+ return unexpected(BAD_VALUE);
+ }
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::alsa>(std::move(alsa));
+ } break;
+ case Tag::id: {
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+ } break;
+ }
+ } else {
+ aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(legacyAddress);
+ }
return aidl;
}
@@ -3009,6 +3116,8 @@
} // namespace android
+#undef GET_DEVICE_DESC_CONNECTION
+
#if defined(BACKEND_NDK)
} // aidl
#endif
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
index 71c547c..9b14a5e 100644
--- a/media/audioaidlconversion/AidlConversionNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -79,39 +79,42 @@
} // namespace
// buffer_provider_t is not supported thus skipped
-ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
- const media::audio::common::AudioConfigBase& aidl, bool isInput) {
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
+ const media::audio::common::AudioConfig& aidl, bool isInput) {
buffer_config_t legacy;
- legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+ legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.base.sampleRate));
legacy.mask |= EFFECT_CONFIG_SMP_RATE;
legacy.channels = VALUE_OR_RETURN(
- aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+ aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.base.channelMask, isInput));
legacy.mask |= EFFECT_CONFIG_CHANNELS;
- legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+ legacy.format =
+ VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.base.format));
legacy.mask |= EFFECT_CONFIG_FORMAT;
+ legacy.buffer.frameCount = aidl.frameCount;
// TODO: add accessMode and mask
return legacy;
}
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_buffer_config_t_AudioConfigBase(const buffer_config_t& legacy, bool isInput) {
- media::audio::common::AudioConfigBase aidl;
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_buffer_config_t_AudioConfig(const buffer_config_t& legacy, bool isInput) {
+ media::audio::common::AudioConfig aidl;
if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
- aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
+ aidl.base.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
}
if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
- aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+ aidl.base.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
static_cast<audio_channel_mask_t>(legacy.channels), isInput));
}
if (legacy.mask & EFFECT_CONFIG_FORMAT) {
- aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
+ aidl.base.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
static_cast<audio_format_t>(legacy.format)));
}
+ aidl.frameCount = legacy.buffer.frameCount;
// TODO: add accessMode and mask
return aidl;
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
index bdb3a2c..1ec4849 100644
--- a/media/audioaidlconversion/Android.bp
+++ b/media/audioaidlconversion/Android.bp
@@ -152,6 +152,37 @@
}
/**
+ * Only including AIDL core HAL conversion.
+ */
+cc_library {
+ name: "libaudio_aidl_conversion_core_ndk",
+ srcs: [
+ "AidlConversionCore.cpp",
+ ],
+ header_libs: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ export_header_lib_headers: [
+ "libaudio_aidl_conversion_common_util_ndk",
+ ],
+ defaults: [
+ "audio_aidl_conversion_common_default",
+ "latest_android_hardware_audio_common_ndk_shared",
+ "latest_android_hardware_audio_core_ndk_shared",
+ "latest_android_media_audio_common_types_ndk_shared",
+ ],
+ shared_libs: [
+ "libaudio_aidl_conversion_common_ndk",
+ "libbinder_ndk",
+ "libbase",
+ ],
+ cflags: [
+ "-DBACKEND_NDK",
+ ],
+ min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
+
+/**
* Only including AIDL effect HAL conversion.
*/
cc_library {
diff --git a/media/audioaidlconversion/include/media/AidlConversionCore.h b/media/audioaidlconversion/include/media/AidlConversionCore.h
new file mode 100644
index 0000000..aaa2e53
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCore.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ */
+#include <aidl/android/hardware/audio/core/IStreamIn.h>
+#include <media/AidlConversionUtil.h>
+#include <system/audio.h>
+
+namespace aidl {
+namespace android {
+
+ConversionResult<audio_microphone_direction_t>
+aidl2legacy_MicrophoneDirection_audio_microphone_direction_t(
+ hardware::audio::core::IStreamIn::MicrophoneDirection aidl);
+ConversionResult<hardware::audio::core::IStreamIn::MicrophoneDirection>
+legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(audio_microphone_direction_t legacy);
+
+} // namespace android
+} // namespace aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index 9100892..ec1f75c 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -190,6 +190,9 @@
ConversionResult<media::audio::common::AudioDeviceDescription>
legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+media::audio::common::AudioDeviceAddress::Tag suggestDeviceAddressTag(
+ const media::audio::common::AudioDeviceDescription& description);
+
::android::status_t aidl2legacy_AudioDevice_audio_device(
const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
char* legacyAddress);
@@ -204,6 +207,8 @@
audio_devices_t legacyType, const char* legacyAddress);
ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
audio_devices_t legacyType, const ::android::String8& legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+ audio_devices_t legacyType, const std::string& legacyAddress);
ConversionResult<audio_extra_audio_descriptor>
aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
index e92f1a9..813a728 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -34,9 +34,9 @@
namespace aidl {
namespace android {
-ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
- const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfig_buffer_config_t(
+ const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig> legacy2aidl_buffer_config_t_AudioConfig(
const buffer_config_t& legacy, bool isInput);
::android::status_t aidl2legacy_AudioAttributesTags(
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index ed91e2c..b179cbb 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -58,15 +58,15 @@
ConversionResult<To> convertIntegral(From from) {
// Special handling is required for signed / vs. unsigned comparisons, since otherwise we may
// have the signed converted to unsigned and produce wrong results.
- if (std::is_signed_v<From> && !std::is_signed_v<To>) {
+ if constexpr (std::is_signed_v<From> && !std::is_signed_v<To>) {
if (from < 0 || from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
- } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
+ } else if constexpr (std::is_signed_v<To> && !std::is_signed_v<From>) {
if (from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
- } else {
+ } else /* constexpr */ {
if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
return ::android::base::unexpected(::android::BAD_VALUE);
}
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 5d2856a..e424860 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -334,7 +334,10 @@
// By default needsUpdate = false in case the supplied level does meet
// the requirements. For Level 1b, we want to update the level anyway,
// so we set it to true in that case.
- bool needsUpdate = (me.v.level == LEVEL_AVC_1B);
+ bool needsUpdate = false;
+ if (me.v.level == LEVEL_AVC_1B || !me.F(me.v.level).supportsAtAll(me.v.level)) {
+ needsUpdate = true;
+ }
for (const LevelLimits &limit : kLimits) {
if (mbs <= limit.mbs && mbsPerSec <= limit.mbsPerSec &&
bitrate.v.value <= limit.bitrate) {
@@ -356,7 +359,7 @@
needsUpdate = true;
}
}
- if (!found) {
+ if (!found || me.v.level > LEVEL_AVC_5) {
// We set to the highest supported level.
me.set().level = LEVEL_AVC_5;
}
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 9c26c02..ec1dd14 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -341,6 +341,9 @@
// By default needsUpdate = false in case the supplied level does meet
// the requirements.
bool needsUpdate = false;
+ if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+ needsUpdate = true;
+ }
for (const LevelLimits &limit : kLimits) {
if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
bitrate.v.value <= limit.bitrate) {
@@ -362,7 +365,7 @@
needsUpdate = true;
}
}
- if (!found) {
+ if (!found || me.v.level > LEVEL_HEVC_MAIN_5_2) {
// We set to the highest supported level.
me.set().level = LEVEL_HEVC_MAIN_5_2;
}
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index d5e8c56..acc42e9 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -49,6 +49,8 @@
const char *MEDIA_MIMETYPE_VIDEO = MEDIA_MIMETYPE_VIDEO_H263;
#endif
+constexpr float VBV_DELAY = 5.0f;
+
} // namepsace
class C2SoftMpeg4Enc::IntfImpl : public SimpleInterface<void>::BaseParams {
@@ -131,7 +133,7 @@
C2Config::LEVEL_MP4V_1,
C2Config::LEVEL_MP4V_2})
})
- .withSetter(ProfileLevelSetter)
+ .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
.build());
#else
addParameter(
@@ -148,7 +150,7 @@
C2Config::LEVEL_H263_40,
C2Config::LEVEL_H263_45})
})
- .withSetter(ProfileLevelSetter)
+ .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
.build());
#endif
}
@@ -179,7 +181,10 @@
static C2R ProfileLevelSetter(
bool mayBlock,
- C2P<C2StreamProfileLevelInfo::output> &me) {
+ C2P<C2StreamProfileLevelInfo::output> &me,
+ const C2P<C2StreamPictureSizeInfo::input> &size,
+ const C2P<C2StreamFrameRateInfo::output> &frameRate,
+ const C2P<C2StreamBitrateInfo::output> &bitrate) {
(void)mayBlock;
if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
#ifdef MPEG4
@@ -188,13 +193,91 @@
me.set().profile = PROFILE_H263_BASELINE;
#endif
}
- if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+
+ struct LevelLimits {
+ C2Config::level_t level;
+ uint32_t sampleRate;
+ uint32_t width;
+ uint32_t height;
+ uint32_t frameRate;
+ uint32_t bitrate;
+ uint32_t vbvSize;
+ };
+
+ constexpr LevelLimits kLimits[] = {
#ifdef MPEG4
- me.set().level = LEVEL_MP4V_2;
+ { LEVEL_MP4V_0, 380160, 176, 144, 15, 64000, 163840 },
+ // { LEVEL_MP4V_0B, 380160, 176, 144, 15, 128000, 163840 },
+ { LEVEL_MP4V_1, 380160, 176, 144, 30, 64000, 163840 },
+ { LEVEL_MP4V_2, 1520640, 352, 288, 30, 128000, 655360 },
#else
- me.set().level = LEVEL_H263_45;
+ // HRD Buffer Size = (B + BPPmaxKb * 1024 bits)
+ // where, (BPPmaxKb * 1024) is maximum number of bits per picture
+ // that has been negotiated for use in the bitstream Sec 3.6 of T-Rec-H.263
+ // and B = 4 * Rmax / PCF. Rmax is max bit rate and PCF is picture
+ // clock frequency
+ { LEVEL_H263_10, 380160, 176, 144, 15, 64000, 74077 },
+ { LEVEL_H263_45, 380160, 176, 144, 15, 128000, 82619 },
+ { LEVEL_H263_20, 1520640, 352, 288, 30, 128000, 279227 },
+ { LEVEL_H263_30, 3041280, 352, 288, 30, 384000, 313395 },
+ { LEVEL_H263_40, 3041280, 352, 288, 30, 2048000, 535483 },
+ // { LEVEL_H263_50, 5068800, 352, 288, 60, 4096000, 808823 },
#endif
+ };
+
+ auto mbs = ((size.v.width + 15) / 16) * ((size.v.height + 15) / 16);
+ auto sampleRate = mbs * frameRate.v.value * 16 * 16;
+ auto vbvSize = bitrate.v.value * VBV_DELAY;
+
+ // Check if the supplied level meets the MB / bitrate requirements. If
+ // not, update the level with the lowest level meeting the requirements.
+ bool found = false;
+
+ // By default needsUpdate = false in case the supplied level does meet
+ // the requirements.
+ bool needsUpdate = false;
+#ifdef MPEG4
+ // For Level 0b, we want to update the level anyway, as library does not
+ // seem to accept this value.
+ if (me.v.level == LEVEL_MP4V_0B) {
+ needsUpdate = true;
}
+#endif
+ if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+ needsUpdate = true;
+ }
+ for (const LevelLimits &limit : kLimits) {
+ if (sampleRate <= limit.sampleRate && size.v.width <= limit.width &&
+ vbvSize <= limit.vbvSize && size.v.height <= limit.height &&
+ bitrate.v.value <= limit.bitrate && frameRate.v.value <= limit.frameRate) {
+ // This is the lowest level that meets the requirements, and if
+ // we haven't seen the supplied level yet, that means we don't
+ // need the update.
+ if (needsUpdate) {
+ ALOGD("Given level %x does not cover current configuration: "
+ "adjusting to %x", me.v.level, limit.level);
+ me.set().level = limit.level;
+ }
+ found = true;
+ break;
+ }
+ if (me.v.level == limit.level) {
+ // We break out of the loop when the lowest feasible level is
+ // found. The fact that we're here means that our level doesn't
+ // meet the requirement and needs to be updated.
+ needsUpdate = true;
+ }
+ }
+ // If not found or exceeds max level, set to the highest supported level.
+#ifdef MPEG4
+ if (!found || me.v.level > LEVEL_MP4V_2) {
+ me.set().level = LEVEL_MP4V_2;
+ }
+#else
+ if (!found || (me.v.level != LEVEL_H263_45 && me.v.level > LEVEL_H263_40)) {
+ me.set().level = LEVEL_H263_40;
+ }
+#endif
return C2R::Ok();
}
@@ -325,7 +408,7 @@
mEncParams->encHeight[0] = mSize->height;
mEncParams->encFrameRate[0] = mFrameRate->value + 0.5;
mEncParams->rcType = VBR_1;
- mEncParams->vbvDelay = 5.0f;
+ mEncParams->vbvDelay = VBV_DELAY;
mEncParams->profile_level = CORE_PROFILE_LEVEL2;
mEncParams->packetSize = 32;
mEncParams->rvlcEnable = PV_OFF;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index 5700e5d..e903069 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -263,6 +263,9 @@
// By default needsUpdate = false in case the supplied level does meet
// the requirements.
bool needsUpdate = false;
+ if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+ needsUpdate = true;
+ }
for (const LevelLimits& limit : kLimits) {
if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
bitrate.v.value <= limit.bitrate && dimension <= limit.dimension) {
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index a008dc2..e8969dd 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2543,17 +2543,6 @@
}
void CCodec::initiateReleaseIfStuck() {
- std::string name;
- bool pendingDeadline = false;
- {
- Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
- if (deadline->get() < std::chrono::steady_clock::now()) {
- name = deadline->getName();
- }
- if (deadline->get() != TimePoint::max()) {
- pendingDeadline = true;
- }
- }
bool tunneled = false;
bool isMediaTypeKnown = false;
{
@@ -2591,6 +2580,17 @@
tunneled = config->mTunneled;
isMediaTypeKnown = (kKnownMediaTypes.count(config->mCodingMediaType) != 0);
}
+ std::string name;
+ bool pendingDeadline = false;
+ {
+ Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+ if (deadline->get() < std::chrono::steady_clock::now()) {
+ name = deadline->getName();
+ }
+ if (deadline->get() != TimePoint::max()) {
+ pendingDeadline = true;
+ }
+ }
if (!tunneled && isMediaTypeKnown && name.empty()) {
constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index fc82426..0142686 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2066,7 +2066,10 @@
// csd cannot be re-ordered and will always arrive first.
if (initData != nullptr) {
Mutexed<Output>::Locked output(mOutput);
- if (output->buffers && outputFormat) {
+ if (!output->buffers) {
+ return false;
+ }
+ if (outputFormat) {
output->buffers->updateSkipCutBuffer(outputFormat);
output->buffers->setFormat(outputFormat);
}
@@ -2075,7 +2078,7 @@
}
size_t index;
sp<MediaCodecBuffer> outBuffer;
- if (output->buffers && output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
+ if (output->buffers->registerCsd(initData, &index, &outBuffer) == OK) {
outBuffer->meta()->setInt64("timeUs", timestamp.peek());
outBuffer->meta()->setInt32("flags", BUFFER_FLAG_CODEC_CONFIG);
ALOGV("[%s] onWorkDone: csd index = %zu [%p]", mName, index, outBuffer.get());
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index dfdd84d..2dea84c 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "C2Store"
-#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include <C2AllocatorBlob.h>
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 6ffbdc4..7c7b65b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -250,6 +250,12 @@
return af->setMode(mode);
}
+status_t AudioSystem::setSimulateDeviceConnections(bool enabled) {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->setSimulateDeviceConnections(enabled);
+}
+
status_t AudioSystem::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return PERMISSION_DENIED;
@@ -1544,6 +1550,15 @@
return OK;
}
+status_t AudioSystem::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) {
+ if (result == nullptr) return BAD_VALUE;
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aps->listDeclaredDevicePorts(role, result)));
+ return OK;
+}
+
status_t AudioSystem::getAudioPort(struct audio_port_v7* port) {
if (port == nullptr) {
return BAD_VALUE;
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index ff4b071..12f5013 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -1598,13 +1598,16 @@
}
AutoMutex lock(mLock);
+ // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
+ if (mState == STATE_STOPPED || mState == STATE_FLUSHED) {
+ *position = 0;
+ return NO_ERROR;
+ }
// FIXME: offloaded and direct tracks call into the HAL for render positions
// for compressed/synced data; however, we use proxy position for pure linear pcm data
// as we do not know the capability of the HAL for pcm position support and standby.
// There may be some latency differences between the HAL position and the proxy position.
if (isOffloadedOrDirect_l() && !isPurePcmData_l()) {
- uint32_t dspFrames = 0;
-
if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
ALOGV("%s(%d): called in paused state, return cached position %u",
__func__, mPortId, mPausedPosition);
@@ -1612,13 +1615,15 @@
return NO_ERROR;
}
+ uint32_t dspFrames = 0;
if (mOutput != AUDIO_IO_HANDLE_NONE) {
uint32_t halFrames; // actually unused
- (void) AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
// FIXME: on getRenderPosition() error, we return OK with frame position 0.
+ if (AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames) != NO_ERROR) {
+ *position = 0;
+ return NO_ERROR;
+ }
}
- // FIXME: dspFrames may not be zero in (mState == STATE_STOPPED || mState == STATE_FLUSHED)
- // due to hardware latency. We leave this behavior for now.
*position = dspFrames;
} else {
if (mCblk->mFlags & CBLK_INVALID) {
@@ -1626,11 +1631,9 @@
// FIXME: for compatibility with the Java API we ignore the restoreTrack_l()
// error here (e.g. DEAD_OBJECT) and return OK with the last recorded server position.
}
-
- // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
- *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
- 0 : updateAndGetPosition_l().value();
+ *position = updateAndGetPosition_l().value();
}
+
return NO_ERROR;
}
@@ -2484,11 +2487,22 @@
timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
timeout.tv_nsec = 0;
+ // Use timestamp progress to safeguard we don't falsely time out.
+ AudioTimestamp timestamp{};
+ const bool isTimestampValid = getTimestamp(timestamp) == OK;
+ const auto frameCount = isTimestampValid ? timestamp.mPosition : 0;
+
status_t status = proxy->waitStreamEndDone(&timeout);
switch (status) {
+ case TIMED_OUT:
+ if (isTimestampValid
+ && getTimestamp(timestamp) == OK && frameCount != timestamp.mPosition) {
+ ALOGD("%s: waitStreamEndDone retrying", __func__);
+ break; // we retry again (and recheck possible state change).
+ }
+ [[fallthrough]];
case NO_ERROR:
case DEAD_OBJECT:
- case TIMED_OUT:
if (status != DEAD_OBJECT) {
// for DEAD_OBJECT, we do not send a EVENT_STREAM_END after stop();
// instead, the application should handle the EVENT_NEW_IAUDIOTRACK.
@@ -2506,6 +2520,7 @@
}
}
if (waitStreamEnd && status != DEAD_OBJECT) {
+ ALOGV("%s: waitStreamEndDone complete", __func__);
return NS_INACTIVE;
}
break;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index a005ab4..7bf7b98 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -809,6 +809,10 @@
return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
}
+status_t AudioFlingerClientAdapter::setSimulateDeviceConnections(bool enabled) {
+ return statusTFromBinderStatus(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) {
int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
@@ -1355,6 +1359,10 @@
return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
}
+Status AudioFlingerServerAdapter::setSimulateDeviceConnections(bool enabled) {
+ return Status::fromStatusT(mDelegate->setSimulateDeviceConnections(enabled));
+}
+
Status AudioFlingerServerAdapter::setRequestedLatencyMode(
int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 7c44c74..e676d89 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -229,6 +229,9 @@
void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
+ // Used for tests only. Requires AIDL HAL to work.
+ void setSimulateDeviceConnections(boolean enabled);
+
/**
* Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
* This can be used when some use case on a given mixer/stream can only be enabled
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index ed7e243..fb87042 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -202,7 +202,9 @@
in AudioAttributesInternal attributes);
/**
- * List available audio ports and their attributes. Returns the generation.
+ * List currently attached audio ports and their attributes. Returns the generation.
+ * The generation is incremented each time when anything changes in the ports
+ * configuration.
*
* On input, count represents the maximum length of the returned array.
* On output, count is the total number of elements, which may be larger than the array size.
@@ -214,6 +216,13 @@
inout Int count,
out AudioPortFw[] ports);
+ /**
+ * List all device ports declared in the configuration (including currently detached ones)
+ * 'role' can be 'NONE' to get both input and output devices,
+ * 'SINK' for output devices, and 'SOURCE' for input devices.
+ */
+ AudioPortFw[] listDeclaredDevicePorts(AudioPortRole role);
+
/** Get attributes for the audio port with the given id (AudioPort.hal.id field). */
AudioPortFw getAudioPort(int /* audio_port_handle_t */ portId);
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index b1feb60..6080314 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -80,5 +80,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libaudioflinger",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 543ce00..3e3b79c 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
#include <vector>
#include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPortFw.h>
#include <android/media/AudioVibratorInfo.h>
#include <android/media/BnAudioFlingerClient.h>
#include <android/media/BnAudioPolicyServiceClient.h>
@@ -121,6 +122,9 @@
// set audio mode in audio hardware
static status_t setMode(audio_mode_t mode);
+ // test API: switch HALs into the mode which simulates external device connections
+ static status_t setSimulateDeviceConnections(bool enabled);
+
// returns true in *state if tracks are active on the specified stream or have been active
// in the past inPastMs milliseconds
static status_t isStreamActive(audio_stream_type_t stream, bool *state, uint32_t inPastMs);
@@ -378,6 +382,9 @@
struct audio_port_v7 *ports,
unsigned int *generation);
+ static status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result);
+
/* Get attributes for a given audio port. On input, the port
* only needs the 'id' field to be filled in. */
static status_t getAudioPort(struct audio_port_v7 *port);
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 25b5414..b1491da 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -360,6 +360,8 @@
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+ virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
+
virtual status_t setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode) = 0;
@@ -473,6 +475,7 @@
int32_t getAAudioMixerBurstCount() override;
int32_t getAAudioHardwareBurstMinUsec() override;
status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setSimulateDeviceConnections(bool enabled) override;
status_t setRequestedLatencyMode(audio_io_handle_t output,
audio_latency_mode_t mode) override;
status_t getSupportedLatencyModes(
@@ -569,6 +572,7 @@
GET_AAUDIO_MIXER_BURST_COUNT = media::BnAudioFlingerService::TRANSACTION_getAAudioMixerBurstCount,
GET_AAUDIO_HARDWARE_BURST_MIN_USEC = media::BnAudioFlingerService::TRANSACTION_getAAudioHardwareBurstMinUsec,
SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
+ SET_SIMULATE_DEVICE_CONNECTIONS = media::BnAudioFlingerService::TRANSACTION_setSimulateDeviceConnections,
SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
@@ -698,6 +702,7 @@
Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+ Status setSimulateDeviceConnections(bool enabled) override;
Status setRequestedLatencyMode(
int output, media::audio::common::AudioLatencyMode mode) override;
Status getSupportedLatencyModes(int output,
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 2189521..1e8dcca 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -14,6 +14,12 @@
"-Wall",
"-Werror",
],
+ shared_libs: [
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
sanitize: {
misc_undefined: [
"unsigned-integer-overflow",
@@ -22,37 +28,35 @@
},
}
-cc_test {
- name: "audio_aidl_conversion_tests",
+cc_defaults {
+ name: "audio_aidl_conversion_test_defaults",
defaults: [
"libaudioclient_tests_defaults",
"latest_android_media_audio_common_types_cpp_static",
],
- srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
- shared_libs: [
- "libbinder",
- "libcutils",
- "liblog",
- "libutils",
- ],
static_libs: [
- "libaudioclient_aidl_conversion",
- "libaudio_aidl_conversion_common_cpp",
"audioclient-types-aidl-cpp",
"av-types-aidl-cpp",
+ "libaudio_aidl_conversion_common_cpp",
+ "libaudioclient_aidl_conversion",
"libstagefright_foundation",
],
}
cc_test {
+ name: "audio_aidl_conversion_tests",
+ defaults: [
+ "audio_aidl_conversion_test_defaults",
+ ],
+ srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
+}
+
+cc_test {
name: "audio_aidl_status_tests",
defaults: ["libaudioclient_tests_defaults"],
srcs: ["audio_aidl_status_tests.cpp"],
shared_libs: [
"libaudioclient_aidl_conversion",
- "libbinder",
- "libcutils",
- "libutils",
],
}
@@ -70,9 +74,6 @@
shared_libs: [
"framework-permission-aidl-cpp",
"libaudioclient",
- "libbinder",
- "libcutils",
- "libutils",
],
data: ["track_test_input_*.txt"],
}
@@ -89,35 +90,23 @@
"libmediametrics_headers",
],
shared_libs: [
- "libaudioclient",
- "libbinder",
- "libcutils",
- "libutils",
"framework-permission-aidl-cpp",
+ "libaudioclient",
],
data: ["record_test_input_*.txt"],
}
cc_defaults {
name: "libaudioclient_gtests_defaults",
- cflags: [
- "-Wall",
- "-Werror",
- ],
defaults: [
- "latest_android_media_audio_common_types_cpp_static",
+ "audio_aidl_conversion_test_defaults",
],
shared_libs: [
"capture_state_listener-aidl-cpp",
"framework-permission-aidl-cpp",
- "libaudioclient_aidl_conversion",
- "libaudio_aidl_conversion_common_cpp",
"libbase",
- "libbinder",
"libcgrouprc",
- "libcutils",
"libdl",
- "liblog",
"libmedia",
"libmediametrics",
"libmediautils",
@@ -125,8 +114,6 @@
"libnblog",
"libprocessgroup",
"libshmemcompat",
- "libstagefright_foundation",
- "libutils",
"libxml2",
"mediametricsservice-aidl-cpp",
"packagemanager_aidl-cpp",
@@ -148,7 +135,6 @@
],
data: ["bbb*.raw"],
test_config_template: "audio_test_template.xml",
- test_suites: ["device-tests"],
}
cc_test {
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index e2216a0..91ef7b3 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -15,6 +15,7 @@
*/
#include <iostream>
+#include <string>
#include <gtest/gtest.h>
@@ -32,6 +33,7 @@
using media::AudioPortType;
using media::audio::common::AudioChannelLayout;
using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
using media::audio::common::AudioDeviceDescription;
using media::audio::common::AudioDeviceType;
using media::audio::common::AudioEncapsulationMetadataType;
@@ -131,6 +133,14 @@
return make_AudioDeviceDescription(AudioDeviceType::IN_DEFAULT);
}
+AudioDeviceDescription make_ADD_MicIn() {
+ return make_AudioDeviceDescription(AudioDeviceType::IN_MICROPHONE);
+}
+
+AudioDeviceDescription make_ADD_RSubmixIn() {
+ return make_AudioDeviceDescription(AudioDeviceType::IN_SUBMIX);
+}
+
AudioDeviceDescription make_ADD_DefaultOut() {
return make_AudioDeviceDescription(AudioDeviceType::OUT_DEFAULT);
}
@@ -145,6 +155,39 @@
AudioDeviceDescription::CONNECTION_BT_SCO());
}
+AudioDeviceDescription make_ADD_BtA2dpHeadphone() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADPHONE,
+ AudioDeviceDescription::CONNECTION_BT_A2DP());
+}
+
+AudioDeviceDescription make_ADD_BtLeHeadset() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_BtLeBroadcast() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_BROADCAST,
+ AudioDeviceDescription::CONNECTION_BT_LE());
+}
+
+AudioDeviceDescription make_ADD_IpV4Device() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_DEVICE,
+ AudioDeviceDescription::CONNECTION_IP_V4());
+}
+
+AudioDeviceDescription make_ADD_UsbHeadset() {
+ return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
+ AudioDeviceDescription::CONNECTION_USB());
+}
+
+AudioDevice make_AudioDevice(const AudioDeviceDescription& type,
+ const AudioDeviceAddress& address) {
+ AudioDevice result;
+ result.type = type;
+ result.address = address;
+ return result;
+}
+
AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
AudioFormatDescription result;
result.type = type;
@@ -390,6 +433,48 @@
make_ADD_DefaultOut(), make_ADD_WiredHeadset(),
make_ADD_BtScoHeadset()));
+class AudioDeviceRoundTripTest : public testing::TestWithParam<AudioDevice> {};
+TEST_P(AudioDeviceRoundTripTest, Aidl2Legacy2Aidl) {
+ const auto initial = GetParam();
+ audio_devices_t legacyType;
+ String8 legacyAddress;
+ status_t status = aidl2legacy_AudioDevice_audio_device(initial, &legacyType, &legacyAddress);
+ ASSERT_EQ(OK, status);
+ auto convBack = legacy2aidl_audio_device_AudioDevice(legacyType, legacyAddress);
+ ASSERT_TRUE(convBack.ok());
+ EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(
+ AudioDeviceRoundTrip, AudioDeviceRoundTripTest,
+ testing::Values(
+ make_AudioDevice(make_ADD_MicIn(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("bottom")),
+ make_AudioDevice(make_ADD_RSubmixIn(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("1:2-in-3")),
+ // The case of a "blueprint" device port for an external device.
+ make_AudioDevice(make_ADD_BtScoHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+ make_AudioDevice(make_ADD_BtScoHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ // Another "blueprint"
+ make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("")),
+ make_AudioDevice(make_ADD_BtA2dpHeadphone(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ make_AudioDevice(make_ADD_BtLeHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, 6})),
+ make_AudioDevice(make_ADD_BtLeBroadcast(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>("42")),
+ make_AudioDevice(make_ADD_IpV4Device(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, 1})),
+ make_AudioDevice(make_ADD_UsbHeadset(),
+ AudioDeviceAddress::make<AudioDeviceAddress::Tag::alsa>(
+ std::vector<int32_t>{1, 2}))));
+
class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
};
TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index 682f43e..d43b669 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -18,12 +18,19 @@
#include <string.h>
+#include <set>
+
#include <gtest/gtest.h>
+#include <media/AidlConversionCppNdk.h>
#include <media/IAudioFlinger.h>
#include <utils/Log.h>
#include "audio_test_utils.h"
+using android::media::audio::common::AudioDeviceAddress;
+using android::media::audio::common::AudioDeviceDescription;
+using android::media::audio::common::AudioDeviceType;
+using android::media::audio::common::AudioPortExt;
using namespace android;
void anyPatchContainsInputDevice(audio_port_handle_t deviceId, bool& res) {
@@ -579,3 +586,106 @@
EXPECT_EQ(NO_ERROR, AudioSystem::setUserIdDeviceAffinities(userId, outputDevices));
EXPECT_EQ(NO_ERROR, AudioSystem::removeUserIdDeviceAffinities(userId));
}
+
+namespace {
+
+class WithSimulatedDeviceConnections {
+ public:
+ WithSimulatedDeviceConnections()
+ : mIsSupported(AudioSystem::setSimulateDeviceConnections(true) == OK) {}
+ ~WithSimulatedDeviceConnections() {
+ if (mIsSupported) {
+ if (status_t status = AudioSystem::setSimulateDeviceConnections(false); status != OK) {
+ ALOGE("Error restoring device connections simulation state: %d", status);
+ }
+ }
+ }
+ bool isSupported() const { return mIsSupported; }
+
+ private:
+ const bool mIsSupported;
+};
+
+android::media::audio::common::AudioPort GenerateUniqueDeviceAddress(
+ const android::media::audio::common::AudioPort& port) {
+ static int nextId = 0;
+ using Tag = AudioDeviceAddress::Tag;
+ AudioDeviceAddress address;
+ switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
+ case Tag::id:
+ address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
+ break;
+ case Tag::mac:
+ address = AudioDeviceAddress::make<Tag::mac>(
+ std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv4:
+ address = AudioDeviceAddress::make<Tag::ipv4>(
+ std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
+ break;
+ case Tag::ipv6:
+ address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
+ 0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
+ break;
+ case Tag::alsa:
+ address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
+ break;
+ }
+ android::media::audio::common::AudioPort result = port;
+ result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
+ return result;
+}
+
+} // namespace
+
+TEST_F(AudioSystemTest, SetDeviceConnectedState) {
+ WithSimulatedDeviceConnections connSim;
+ if (!connSim.isSupported()) {
+ GTEST_SKIP() << "Simulation of external device connections not supported";
+ }
+ std::vector<media::AudioPortFw> ports;
+ ASSERT_EQ(OK, AudioSystem::listDeclaredDevicePorts(media::AudioPortRole::NONE, &ports));
+ if (ports.empty()) {
+ GTEST_SKIP() << "No ports returned by the audio system";
+ }
+ const std::set<AudioDeviceType> typesToUse{
+ AudioDeviceType::IN_DEVICE, AudioDeviceType::IN_HEADSET,
+ AudioDeviceType::IN_MICROPHONE, AudioDeviceType::OUT_DEVICE,
+ AudioDeviceType::OUT_HEADPHONE, AudioDeviceType::OUT_HEADSET,
+ AudioDeviceType::OUT_HEARING_AID, AudioDeviceType::OUT_SPEAKER};
+ std::vector<media::AudioPortFw> externalDevicePorts;
+ for (const auto& port : ports) {
+ if (const auto& device = port.hal.ext.get<AudioPortExt::device>().device;
+ !device.type.connection.empty() && typesToUse.count(device.type.type)) {
+ externalDevicePorts.push_back(port);
+ }
+ }
+ if (externalDevicePorts.empty()) {
+ GTEST_SKIP() << "No ports for considered non-attached devices";
+ }
+ for (auto& port : externalDevicePorts) {
+ android::media::audio::common::AudioPort aidlPort = GenerateUniqueDeviceAddress(port.hal);
+ SCOPED_TRACE(aidlPort.toString());
+ audio_devices_t type;
+ char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+ status_t status = aidl2legacy_AudioDevice_audio_device(
+ aidlPort.ext.get<AudioPortExt::Tag::device>().device, &type, address);
+ ASSERT_EQ(OK, status);
+ audio_policy_dev_state_t deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+ if (deviceState != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) continue;
+ // !!! Instead of the default format, use each format from 'ext.encodedFormats'
+ // !!! if they are not empty
+ status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ aidlPort, AUDIO_FORMAT_DEFAULT);
+ EXPECT_EQ(OK, status);
+ if (status != OK) continue;
+ deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, deviceState);
+ status = AudioSystem::setDeviceConnectionState(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ aidlPort, AUDIO_FORMAT_DEFAULT);
+ EXPECT_EQ(OK, status);
+ deviceState = AudioSystem::getDeviceConnectionState(type, address);
+ EXPECT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, deviceState);
+ }
+}
diff --git a/media/libaudiofoundation/AudioProfile.cpp b/media/libaudiofoundation/AudioProfile.cpp
index 2170cd8..999e263 100644
--- a/media/libaudiofoundation/AudioProfile.cpp
+++ b/media/libaudiofoundation/AudioProfile.cpp
@@ -327,6 +327,24 @@
return false;
}
+const SampleRateSet AudioProfileVector::getSampleRatesFor(audio_format_t format) const {
+ for (const auto& profile : *this) {
+ if (profile->getFormat() == format) {
+ return profile->getSampleRates();
+ }
+ }
+ return {};
+}
+
+const ChannelMaskSet AudioProfileVector::getChannelMasksFor(audio_format_t format) const {
+ for (const auto& profile : *this) {
+ if (profile->getFormat() == format) {
+ return profile->getChannels();
+ }
+ }
+ return {};
+}
+
bool AudioProfileVector::contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags) const
{
for (const auto& audioProfile : *this) {
diff --git a/media/libaudiofoundation/include/media/AudioProfile.h b/media/libaudiofoundation/include/media/AudioProfile.h
index 79dfd12..a668afe 100644
--- a/media/libaudiofoundation/include/media/AudioProfile.h
+++ b/media/libaudiofoundation/include/media/AudioProfile.h
@@ -139,6 +139,9 @@
bool hasDynamicProfile() const;
bool hasDynamicRateFor(audio_format_t format) const;
+ const SampleRateSet getSampleRatesFor(audio_format_t format) const;
+ const ChannelMaskSet getChannelMasksFor(audio_format_t format) const;
+
bool contains(const sp<AudioProfile>& profile, bool ignoreDynamicFlags = false) const;
virtual void dump(std::string *dst, int spaces) const;
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index f47dd0b..1dbcb86 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -76,3 +76,11 @@
export_include_dirs: ["include"],
}
+
+cc_library_headers {
+ name: "libaudiohalimpl_headers",
+
+ header_libs: ["libaudiohal_headers"],
+ export_header_lib_headers: ["libaudiohal_headers"],
+ export_include_dirs: ["impl"],
+}
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d5f6598..1e3d45f 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -274,6 +274,7 @@
"EffectsFactoryHalAidl.cpp",
"EffectsFactoryHalEntry.cpp",
"StreamHalAidl.cpp",
+ ":audio_effectproxy_src_files"
],
static_libs: [
"android.hardware.common-V2-ndk",
@@ -283,6 +284,7 @@
"libbinder_ndk",
"libaudio_aidl_conversion_common_cpp",
"libaudio_aidl_conversion_common_ndk",
+ "libaudio_aidl_conversion_core_ndk",
"libaudio_aidl_conversion_effect_ndk",
"libaudioaidlcommon",
],
@@ -297,3 +299,8 @@
"-DBACKEND_CPP_NDK",
],
}
+
+filegroup {
+ name: "audio_effectproxy_src_files",
+ srcs: ["EffectProxy.cpp"],
+}
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 8b88f24..a8a48ae 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -23,6 +23,8 @@
#include <aidl/android/hardware/audio/core/BnStreamCallback.h>
#include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
#include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <android/binder_enums.h>
+#include <binder/Enums.h>
#include <error/expected_utils.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionUtil.h>
@@ -34,32 +36,42 @@
#include "StreamHalAidl.h"
using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioChannelLayout;
using aidl::android::media::audio::common::AudioConfig;
using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceAddress;
using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMMapPolicy;
+using aidl::android::media::audio::common::AudioMMapPolicyInfo;
+using aidl::android::media::audio::common::AudioMMapPolicyType;
using aidl::android::media::audio::common::AudioMode;
using aidl::android::media::audio::common::AudioOutputFlags;
using aidl::android::media::audio::common::AudioPort;
using aidl::android::media::audio::common::AudioPortConfig;
using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioPortMixExt;
using aidl::android::media::audio::common::AudioPortMixExtUseCase;
-using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioProfile;
using aidl::android::media::audio::common::AudioSource;
-using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Float;
-using aidl::android::hardware::audio::common::getFrameSizeInBytes;
-using aidl::android::hardware::audio::common::isBitPositionFlagSet;
-using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::MicrophoneDynamicInfo;
using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
+using aidl::android::hardware::audio::common::isDefaultAudioFormat;
+using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
namespace android {
@@ -84,6 +96,75 @@
portConfig->format = config.base.format;
}
+template<typename OutEnum, typename OutEnumRange, typename InEnum>
+ConversionResult<OutEnum> convertEnum(const OutEnumRange& range, InEnum e) {
+ using InIntType = std::underlying_type_t<InEnum>;
+ static_assert(std::is_same_v<InIntType, std::underlying_type_t<OutEnum>>);
+
+ InIntType inEnumIndex = static_cast<InIntType>(e);
+ OutEnum outEnum = static_cast<OutEnum>(inEnumIndex);
+ if (std::find(range.begin(), range.end(), outEnum) == range.end()) {
+ return ::android::base::unexpected(BAD_VALUE);
+ }
+ return outEnum;
+}
+
+template<typename NdkEnum, typename CppEnum>
+ConversionResult<NdkEnum> cpp2ndk_Enum(CppEnum e) {
+ return convertEnum<NdkEnum>(::ndk::enum_range<NdkEnum>(), e);
+}
+
+template<typename CppEnum, typename NdkEnum>
+ConversionResult<CppEnum> ndk2cpp_Enum(NdkEnum e) {
+ return convertEnum<CppEnum>(::android::enum_range<CppEnum>(), e);
+}
+
+ConversionResult<android::media::audio::common::AudioDeviceAddress>
+ndk2cpp_AudioDeviceAddress(const AudioDeviceAddress& ndk) {
+ using CppTag = android::media::audio::common::AudioDeviceAddress::Tag;
+ using NdkTag = AudioDeviceAddress::Tag;
+
+ CppTag cppTag = VALUE_OR_RETURN(ndk2cpp_Enum<CppTag>(ndk.getTag()));
+
+ switch (cppTag) {
+ case CppTag::id:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::id>(
+ ndk.get<NdkTag::id>());
+ case CppTag::mac:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::mac>(
+ ndk.get<NdkTag::mac>());
+ case CppTag::ipv4:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv4>(
+ ndk.get<NdkTag::ipv4>());
+ case CppTag::ipv6:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::ipv6>(
+ ndk.get<NdkTag::ipv6>());
+ case CppTag::alsa:
+ return android::media::audio::common::AudioDeviceAddress::make<CppTag::alsa>(
+ ndk.get<NdkTag::alsa>());
+ }
+
+ return ::android::base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<media::audio::common::AudioDevice> ndk2cpp_AudioDevice(const AudioDevice& ndk) {
+ media::audio::common::AudioDevice cpp;
+ cpp.type.type = VALUE_OR_RETURN(
+ ndk2cpp_Enum<media::audio::common::AudioDeviceType>(ndk.type.type));
+ cpp.type.connection = ndk.type.connection;
+ cpp.address = VALUE_OR_RETURN(ndk2cpp_AudioDeviceAddress(ndk.address));
+ return cpp;
+}
+
+ConversionResult<media::audio::common::AudioMMapPolicyInfo>
+ndk2cpp_AudioMMapPolicyInfo(const AudioMMapPolicyInfo& ndk) {
+ media::audio::common::AudioMMapPolicyInfo cpp;
+ cpp.device = VALUE_OR_RETURN(ndk2cpp_AudioDevice(ndk.device));
+ cpp.mmapPolicy = VALUE_OR_RETURN(
+ ndk2cpp_Enum<media::audio::common::AudioMMapPolicy>(ndk.mmapPolicy));
+ return cpp;
+}
+
} // namespace
status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
@@ -116,6 +197,7 @@
}
ALOGI("%s: module %s default port ids: input %d, output %d",
__func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+ RETURN_STATUS_IF_ERROR(updateRoutes());
std::vector<AudioPortConfig> portConfigs;
RETURN_STATUS_IF_ERROR(
statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs))); // OK if empty
@@ -257,9 +339,9 @@
AudioPortConfig mixPortConfig;
Cleanups cleanups;
audio_config writableConfig = *config;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
- &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
*size = aidlConfig.frameCount *
getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
// Do not disarm cleanups to release temporary port configs.
@@ -270,7 +352,11 @@
int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
AudioSource aidlSource, struct audio_config* config,
Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
- int32_t* nominalLatency) {
+ AudioPatch* aidlPatch) {
+ ALOGD("%p %s::%s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
+ this, getClassName().c_str(), __func__, aidlHandle, aidlDevice.toString().c_str(),
+ aidlFlags.toString().c_str(), toString(aidlSource).c_str(),
+ aidlConfig->toString().c_str(), mixPortConfig->toString().c_str());
const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
// Find / create AudioPortConfigs for the device port and the mix port,
// then find / create a patch between them, and open a stream on the mix port.
@@ -281,25 +367,23 @@
cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
}
RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
- mixPortConfig, &created));
+ std::set<int32_t>{devicePortConfig.portId}, mixPortConfig, &created));
if (created) {
cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
}
setConfigFromPortConfig(aidlConfig, *mixPortConfig);
- AudioPatch patch;
if (isInput) {
RETURN_STATUS_IF_ERROR(findOrCreatePatch(
- {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+ {devicePortConfig.id}, {mixPortConfig->id}, aidlPatch, &created));
} else {
RETURN_STATUS_IF_ERROR(findOrCreatePatch(
- {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+ {mixPortConfig->id}, {devicePortConfig.id}, aidlPatch, &created));
}
if (created) {
- cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+ cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, aidlPatch->id);
}
- *nominalLatency = patch.latenciesMs[0];
if (aidlConfig->frameCount <= 0) {
- aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+ aidlConfig->frameCount = aidlPatch->minimumStreamBufferSizeFrames;
}
*config = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
@@ -445,10 +529,10 @@
AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
AudioPortConfig mixPortConfig;
Cleanups cleanups;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
- config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
args.portConfigId = mixPortConfig.id;
const bool isOffload = isBitPositionFlagSet(
@@ -472,8 +556,9 @@
__func__, ret.desc.toString().c_str());
return NO_INIT;
}
- *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+ *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
std::move(ret.stream), this /*callbackBroker*/);
+ mStreams.insert(std::pair(*outStream, aidlPatch.id));
void* cbCookie = (*outStream).get();
{
std::lock_guard l(mLock);
@@ -510,9 +595,9 @@
::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
AudioPortConfig mixPortConfig;
Cleanups cleanups;
- int32_t nominalLatency;
+ AudioPatch aidlPatch;
RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
- config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+ config, &cleanups, &aidlConfig, &mixPortConfig, &aidlPatch));
::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
args.portConfigId = mixPortConfig.id;
RecordTrackMetadata aidlTrackMetadata{
@@ -532,8 +617,9 @@
__func__, ret.desc.toString().c_str());
return NO_INIT;
}
- *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+ *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
std::move(ret.stream), this /*micInfoProvider*/);
+ mStreams.insert(std::pair(*inStream, aidlPatch.id));
cleanups.disarmAll();
return OK;
}
@@ -601,20 +687,41 @@
__func__, ::android::internal::ToString(aidlSources).c_str(),
::android::internal::ToString(aidlSinks).c_str());
auto fillPortConfigs = [&](
- const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+ const std::vector<AudioPortConfig>& configs,
+ const std::set<int32_t>& destinationPortIds,
+ std::vector<int32_t>* ids, std::set<int32_t>* portIds) -> status_t {
for (const auto& s : configs) {
AudioPortConfig portConfig;
bool created = false;
- RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+ s, destinationPortIds, &portConfig, &created));
if (created) {
cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
}
ids->push_back(portConfig.id);
+ if (portIds != nullptr) {
+ portIds->insert(portConfig.portId);
+ }
}
return OK;
};
- RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
- RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+ // When looking up port configs, the destinationPortId is only used for mix ports.
+ // Thus, we process device port configs first, and look up the destination port ID from them.
+ bool sourceIsDevice = std::any_of(aidlSources.begin(), aidlSources.end(),
+ [](const auto& config) { return config.ext.getTag() == AudioPortExt::device; });
+ const std::vector<AudioPortConfig>& devicePortConfigs =
+ sourceIsDevice ? aidlSources : aidlSinks;
+ std::vector<int32_t>* devicePortConfigIds =
+ sourceIsDevice ? &aidlPatch.sourcePortConfigIds : &aidlPatch.sinkPortConfigIds;
+ const std::vector<AudioPortConfig>& mixPortConfigs =
+ sourceIsDevice ? aidlSinks : aidlSources;
+ std::vector<int32_t>* mixPortConfigIds =
+ sourceIsDevice ? &aidlPatch.sinkPortConfigIds : &aidlPatch.sourcePortConfigIds;
+ std::set<int32_t> devicePortIds;
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(
+ devicePortConfigs, std::set<int32_t>(), devicePortConfigIds, &devicePortIds));
+ RETURN_STATUS_IF_ERROR(fillPortConfigs(
+ mixPortConfigs, devicePortIds, mixPortConfigIds, nullptr));
if (existingPatchIt != mPatches.end()) {
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
mModule->setAudioPatch(aidlPatch, &aidlPatch)));
@@ -649,22 +756,68 @@
return OK;
}
-status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
- TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
- TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return INVALID_OPERATION;
-}
-
-status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
+status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mModule) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ audio_port_v7 portV7;
+ audio_populate_audio_port_v7(port, &portV7);
+ RETURN_STATUS_IF_ERROR(getAudioPort(&portV7));
+ return audio_populate_audio_port(&portV7, port) ? OK : BAD_VALUE;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ auto aidlPort = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+ if (aidlPort.ext.getTag() != AudioPortExt::device) {
+ ALOGE("%s: provided port is not a device port (module %s): %s",
+ __func__, mInstance.c_str(), aidlPort.toString().c_str());
+ return BAD_VALUE;
+ }
+ const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ // It seems that we don't have to call HAL since all valid ports have been added either
+ // during initialization, or while handling connection of an external device.
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGE("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ const int32_t fwkId = aidlPort.id;
+ aidlPort = portsIt->second;
+ aidlPort.id = fwkId;
+ *port = VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioPort_audio_port_v7(
+ aidlPort, isInput));
+ return OK;
+}
+
+status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
+ ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (config == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+ config->role, config->type)) == ::aidl::android::AudioPortDirection::INPUT;
+ AudioPortConfig requestedPortConfig = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+ *config, isInput, 0 /*portId*/));
+ AudioPortConfig portConfig;
+ bool created = false;
+ RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(
+ requestedPortConfig, std::set<int32_t>(), &portConfig, &created));
return OK;
}
@@ -732,23 +885,41 @@
}
status_t DeviceHalAidl::getMmapPolicyInfos(
- media::audio::common::AudioMMapPolicyType policyType __unused,
- std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
+ media::audio::common::AudioMMapPolicyType policyType,
+ std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
+ AudioMMapPolicyType mmapPolicyType =
+ VALUE_OR_RETURN_STATUS(cpp2ndk_Enum<AudioMMapPolicyType>(policyType));
+
+ std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
+
+ if (status_t status = statusTFromBinderStatus(
+ mModule->getMmapPolicyInfos(mmapPolicyType, &mmapPolicyInfos)); status != OK) {
+ return status;
+ }
+
+ *policyInfos = VALUE_OR_RETURN_STATUS(
+ convertContainer<std::vector<media::audio::common::AudioMMapPolicyInfo>>(
+ mmapPolicyInfos, ndk2cpp_AudioMMapPolicyInfo));
return OK;
}
int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ int32_t mixerBurstCount = 0;
+ if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
+ return mixerBurstCount;
+ }
+ return 0;
}
int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ int32_t hardwareBurstMinUsec = 0;
+ if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
+ return hardwareBurstMinUsec;
+ }
+ return 0;
}
error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
@@ -764,12 +935,82 @@
TIME_CHECK();
if (!mModule) return NO_INIT;
return mModule->dump(fd, Args(args).args(), args.size());
-};
+}
-int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
+int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
TIME_CHECK();
- ALOGE("%s not implemented yet", __func__);
- return INVALID_OPERATION;
+ if (!mModule) return NO_INIT;
+ if (supports == nullptr) {
+ return BAD_VALUE;
+ }
+ return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
+}
+
+status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ if (port == nullptr) {
+ return BAD_VALUE;
+ }
+ bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+ ::aidl::android::AudioPortDirection::INPUT;
+ AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
+ if (aidlPort.ext.getTag() != AudioPortExt::device) {
+ ALOGE("%s: provided port is not a device port (module %s): %s",
+ __func__, mInstance.c_str(), aidlPort.toString().c_str());
+ return BAD_VALUE;
+ }
+ if (connected) {
+ AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ // Reset the device address to find the "template" port.
+ matchDevice.address = AudioDeviceAddress::make<AudioDeviceAddress::id>();
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGW("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ // Use the ID of the "template" port, use all the information from the provided port.
+ aidlPort.id = portsIt->first;
+ AudioPort connectedPort;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
+ aidlPort, &connectedPort)));
+ const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
+ LOG_ALWAYS_FATAL_IF(!inserted,
+ "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
+ __func__, mInstance.c_str(), connectedPort.toString().c_str(),
+ it->second.toString().c_str());
+ } else { // !connected
+ AudioDevice matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
+ auto portsIt = findPort(matchDevice);
+ if (portsIt == mPorts.end()) {
+ ALOGW("%s: device port for device %s is not found in the module %s",
+ __func__, matchDevice.toString().c_str(), mInstance.c_str());
+ return BAD_VALUE;
+ }
+ // Any streams opened on the external device must be closed by this time,
+ // thus we can clean up patches and port configs that were created for them.
+ resetUnusedPatchesAndPortConfigs();
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
+ portsIt->second.id)));
+ mPorts.erase(portsIt);
+ }
+ return updateRoutes();
+}
+
+status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
+ TIME_CHECK();
+ if (!mModule) return NO_INIT;
+ ModuleDebug debug{ .simulateDeviceConnections = enabled };
+ status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
+ // This is important to log as it affects HAL behavior.
+ if (status == OK) {
+ ALOGI("%s: set enabled: %d", __func__, enabled);
+ } else {
+ ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
+ }
+ return status;
}
bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
@@ -865,7 +1106,8 @@
status_t DeviceHalAidl::findOrCreatePortConfig(
const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
- AudioSource source, AudioPortConfig* portConfig, bool* created) {
+ AudioSource source, const std::set<int32_t>& destinationPortIds,
+ AudioPortConfig* portConfig, bool* created) {
// These flags get removed one by one in this order when retrying port finding.
static const std::vector<AudioInputFlags> kOptionalInputFlags{
AudioInputFlags::FAST, AudioInputFlags::RAW };
@@ -873,7 +1115,7 @@
if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
auto optionalInputFlagsIt = kOptionalInputFlags.begin();
AudioIoFlags matchFlags = flags.value();
- auto portsIt = findPort(config, matchFlags);
+ auto portsIt = findPort(config, matchFlags, destinationPortIds);
while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
&& optionalInputFlagsIt != kOptionalInputFlags.end()) {
if (!isBitPositionFlagSet(
@@ -883,7 +1125,7 @@
}
matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
~makeBitPositionFlagMask(*optionalInputFlagsIt++));
- portsIt = findPort(config, matchFlags);
+ portsIt = findPort(config, matchFlags, destinationPortIds);
ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
"retried with flags %s", __func__, config.toString().c_str(),
flags.value().toString().c_str(), mInstance.c_str(),
@@ -919,7 +1161,8 @@
}
status_t DeviceHalAidl::findOrCreatePortConfig(
- const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+ const AudioPortConfig& requestedPortConfig, const std::set<int32_t>& destinationPortIds,
+ AudioPortConfig* portConfig, bool* created) {
using Tag = AudioPortExt::Tag;
if (requestedPortConfig.ext.getTag() == Tag::mix) {
if (const auto& p = requestedPortConfig;
@@ -936,7 +1179,8 @@
requestedPortConfig.ext.get<Tag::mix>().usecase.
get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
return findOrCreatePortConfig(config, requestedPortConfig.flags,
- requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
+ requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
+ portConfig, created);
} else if (requestedPortConfig.ext.getTag() == Tag::device) {
return findOrCreatePortConfig(
requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
@@ -968,20 +1212,30 @@
[&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
}
+
DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
- const AudioConfig& config, const AudioIoFlags& flags) {
+ const AudioConfig& config, const AudioIoFlags& flags,
+ const std::set<int32_t>& destinationPortIds) {
+ auto belongsToProfile = [&config](const AudioProfile& prof) {
+ return (isDefaultAudioFormat(config.base.format) || prof.format == config.base.format) &&
+ (config.base.channelMask.getTag() == AudioChannelLayout::none ||
+ std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+ config.base.channelMask) != prof.channelMasks.end()) &&
+ (config.base.sampleRate == 0 ||
+ std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+ config.base.sampleRate) != prof.sampleRates.end());
+ };
auto matcher = [&](const auto& pair) {
const auto& p = pair.second;
return p.ext.getTag() == AudioPortExt::Tag::mix &&
p.flags == flags &&
- std::find_if(p.profiles.begin(), p.profiles.end(),
- [&](const auto& prof) {
- return prof.format == config.base.format &&
- std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
- config.base.channelMask) != prof.channelMasks.end() &&
- std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
- config.base.sampleRate) != prof.sampleRates.end();
- }) != p.profiles.end(); };
+ (destinationPortIds.empty() ||
+ std::any_of(destinationPortIds.begin(), destinationPortIds.end(),
+ [&](const int32_t destId) { return mRoutingMatrix.count(
+ std::make_pair(p.id, destId)) != 0; })) &&
+ (p.profiles.empty() ||
+ std::find_if(p.profiles.begin(), p.profiles.end(), belongsToProfile) !=
+ p.profiles.end()); };
return std::find_if(mPorts.begin(), mPorts.end(), matcher);
}
@@ -1006,34 +1260,7 @@
(!flags.has_value() || p.flags.value() == flags.value()) &&
p.ext.template get<Tag::mix>().handle == ioHandle; });
}
-/*
-DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
- const AudioPortConfig& portConfig) {
- using Tag = AudioPortExt::Tag;
- if (portConfig.ext.getTag() == Tag::mix) {
- return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
- [&](const auto& pair) {
- const auto& p = pair.second;
- LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
- !p.sampleRate.has_value() || !p.channelMask.has_value() ||
- !p.format.has_value() || !p.flags.has_value(),
- "%s: stored mix port config is not fully specified: %s",
- __func__, p.toString().c_str());
- return p.ext.getTag() == Tag::mix &&
- (!portConfig.sampleRate.has_value() ||
- p.sampleRate == portConfig.sampleRate) &&
- (!portConfig.channelMask.has_value() ||
- p.channelMask == portConfig.channelMask) &&
- (!portConfig.format.has_value() || p.format == portConfig.format) &&
- (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
- p.ext.template get<Tag::mix>().handle ==
- portConfig.ext.template get<Tag::mix>().handle; });
- } else if (portConfig.ext.getTag() == Tag::device) {
- return findPortConfig(portConfig.ext.get<Tag::device>().device);
- }
- return mPortConfigs.end();
-}
-*/
+
void DeviceHalAidl::resetPatch(int32_t patchId) {
if (auto it = mPatches.find(patchId); it != mPatches.end()) {
mPatches.erase(it);
@@ -1061,6 +1288,56 @@
ALOGE("%s: port config id %d not found", __func__, portConfigId);
}
+void DeviceHalAidl::resetUnusedPatches() {
+ // Since patches can be created independently of streams via 'createAudioPatch',
+ // here we only clean up patches for released streams.
+ for (auto it = mStreams.begin(); it != mStreams.end(); ) {
+ if (auto streamSp = it->first.promote(); streamSp) {
+ ++it;
+ } else {
+ resetPatch(it->second);
+ it = mStreams.erase(it);
+ }
+ }
+}
+
+void DeviceHalAidl::resetUnusedPatchesAndPortConfigs() {
+ resetUnusedPatches();
+ resetUnusedPortConfigs();
+}
+
+void DeviceHalAidl::resetUnusedPortConfigs() {
+ // The assumption is that port configs are used to create patches
+ // (or to open streams, but that involves creation of patches, too). Thus,
+ // orphaned port configs can and should be reset.
+ std::set<int32_t> portConfigIds;
+ std::transform(mPortConfigs.begin(), mPortConfigs.end(),
+ std::inserter(portConfigIds, portConfigIds.end()),
+ [](const auto& pcPair) { return pcPair.first; });
+ for (const auto& p : mPatches) {
+ for (int32_t id : p.second.sourcePortConfigIds) portConfigIds.erase(id);
+ for (int32_t id : p.second.sinkPortConfigIds) portConfigIds.erase(id);
+ }
+ for (int32_t id : portConfigIds) resetPortConfig(id);
+}
+
+status_t DeviceHalAidl::updateRoutes() {
+ TIME_CHECK();
+ std::vector<AudioRoute> routes;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mModule->getAudioRoutes(&routes)));
+ ALOGW_IF(routes.empty(), "%s: module %s returned an empty list of audio routes",
+ __func__, mInstance.c_str());
+ mRoutingMatrix.clear();
+ for (const auto& r : routes) {
+ for (auto portId : r.sourcePortIds) {
+ mRoutingMatrix.emplace(r.sinkPortId, portId);
+ mRoutingMatrix.emplace(portId, r.sinkPortId);
+ }
+ }
+ return OK;
+}
+
void DeviceHalAidl::clearCallbacks(void* cookie) {
std::lock_guard l(mLock);
mCallbacks.erase(cookie);
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 0a86ddc..fd0cd54 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -24,6 +24,7 @@
#include <android-base/thread_annotations.h>
#include <media/audiohal/DeviceHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
#include "ConversionHelperAidl.h"
@@ -138,7 +139,7 @@
status_t setAudioPortConfig(const struct audio_port_config* config) override;
// List microphones
- status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones);
+ status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
@@ -154,10 +155,14 @@
error::Result<audio_hw_sync_t> getHwAvSync() override;
- status_t dump(int __unused, const Vector<String16>& __unused) override;
-
int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+ status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
+
+ status_t setSimulateDeviceConnections(bool enabled) override;
+
+ status_t dump(int __unused, const Vector<String16>& __unused) override;
+
private:
friend class sp<DeviceHalAidl>;
@@ -176,6 +181,10 @@
using PortConfigs = std::map<int32_t /*port config ID*/,
::aidl::android::media::audio::common::AudioPortConfig>;
using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+ // Answers the question "whether portID 'first' is reachable from portID 'second'?"
+ // It's not a map because both portIDs are known. The matrix is symmetric.
+ using RoutingMatrix = std::set<std::pair<int32_t, int32_t>>;
+ using Streams = std::map<wp<StreamHalInterface>, int32_t /*patch ID*/>;
class Cleanups;
// Must not be constructed directly by clients.
@@ -209,25 +218,25 @@
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle,
::aidl::android::media::audio::common::AudioSource aidlSource,
+ const std::set<int32_t>& destinationPortIds,
::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
status_t findOrCreatePortConfig(
const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+ const std::set<int32_t>& destinationPortIds,
::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
const std::set<int32_t>& sinkPortConfigIds);
Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
Ports::iterator findPort(
const ::aidl::android::media::audio::common::AudioConfig& config,
- const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+ const ::aidl::android::media::audio::common::AudioIoFlags& flags,
+ const std::set<int32_t>& destinationPortIds);
PortConfigs::iterator findPortConfig(
const ::aidl::android::media::audio::common::AudioDevice& device);
PortConfigs::iterator findPortConfig(
const ::aidl::android::media::audio::common::AudioConfig& config,
const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
int32_t ioHandle);
- // Currently unused but may be useful for implementing setAudioPortConfig
- // PortConfigs::iterator findPortConfig(
- // const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
status_t prepareToOpenStream(
int32_t aidlHandle,
const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
@@ -237,9 +246,13 @@
Cleanups* cleanups,
::aidl::android::media::audio::common::AudioConfig* aidlConfig,
::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
- int32_t* nominalLatency);
+ ::aidl::android::hardware::audio::core::AudioPatch* aidlPatch);
void resetPatch(int32_t patchId);
void resetPortConfig(int32_t portConfigId);
+ void resetUnusedPatches();
+ void resetUnusedPatchesAndPortConfigs();
+ void resetUnusedPortConfigs();
+ status_t updateRoutes();
// CallbackBroker implementation
void clearCallbacks(void* cookie) override;
@@ -266,6 +279,8 @@
int32_t mDefaultOutputPortId = -1;
PortConfigs mPortConfigs;
Patches mPatches;
+ RoutingMatrix mRoutingMatrix;
+ Streams mStreams;
Microphones mMicrophones;
std::mutex mLock;
std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 052eb65..132aad7 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -126,6 +126,11 @@
status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
+ status_t setSimulateDeviceConnections(bool enabled __unused) override {
+ // Only supported by AIDL HALs.
+ return INVALID_OPERATION;
+ }
+
error::Result<audio_hw_sync_t> getHwAvSync() override;
status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 519b871..52fed91 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <cstddef>
#include <cstdint>
#include <cstring>
#include <optional>
@@ -29,6 +30,7 @@
#include <utils/Log.h>
#include "EffectConversionHelperAidl.h"
+#include "EffectProxy.h"
namespace android {
namespace effect {
@@ -37,10 +39,13 @@
using ::aidl::android::hardware::audio::effect::CommandId;
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::aidl::android::media::audio::common::AudioMode;
using ::aidl::android::media::audio::common::AudioSource;
+using ::android::hardware::EventFlag;
using android::effect::utils::EffectParamReader;
using android::effect::utils::EffectParamWriter;
@@ -72,7 +77,9 @@
mIoId(ioId),
mDesc(desc),
mEffect(std::move(effect)),
- mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC) {
+ mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC),
+ mIsProxyEffect(mDesc.common.id.proxy.has_value() &&
+ mDesc.common.id.proxy.value() == mDesc.common.id.uuid) {
mCommon.session = sessionId;
mCommon.ioHandle = ioId;
mCommon.input = mCommon.output = kDefaultAudioConfig;
@@ -96,8 +103,8 @@
return BAD_VALUE;
}
- return *(status_t*)pReplyData =
- statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
+ // Do nothing for EFFECT_CMD_INIT, call IEffect.open() with EFFECT_CMD_SET_CONFIG
+ return *(status_t*)pReplyData = OK;
}
status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
@@ -122,6 +129,8 @@
status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
uint32_t* replySize, void* pReplyData) {
if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
+ ALOGE("%s illegal cmdSize %u pCmdData %p replySize %p replyData %p", __func__, cmdSize,
+ pCmdData, replySize, pReplyData);
return BAD_VALUE;
}
@@ -154,22 +163,61 @@
}
effect_config_t* config = (effect_config_t*)pCmdData;
- Parameter::Common aidlCommon = {
- .session = mSessionId,
- .ioHandle = mIoId,
- .input = {.base = VALUE_OR_RETURN_STATUS(
- ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- config->inputCfg, mIsInputStream))},
- .output = {.base = VALUE_OR_RETURN_STATUS(
- ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
- config->outputCfg, mIsInputStream))}};
+ Parameter::Common common = {
+ .input =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
+ config->inputCfg, mIsInputStream)),
+ .output =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_buffer_config_t_AudioConfig(
+ config->outputCfg, mIsInputStream)),
+ .session = mCommon.session,
+ .ioHandle = mCommon.ioHandle};
- Parameter aidlParam = UNION_MAKE(Parameter, common, aidlCommon);
+ State state;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
+ // in case of buffer/ioHandle re-configure for an opened effect, close it and re-open
+ if (state != State::INIT && mCommon != common) {
+ ALOGI("%s at state %s, closing effect", __func__,
+ android::internal::ToString(state).c_str());
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->close()));
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getState(&state)));
+ mStatusQ.reset();
+ mInputQ.reset();
+ mOutputQ.reset();
+ }
- status_t ret = statusTFromBinderStatus(mEffect->setParameter(aidlParam));
- EffectParamWriter writer(*(effect_param_t*)pReplyData);
- writer.setStatus(ret);
- return ret;
+ if (state == State::INIT) {
+ ALOGI("%s at state %s, opening effect with input %s output %s", __func__,
+ android::internal::ToString(state).c_str(), common.input.toString().c_str(),
+ common.output.toString().c_str());
+ IEffect::OpenEffectReturn openReturn;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn)));
+
+ if (mIsProxyEffect) {
+ const auto& ret =
+ std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
+ mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
+ mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
+ mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+ } else {
+ mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
+ mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
+ mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
+ }
+
+ if (status_t status = updateEventFlags(); status != OK) {
+ mEffect->close();
+ return status;
+ }
+ mCommon = common;
+ } else if (mCommon != common) {
+ ALOGI("%s at state %s, setParameter", __func__, android::internal::ToString(state).c_str());
+ Parameter aidlParam = UNION_MAKE(Parameter, common, mCommon);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+ }
+
+ return *static_cast<int32_t*>(pReplyData) = OK;
}
status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
@@ -187,11 +235,9 @@
const auto& common = param.get<Parameter::common>();
effect_config_t* pConfig = (effect_config_t*)pReplyData;
pConfig->inputCfg = VALUE_OR_RETURN_STATUS(
- ::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(common.input.base, true));
- pConfig->outputCfg =
- VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
- common.output.base, false));
- mCommon = common;
+ ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.input, true));
+ pConfig->outputCfg = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioConfig_buffer_config_t(common.output, false));
return OK;
}
@@ -294,7 +340,21 @@
pReplyData);
return BAD_VALUE;
}
- // TODO: handle this after effectproxy implemented in libaudiohal
+ effect_offload_param_t* offload = (effect_offload_param_t*)pCmdData;
+ // send to proxy to update active sub-effect
+ if (mIsProxyEffect) {
+ ALOGI("%s offload param offload %s ioHandle %d", __func__,
+ offload->isOffload ? "true" : "false", offload->ioHandle);
+ mCommon.ioHandle = offload->ioHandle;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+ std::static_pointer_cast<EffectProxy>(mEffect)->setOffloadParam(offload)));
+ // update FMQs
+ const auto& ret = std::static_pointer_cast<EffectProxy>(mEffect)->getEffectReturnParam();
+ mStatusQ = std::make_shared<StatusMQ>(ret->statusMQ);
+ mInputQ = std::make_shared<DataMQ>(ret->inputDataMQ);
+ mOutputQ = std::make_shared<DataMQ>(ret->outputDataMQ);
+ RETURN_STATUS_IF_ERROR(updateEventFlags());
+ }
return *static_cast<int32_t*>(pReplyData) = OK;
}
@@ -338,5 +398,20 @@
return visualizerMeasure(replySize, pReplyData);
}
+status_t EffectConversionHelperAidl::updateEventFlags() {
+ status_t status = BAD_VALUE;
+ EventFlag* efGroup = nullptr;
+ if (mStatusQ->isValid()) {
+ status = EventFlag::createEventFlag(mStatusQ->getEventFlagWord(), &efGroup);
+ if (status != OK || !efGroup) {
+ ALOGE("%s: create EventFlagGroup failed, ret %d, egGroup %p", __func__, status,
+ efGroup);
+ status = (status == OK) ? BAD_VALUE : status;
+ }
+ }
+ mEfGroup.reset(efGroup, EventFlagDeleter());
+ return status;
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 54df1b8..0c682ff 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -19,6 +19,7 @@
#include <utils/Errors.h>
#include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include <fmq/AidlMessageQueue.h>
#include <system/audio_effect.h>
#include <system/audio_effects/audio_effects_utils.h>
@@ -30,10 +31,16 @@
status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
void* pReplyData);
virtual ~EffectConversionHelperAidl() {}
- const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
- getEffectReturnParam() const {
- return mOpenReturn;
- }
+
+ using StatusMQ = ::android::AidlMessageQueue<
+ ::aidl::android::hardware::audio::effect::IEffect::Status,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ using DataMQ = ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+ std::shared_ptr<StatusMQ> getStatusMQ() { return mStatusQ; }
+ std::shared_ptr<DataMQ> getInputMQ() { return mInputQ; }
+ std::shared_ptr<DataMQ> getOutputMQ() { return mOutputQ; }
+ std::shared_ptr<android::hardware::EventFlag> getEventFlagGroup() { return mEfGroup; }
protected:
const int32_t mSessionId;
@@ -42,7 +49,6 @@
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
// whether the effect is instantiated on an input stream
const bool mIsInputStream;
- ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
EffectConversionHelperAidl(
@@ -59,6 +65,7 @@
const aidl::android::media::audio::common::AudioFormatDescription kDefaultFormatDescription = {
.type = aidl::android::media::audio::common::AudioFormatType::PCM,
.pcm = aidl::android::media::audio::common::PcmType::FLOAT_32_BIT};
+ const bool mIsProxyEffect;
static constexpr int kDefaultframeCount = 0x100;
@@ -75,6 +82,20 @@
uint32_t* /* replySize */,
void* /* pReplyData */);
static const std::map<uint32_t /* effect_command_e */, CommandHandler> mCommandHandlerMap;
+ // data and status FMQ
+ std::shared_ptr<StatusMQ> mStatusQ = nullptr;
+ std::shared_ptr<DataMQ> mInputQ = nullptr, mOutputQ = nullptr;
+
+
+ struct EventFlagDeleter {
+ void operator()(::android::hardware::EventFlag* flag) const {
+ if (flag) {
+ ::android::hardware::EventFlag::deleteEventFlag(&flag);
+ }
+ }
+ };
+ std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr;
+ status_t updateEventFlags();
status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
@@ -112,6 +133,7 @@
virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
return BAD_VALUE;
}
+
};
} // namespace effect
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c19ac8..faf5f45 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -31,6 +31,7 @@
#include <utils/Log.h>
#include "EffectHalAidl.h"
+#include "EffectProxy.h"
#include <aidl/android/hardware/audio/effect/IEffect.h>
@@ -61,19 +62,22 @@
EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
const std::shared_ptr<IEffect>& effect, uint64_t effectId,
- int32_t sessionId, int32_t ioId, const Descriptor& desc)
+ int32_t sessionId, int32_t ioId, const Descriptor& desc,
+ bool isProxyEffect)
: mFactory(factory),
mEffect(effect),
mEffectId(effectId),
mSessionId(sessionId),
mIoId(ioId),
- mDesc(desc) {
+ mDesc(desc),
+ mIsProxyEffect(isProxyEffect) {
createAidlConversion(effect, sessionId, ioId, desc);
}
EffectHalAidl::~EffectHalAidl() {
- if (mFactory) {
- mFactory->destroyEffect(mEffect);
+ if (mEffect) {
+ mIsProxyEffect ? std::static_pointer_cast<EffectProxy>(mEffect)->destroy()
+ : mFactory->destroyEffect(mEffect);
}
}
@@ -157,37 +161,54 @@
return OK;
}
-
// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
status_t EffectHalAidl::process() {
- size_t available = mInputQ->availableToWrite();
+ auto statusQ = mConversion->getStatusMQ();
+ auto inputQ = mConversion->getInputMQ();
+ auto outputQ = mConversion->getOutputMQ();
+ auto efGroup = mConversion->getEventFlagGroup();
+ if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
+ !outputQ->isValid() || !efGroup) {
+ ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
+ statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0,
+ outputQ ? outputQ->isValid() : 0, efGroup.get());
+ return INVALID_OPERATION;
+ }
+
+ size_t available = inputQ->availableToWrite();
size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
if (floatsToWrite == 0) {
- ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+ ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
mInBuffer->getSize() / sizeof(float), available);
return INVALID_OPERATION;
}
- if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
- ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+ if (!mInBuffer->audioBuffer() ||
+ !inputQ->write((float*)mInBuffer->audioBuffer()->f32, floatsToWrite)) {
+ ALOGE("%s failed to write %zu floats from audiobuffer %p to inputQ [avail %zu]", __func__,
+ floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
return INVALID_OPERATION;
}
+ efGroup->wake(aidl::android::hardware::audio::effect::kEventFlagNotEmpty);
IEffect::Status retStatus{};
- if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+ if (!statusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
(size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
- ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+ ALOGE("%s read status failed: %s", __func__, retStatus.toString().c_str());
return INVALID_OPERATION;
}
- available = mOutputQ->availableToRead();
+ available = outputQ->availableToRead();
size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
if (floatsToRead == 0) {
- ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+ ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
mOutBuffer->getSize() / sizeof(float), available);
return INVALID_OPERATION;
}
- if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
- ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+ // always read floating point data for AIDL
+ if (!mOutBuffer->audioBuffer() ||
+ !outputQ->read(mOutBuffer->audioBuffer()->f32, floatsToRead)) {
+ ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", __func__, floatsToRead,
+ mOutBuffer->audioBuffer());
return INVALID_OPERATION;
}
@@ -210,20 +231,7 @@
return INVALID_OPERATION;
}
- status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
- // update FMQs when effect open successfully
- if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
- const auto& retParam = mConversion->getEffectReturnParam();
- mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
- mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
- mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
- if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
- ALOGE("%s return with invalid FMQ", __func__);
- return NO_INIT;
- }
- }
-
- return ret;
+ return mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
}
status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 194150d..47049d7 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -23,6 +23,7 @@
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <system/audio_effect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
#include "EffectConversionHelperAidl.h"
@@ -31,11 +32,6 @@
class EffectHalAidl : public EffectHalInterface {
public:
- using StatusMQ = ::android::AidlMessageQueue<
- ::aidl::android::hardware::audio::effect::IEffect::Status,
- ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
- using DataMQ = ::android::AidlMessageQueue<
- float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
// Set the input buffer.
status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
@@ -83,12 +79,11 @@
const int32_t mSessionId;
const int32_t mIoId;
const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+ const bool mIsProxyEffect;
+
std::unique_ptr<EffectConversionHelperAidl> mConversion;
- std::unique_ptr<StatusMQ> mStatusQ;
- std::unique_ptr<DataMQ> mInputQ, mOutputQ;
sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
- effect_config_t mConfig;
status_t createAidlConversion(
std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
@@ -99,8 +94,10 @@
const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory,
const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect,
uint64_t effectId, int32_t sessionId, int32_t ioId,
- const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+ const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ bool isProxyEffect);
bool setEffectReverse(bool reverse);
+ bool needUpdateReturnParam(uint32_t cmdCode);
// The destructor automatically releases the effect.
virtual ~EffectHalAidl();
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
new file mode 100644
index 0000000..b61532d
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <memory>
+#define LOG_TAG "EffectProxy"
+//#define LOG_NDEBUG 0
+
+#include <fmq/AidlMessageQueue.h>
+#include <utils/Log.h>
+
+#include "EffectProxy.h"
+
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
+using ::aidl::android::media::audio::common::AudioUuid;
+
+namespace android {
+namespace effect {
+
+EffectProxy::EffectProxy(const Descriptor::Identity& id, const std::shared_ptr<IFactory>& factory)
+ : mIdentity([](const Descriptor::Identity& subId) {
+ // update EffectProxy implementation UUID to the sub-effect proxy UUID
+ ALOG_ASSERT(subId.proxy.has_value(), "Sub-effect Identity must have valid proxy UUID");
+ Descriptor::Identity tempId = subId;
+ tempId.uuid = subId.proxy.value();
+ return tempId;
+ }(id)),
+ mFactory(factory) {}
+
+EffectProxy::~EffectProxy() {
+ close();
+ destroy();
+ mSubEffects.clear();
+}
+
+// sub effect must have same proxy UUID as EffectProxy, and the type UUID must match.
+ndk::ScopedAStatus EffectProxy::addSubEffect(const Descriptor& sub) {
+ ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ if (0 != mSubEffects.count(sub.common.id) || !sub.common.id.proxy.has_value() ||
+ sub.common.id.proxy.value() != mIdentity.uuid) {
+ ALOGE("%s sub effect already exist or mismatch %s", __func__, sub.toString().c_str());
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "illegalSubEffect");
+ }
+
+ // not create sub-effect yet
+ std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[sub.common.id]) = nullptr;
+ std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[sub.common.id]) = sub;
+ // set the last added sub-effect to active before setOffloadParam()
+ mActiveSub = sub.common.id;
+ ALOGI("%s add %s to proxy %s flag %s", __func__, mActiveSub.toString().c_str(),
+ mIdentity.toString().c_str(), sub.common.flags.toString().c_str());
+
+ if (sub.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL) {
+ mSubFlags.hwAcceleratorMode = Flags::HardwareAccelerator::TUNNEL;
+ }
+
+ // initial flag values before we know which sub-effect to active (with setOffloadParam)
+ // same as HIDL EffectProxy flags
+ mSubFlags.type = Flags::Type::INSERT;
+ mSubFlags.insert = Flags::Insert::LAST;
+ mSubFlags.volume = Flags::Volume::CTRL;
+
+ // set indication if any sub-effect indication was set
+ mSubFlags.offloadIndication |= sub.common.flags.offloadIndication;
+ mSubFlags.deviceIndication |= sub.common.flags.deviceIndication;
+ mSubFlags.audioModeIndication |= sub.common.flags.audioModeIndication;
+ mSubFlags.audioSourceIndication |= sub.common.flags.audioSourceIndication;
+
+ // set bypass when all sub-effects are bypassing
+ mSubFlags.bypass &= sub.common.flags.bypass;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectProxy::create() {
+ ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+
+ for (auto& sub : mSubEffects) {
+ auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+ ALOGI("%s sub-effect %s", __func__, sub.first.uuid.toString().c_str());
+ status = mFactory->createEffect(sub.first.uuid, &effectHandle);
+ if (!status.isOk() || !effectHandle) {
+ ALOGE("%s sub-effect failed %s", __func__, sub.first.uuid.toString().c_str());
+ break;
+ }
+ }
+
+ // destroy all created effects if failure
+ if (!status.isOk()) {
+ destroy();
+ }
+ return status;
+}
+
+ndk::ScopedAStatus EffectProxy::destroy() {
+ ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
+ ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
+ if (status.isOk()) {
+ effect.reset();
+ }
+ return status;
+ });
+}
+
+const IEffect::OpenEffectReturn* EffectProxy::getEffectReturnParam() {
+ return &std::get<SubEffectTupleIndex::RETURN>(mSubEffects[mActiveSub]);
+}
+
+ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) {
+ const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
+ const auto& desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
+ ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
+ desc.common.id.uuid.toString().c_str(), desc.common.flags.toString().c_str());
+ return offload->isOffload ==
+ (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL);
+ });
+ if (itor == mSubEffects.end()) {
+ ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-");
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+ "noActiveEffctFound");
+ }
+
+ mActiveSub = itor->first;
+ ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__,
+ offload->isOffload ? "" : "non-", mActiveSub.uuid.toString().c_str(),
+ std::get<SubEffectTupleIndex::DESCRIPTOR>(itor->second).common.flags.toString().c_str());
+ return ndk::ScopedAStatus::ok();
+}
+
+// EffectProxy go over sub-effects and call IEffect interfaces
+ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ IEffect::OpenEffectReturn* ret __unused) {
+ ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
+ for (auto& sub : mSubEffects) {
+ auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+ auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
+ if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
+ ALOGE("%s: failed to open UUID %s", __func__, sub.first.uuid.toString().c_str());
+ break;
+ }
+ }
+
+ // close all opened effects if failure
+ if (!status.isOk()) {
+ close();
+ }
+
+ return status;
+}
+
+ndk::ScopedAStatus EffectProxy::close() {
+ ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+ return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
+ return effect->close();
+ });
+}
+
+ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) {
+ if (!desc) {
+ ALOGE("%s: nuull descriptor pointer", __func__);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "nullptr");
+ }
+
+ auto& activeSubEffect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
+ // return initial descriptor if no active sub-effect exist
+ if (!activeSubEffect) {
+ desc->common.id = mIdentity;
+ desc->common.flags = mSubFlags;
+ desc->common.name = "Proxy";
+ desc->common.implementor = "AOSP";
+ } else {
+ *desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(mSubEffects[mActiveSub]);
+ desc->common.id = mIdentity;
+ }
+
+ ALOGI("%s with %s", __func__, desc->toString().c_str());
+ return ndk::ScopedAStatus::ok();
+}
+
+// Handle with active sub-effect first, only send to other sub-effects when success
+ndk::ScopedAStatus EffectProxy::command(CommandId id) {
+ ALOGV("%s: %s, command %s", __func__, mIdentity.type.toString().c_str(),
+ android::internal::ToString(id).c_str());
+ return runWithActiveSubEffectThenOthers(
+ [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+ return effect->command(id);
+ });
+}
+
+// Return the active sub-effect state
+ndk::ScopedAStatus EffectProxy::getState(State* state) {
+ return runWithActiveSubEffect(
+ [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+ return effect->getState(state);
+ });
+}
+
+// Handle with active sub-effect first, only send to other sub-effects when success
+ndk::ScopedAStatus EffectProxy::setParameter(const Parameter& param) {
+ return runWithActiveSubEffectThenOthers(
+ [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+ return effect->setParameter(param);
+ });
+}
+
+// Return the active sub-effect parameter
+ndk::ScopedAStatus EffectProxy::getParameter(const Parameter::Id& id, Parameter* param) {
+ return runWithActiveSubEffect(
+ [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
+ return effect->getParameter(id, param);
+ });
+}
+
+ndk::ScopedAStatus EffectProxy::runWithActiveSubEffectThenOthers(
+ std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
+ ndk::ScopedAStatus status = runWithActiveSubEffect(func);
+ if (!status.isOk()) {
+ return status;
+ }
+
+ // proceed with others if active sub-effect success
+ for (const auto& sub : mSubEffects) {
+ auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+ if (sub.first != mActiveSub) {
+ if (!effect) {
+ ALOGE("%s null sub-effect interface for %s", __func__,
+ sub.first.toString().c_str());
+ continue;
+ }
+ func(effect);
+ }
+ }
+ return status;
+}
+
+ndk::ScopedAStatus EffectProxy::runWithActiveSubEffect(
+ std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
+ auto& effect = std::get<SubEffectTupleIndex::HANDLE>(mSubEffects[mActiveSub]);
+ if (!effect) {
+ ALOGE("%s null active sub-effect interface, active %s", __func__,
+ mActiveSub.toString().c_str());
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
+ "activeSubEffectNull");
+ }
+ return func(effect);
+}
+
+ndk::ScopedAStatus EffectProxy::runWithAllSubEffects(
+ std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func) {
+ ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
+ // proceed with others if active sub-effect success
+ for (auto& sub : mSubEffects) {
+ auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
+ if (!effect) {
+ ALOGW("%s null sub-effect interface for %s", __func__, sub.first.toString().c_str());
+ continue;
+ }
+ ndk::ScopedAStatus temp = func(effect);
+ if (!temp.isOk()) {
+ status = ndk::ScopedAStatus::fromStatus(temp.getStatus());
+ }
+ }
+ return status;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectProxy.h b/media/libaudiohal/impl/EffectProxy.h
new file mode 100644
index 0000000..ffb8a19
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <memory>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <aidl/android/hardware/audio/effect/BnFactory.h>
+#include <fmq/AidlMessageQueue.h>
+#include <system/audio_effect.h>
+
+namespace android {
+namespace effect {
+
+/**
+ * EffectProxy is the proxy for one or more effect AIDL implementations (sub effect) of same type.
+ * The audio framework use EffectProxy as a composite implementation of all sub effect
+ * implementations.
+ *
+ * At any given time, there is only one active effect which consuming and producing data for each
+ * proxy. All setter commands (except the legacy EFFECT_CMD_OFFLOAD, it will be handled by the audio
+ * framework directly) and parameters will be pass through to all sub effects, the getter commands
+ * and parameters will only passthrough to the active sub-effect.
+ *
+ */
+class EffectProxy final : public ::aidl::android::hardware::audio::effect::BnEffect {
+ public:
+ EffectProxy(const ::aidl::android::hardware::audio::effect::Descriptor::Identity& id,
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory);
+
+ /**
+ * Add a sub effect into the proxy, the descriptor of candidate sub-effect need to have same
+ * proxy UUID as mUuid.
+ */
+ ndk::ScopedAStatus addSubEffect(
+ const ::aidl::android::hardware::audio::effect::Descriptor& sub);
+
+ /**
+ * Create all sub-effects via AIDL IFactory, always call create() after all sub-effects added
+ * successfully with addSubEffect.
+ */
+ ndk::ScopedAStatus create();
+
+ /**
+ * Destroy all sub-effects via AIDL IFactory, always call create() after all sub-effects added
+ * successfully with addSubEffect.
+ */
+ ndk::ScopedAStatus destroy();
+
+ /**
+ * Handle offload parameter setting from framework.
+ */
+ ndk::ScopedAStatus setOffloadParam(const effect_offload_param_t* offload);
+
+ /**
+ * Get the const reference of the active sub-effect return parameters.
+ * Always use this interface to get the effect open return parameters (FMQs) after a success
+ * setOffloadParam() call.
+ */
+ const IEffect::OpenEffectReturn* getEffectReturnParam();
+
+ // IEffect interfaces override
+ ndk::ScopedAStatus open(
+ const ::aidl::android::hardware::audio::effect::Parameter::Common& common,
+ const std::optional<::aidl::android::hardware::audio::effect::Parameter::Specific>&
+ specific,
+ ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn* ret) override;
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus getDescriptor(
+ ::aidl::android::hardware::audio::effect::Descriptor* desc) override;
+ ndk::ScopedAStatus command(::aidl::android::hardware::audio::effect::CommandId id) override;
+ ndk::ScopedAStatus getState(::aidl::android::hardware::audio::effect::State* state) override;
+ ndk::ScopedAStatus setParameter(
+ const ::aidl::android::hardware::audio::effect::Parameter& param) override;
+ ndk::ScopedAStatus getParameter(
+ const ::aidl::android::hardware::audio::effect::Parameter::Id& id,
+ ::aidl::android::hardware::audio::effect::Parameter* param) override;
+
+ private:
+ // Proxy identity, copy from one sub-effect, and update the implementation UUID to proxy UUID
+ const ::aidl::android::hardware::audio::effect::Descriptor::Identity mIdentity;
+ const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
+
+ // A map of sub effects descriptor to the IEffect handle and return FMQ
+ enum SubEffectTupleIndex { HANDLE, DESCRIPTOR, RETURN };
+ using EffectProxySub =
+ std::tuple<std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>,
+ ::aidl::android::hardware::audio::effect::Descriptor,
+ ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn>;
+ std::map<const ::aidl::android::hardware::audio::effect::Descriptor::Identity, EffectProxySub>
+ mSubEffects;
+
+ // Descriptor of the only active effect in the mSubEffects map
+ ::aidl::android::hardware::audio::effect::Descriptor::Identity mActiveSub;
+
+ // keep the flag of sub-effects
+ ::aidl::android::hardware::audio::effect::Flags mSubFlags;
+
+ ndk::ScopedAStatus runWithActiveSubEffectThenOthers(
+ std::function<ndk::ScopedAStatus(
+ const std::shared_ptr<
+ ::aidl::android::hardware::audio::effect::IEffect>&)> const& func);
+
+ ndk::ScopedAStatus runWithActiveSubEffect(
+ std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func);
+
+ ndk::ScopedAStatus runWithAllSubEffects(
+ std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func);
+
+ // close and release all sub-effects
+ ~EffectProxy();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index f289f24..bc05aa0 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -15,7 +15,9 @@
*/
#include <algorithm>
+#include <cstddef>
#include <cstdint>
+#include <iterator>
#include <memory>
#define LOG_TAG "EffectsFactoryHalAidl"
//#define LOG_NDEBUG 0
@@ -29,10 +31,12 @@
#include "EffectBufferHalAidl.h"
#include "EffectHalAidl.h"
+#include "EffectProxy.h"
#include "EffectsFactoryHalAidl.h"
using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::media::audio::common::AudioUuid;
using android::detail::AudioHalVersionInfo;
@@ -42,12 +46,56 @@
EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
: mFactory(effectsFactory),
- mHalVersion(AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, [this]() {
- int32_t majorVersion = 0;
- return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk()) ? majorVersion
- : 0;
- }())) {
- ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
+ mHalVersion(AudioHalVersionInfo(
+ AudioHalVersionInfo::Type::AIDL,
+ [this]() {
+ int32_t majorVersion = 0;
+ return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk())
+ ? majorVersion
+ : 0;
+ }())),
+ mHalDescList([this]() {
+ std::vector<Descriptor> list;
+ if (mFactory) {
+ mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list).isOk();
+ }
+ return list;
+ }()),
+ mUuidProxyMap([this]() {
+ std::map<AudioUuid, std::shared_ptr<EffectProxy>> proxyMap;
+ for (const auto& desc : mHalDescList) {
+ // create EffectProxy
+ if (desc.common.id.proxy.has_value()) {
+ const auto& uuid = desc.common.id.proxy.value();
+ if (0 == proxyMap.count(uuid)) {
+ proxyMap.insert({uuid, ndk::SharedRefBase::make<EffectProxy>(desc.common.id,
+ mFactory)});
+ }
+ proxyMap[uuid]->addSubEffect(desc);
+ ALOGI("%s addSubEffect %s", __func__, desc.common.toString().c_str());
+ }
+ }
+ return proxyMap;
+ }()),
+ mProxyDescList([this]() {
+ std::vector<Descriptor> list;
+ for (const auto& proxy : mUuidProxyMap) {
+ if (Descriptor desc; proxy.second && proxy.second->getDescriptor(&desc).isOk()) {
+ list.emplace_back(std::move(desc));
+ }
+ }
+ return list;
+ }()),
+ mNonProxyDescList([this]() {
+ std::vector<Descriptor> list;
+ std::copy_if(mHalDescList.begin(), mHalDescList.end(), std::back_inserter(list),
+ [](const Descriptor& desc) { return !desc.common.id.proxy.has_value(); });
+ return list;
+ }()),
+ mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()) {
+ ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
+ ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
+ mProxyDescList.size());
}
status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -55,11 +103,7 @@
return BAD_VALUE;
}
- {
- std::lock_guard lg(mLock);
- RETURN_STATUS_IF_ERROR(queryEffectList_l());
- *pNumEffects = mDescList->size();
- }
+ *pNumEffects = mEffectCount;
ALOGI("%s %d", __func__, *pNumEffects);
return OK;
}
@@ -69,42 +113,43 @@
return BAD_VALUE;
}
- std::lock_guard lg(mLock);
- RETURN_STATUS_IF_ERROR(queryEffectList_l());
-
- auto listSize = mDescList->size();
- if (index >= listSize) {
- ALOGE("%s index %d exceed size DescList %zd", __func__, index, listSize);
+ if (index >= mEffectCount) {
+ ALOGE("%s index %d exceed max number %zu", __func__, index, mEffectCount);
return INVALID_OPERATION;
}
- *pDescriptor = VALUE_OR_RETURN_STATUS(
- ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(mDescList->at(index)));
+ if (index >= mNonProxyDescList.size()) {
+ *pDescriptor =
+ VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
+ mProxyDescList.at(index - mNonProxyDescList.size())));
+ } else {
+ *pDescriptor =
+ VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_Descriptor_effect_descriptor(
+ mNonProxyDescList.at(index)));
+ }
return OK;
}
status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
effect_descriptor_t* pDescriptor) {
- if (halUuid == nullptr || pDescriptor == nullptr) {
+ if (halUuid == nullptr) {
return BAD_VALUE;
}
- AudioUuid uuid = VALUE_OR_RETURN_STATUS(
- ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
- std::lock_guard lg(mLock);
- return getHalDescriptorWithImplUuid_l(uuid, pDescriptor);
+ AudioUuid uuid =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
+ return getHalDescriptorWithImplUuid(uuid, pDescriptor);
}
status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
std::vector<effect_descriptor_t>* descriptors) {
- if (halType == nullptr || descriptors == nullptr) {
+ if (halType == nullptr) {
return BAD_VALUE;
}
- AudioUuid type = VALUE_OR_RETURN_STATUS(
- ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
- std::lock_guard lg(mLock);
- return getHalDescriptorWithTypeUuid_l(type, descriptors);
+ AudioUuid type =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
+ return getHalDescriptorWithTypeUuid(type, descriptors);
}
status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
@@ -116,18 +161,25 @@
if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
return INVALID_OPERATION;
}
-
ALOGI("%s session %d ioId %d", __func__, sessionId, ioId);
- AudioUuid aidlUuid = VALUE_OR_RETURN_STATUS(
- ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
+ AudioUuid aidlUuid =
+ VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
std::shared_ptr<IEffect> aidlEffect;
- Descriptor desc;
- RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+ // Use EffectProxy interface instead of IFactory to create
+ const bool isProxy = isProxyEffect(aidlUuid);
+ if (isProxy) {
+ aidlEffect = mUuidProxyMap.at(aidlUuid);
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mUuidProxyMap.at(aidlUuid)->create()));
+ } else {
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+ }
if (aidlEffect == nullptr) {
- ALOGE("%s IFactory::createFactory failed UUID %s", __func__, aidlUuid.toString().c_str());
+ ALOGE("%s failed to create effect with UUID: %s", __func__, aidlUuid.toString().c_str());
return NAME_NOT_FOUND;
}
+ Descriptor desc;
RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
uint64_t effectId;
@@ -136,13 +188,23 @@
effectId = ++mEffectIdCounter;
}
- *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc);
+ *effect =
+ sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc, isProxy);
return OK;
}
status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
- // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
- return mFactory->dump(fd, nullptr, 0);
+ status_t ret = OK;
+ // record the error ret and continue dump as many effects as possible
+ for (const auto& proxy : mUuidProxyMap) {
+ if (proxy.second) {
+ if (status_t temp = proxy.second->dump(fd, nullptr, 0); temp != OK) {
+ ret = temp;
+ }
+ }
+ }
+ RETURN_STATUS_IF_ERROR(mFactory->dump(fd, nullptr, 0));
+ return ret;
}
status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
@@ -160,56 +222,42 @@
return mHalVersion;
}
-status_t EffectsFactoryHalAidl::queryEffectList_l() {
- if (!mDescList) {
- std::vector<Descriptor> list;
- auto status = mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list);
- if (!status.isOk()) {
- ALOGE("%s IFactory::queryEffects failed %s", __func__, status.getDescription().c_str());
- return status.getStatus();
- }
-
- mDescList = std::make_unique<std::vector<Descriptor>>(list);
- }
- return OK;
-}
-
-status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid_l(const AudioUuid& uuid,
- effect_descriptor_t* pDescriptor) {
+status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid(const AudioUuid& uuid,
+ effect_descriptor_t* pDescriptor) {
if (pDescriptor == nullptr) {
return BAD_VALUE;
}
- if (!mDescList) {
- RETURN_STATUS_IF_ERROR(queryEffectList_l());
- }
- auto matchIt = std::find_if(mDescList->begin(), mDescList->end(),
- [&](const auto& desc) { return desc.common.id.uuid == uuid; });
- if (matchIt == mDescList->end()) {
- ALOGE("%s UUID %s not found", __func__, uuid.toString().c_str());
+ const auto& list = isProxyEffect(uuid) ? mProxyDescList : mNonProxyDescList;
+ auto matchIt = std::find_if(list.begin(), list.end(),
+ [&](const auto& desc) { return desc.common.id.uuid == uuid; });
+ if (matchIt == list.end()) {
+ ALOGE("%s UUID not found in HAL and proxy list %s", __func__, uuid.toString().c_str());
return BAD_VALUE;
}
+ ALOGI("%s UUID impl found %s", __func__, uuid.toString().c_str());
*pDescriptor = VALUE_OR_RETURN_STATUS(
::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
return OK;
}
-status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid_l(
+status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid(
const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
if (descriptors == nullptr) {
return BAD_VALUE;
}
- if (!mDescList) {
- RETURN_STATUS_IF_ERROR(queryEffectList_l());
- }
+
std::vector<Descriptor> result;
- std::copy_if(mDescList->begin(), mDescList->end(), std::back_inserter(result),
+ std::copy_if(mNonProxyDescList.begin(), mNonProxyDescList.end(), std::back_inserter(result),
[&](auto& desc) { return desc.common.id.type == type; });
- if (result.size() == 0) {
- ALOGE("%s type UUID %s not found", __func__, type.toString().c_str());
+ std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
+ [&](auto& desc) { return desc.common.id.type == type; });
+ if (result.empty()) {
+ ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, type.toString().c_str());
return BAD_VALUE;
}
+ ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), type.toString().c_str());
*descriptors = VALUE_OR_RETURN_STATUS(
aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
@@ -217,6 +265,10 @@
return OK;
}
+bool EffectsFactoryHalAidl::isProxyEffect(const AudioUuid& uuid) const {
+ return 0 != mUuidProxyMap.count(uuid);
+}
+
} // namespace effect
// When a shared library is built from a static library, even explicit
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 9c3643b..debfacf 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -25,6 +25,8 @@
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/thread_defs.h>
+#include "EffectProxy.h"
+
namespace android {
namespace effect {
@@ -60,24 +62,35 @@
detail::AudioHalVersionInfo getHalVersion() const override;
- // for TIME_CHECK
- const std::string getClassName() const { return "EffectHalAidl"; }
-
private:
- std::mutex mLock;
const std::shared_ptr<IFactory> mFactory;
- uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
- std::unique_ptr<std::vector<Descriptor>> mDescList GUARDED_BY(mLock) = nullptr;
const detail::AudioHalVersionInfo mHalVersion;
+ // Full list of HAL effect descriptors
+ const std::vector<Descriptor> mHalDescList;
+ // Map of proxy UUID (key) to the proxy object
+ const std::map<::aidl::android::media::audio::common::AudioUuid /* proxy impl UUID */,
+ std::shared_ptr<EffectProxy>>
+ mUuidProxyMap;
+ // List of effect proxy, initialize after mUuidProxyMap because it need to have all sub-effects
+ const std::vector<Descriptor> mProxyDescList;
+ // List of non-proxy effects
+ const std::vector<Descriptor> mNonProxyDescList;
+ // total number of effects including proxy effects
+ const size_t mEffectCount;
+
+ std::mutex mLock;
+ uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
virtual ~EffectsFactoryHalAidl() = default;
- status_t queryEffectList_l() REQUIRES(mLock);
- status_t getHalDescriptorWithImplUuid_l(
+ status_t getHalDescriptorWithImplUuid(
const aidl::android::media::audio::common::AudioUuid& uuid,
- effect_descriptor_t* pDescriptor) REQUIRES(mLock);
- status_t getHalDescriptorWithTypeUuid_l(
+ effect_descriptor_t* pDescriptor);
+
+ status_t getHalDescriptorWithTypeUuid(
const aidl::android::media::audio::common::AudioUuid& type,
- std::vector<effect_descriptor_t>* descriptors) REQUIRES(mLock);
+ std::vector<effect_descriptor_t>* descriptors);
+
+ bool isProxyEffect(const aidl::android::media::audio::common::AudioUuid& uuid) const;
};
} // namespace effect
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index cbc1578..6c43591 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -22,6 +22,7 @@
#include <audio_utils/clock.h>
#include <media/AidlConversion.h>
+#include <media/AidlConversionCore.h>
#include <media/AidlConversionCppNdk.h>
#include <media/AidlConversionNdk.h>
#include <media/AidlConversionUtil.h>
@@ -40,6 +41,7 @@
using ::aidl::android::hardware::audio::core::IStreamIn;
using ::aidl::android::hardware::audio::core::IStreamOut;
using ::aidl::android::hardware::audio::core::StreamDescriptor;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
namespace android {
@@ -166,9 +168,8 @@
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
values->clear();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ // AIDL HAL doesn't support getParameters API.
+ return INVALID_OPERATION;
}
status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -255,16 +256,23 @@
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ const auto state = getState();
+ StreamDescriptor::Reply reply;
+ if (state == StreamDescriptor::State::STANDBY) {
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true);
+ status != OK) {
+ return status;
+ }
+ return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true);
+ }
+
+ return INVALID_OPERATION;
}
status_t StreamHalAidl::stop() {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
- TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return standby();
}
status_t StreamHalAidl::getLatency(uint32_t *latency) {
@@ -290,6 +298,20 @@
return OK;
}
+status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
+ ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+ if (!mStream) return NO_INIT;
+ StreamDescriptor::Reply reply;
+ // TODO: switch to updateCountersIfNeeded once we sort out mWorkerTid initialization
+ if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), &reply, true);
+ status != OK) {
+ return status;
+ }
+ *frames = reply.hardware.frames;
+ *timestamp = reply.hardware.timeNs;
+ return OK;
+}
+
status_t StreamHalAidl::getXruns(int32_t *frames) {
ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
if (!mStream) return NO_INIT;
@@ -419,19 +441,35 @@
}
status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
- struct audio_mmap_buffer_info *info __unused) {
+ struct audio_mmap_buffer_info *info) {
ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (!mContext.isMmapped()) {
+ return BAD_VALUE;
+ }
+ const MmapBufferDescriptor& bufferDescriptor = mContext.getMmapBufferDescriptor();
+ info->shared_memory_fd = bufferDescriptor.sharedMemory.fd.get();
+ info->buffer_size_frames = mContext.getBufferSizeFrames();
+ info->burst_size_frames = bufferDescriptor.burstSizeFrames;
+ info->flags = static_cast<audio_mmap_buffer_flag>(bufferDescriptor.flags);
+
return OK;
}
-status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
- ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (!mContext.isMmapped()) {
+ return BAD_VALUE;
+ }
+ int64_t aidlPosition = 0, aidlTimestamp = 0;
+ if (status_t status = getHardwarePosition(&aidlPosition, &aidlTimestamp); status != OK) {
+ return status;
+ }
+
+ position->time_nanoseconds = aidlTimestamp;
+ position->position_frames = static_cast<int32_t>(aidlPosition);
return OK;
}
@@ -440,19 +478,6 @@
return OK;
}
-status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
- ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
- // Obsolete, must be done by the HAL module.
- return true;
-}
-
status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
std::optional<audio_source_t> source __unused,
audio_devices_t type __unused) {
@@ -574,11 +599,10 @@
return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
}
-status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
+status_t StreamOutHalAidl::selectPresentation(int presentationId, int programId) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return statusTFromBinderStatus(mStream->selectPresentation(presentationId, programId));
}
status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
@@ -684,48 +708,61 @@
return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
}
-status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (mode == nullptr) {
+ return BAD_VALUE;
+ }
+ ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getDualMonoMode(&aidlMode)));
+ *mode = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(aidlMode));
return OK;
}
-status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ ::aidl::android::media::audio::common::AudioDualMonoMode aidlMode = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(mode));
+ return statusTFromBinderStatus(mStream->setDualMonoMode(aidlMode));
+}
+
+status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (leveldB == nullptr) {
+ return BAD_VALUE;
+ }
+ return statusTFromBinderStatus(mStream->getAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ return statusTFromBinderStatus(mStream->setAudioDescriptionMixLevel(leveldB));
+}
+
+status_t StreamOutHalAidl::getPlaybackRateParameters(audio_playback_rate_t* playbackRate) {
+ TIME_CHECK();
+ if (!mStream) return NO_INIT;
+ if (playbackRate == nullptr) {
+ return BAD_VALUE;
+ }
+ ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate;
+ RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getPlaybackRateParameters(&aidlRate)));
+ *playbackRate = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(aidlRate));
return OK;
}
-status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+status_t StreamOutHalAidl::setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
-}
-
-status_t StreamOutHalAidl::getPlaybackRateParameters(
- audio_playback_rate_t* playbackRate __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return BAD_VALUE;
-}
-
-status_t StreamOutHalAidl::setPlaybackRateParameters(
- const audio_playback_rate_t& playbackRate __unused) {
- TIME_CHECK();
- if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return BAD_VALUE;
+ ::aidl::android::media::audio::common::AudioPlaybackRate aidlRate = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate));
+ return statusTFromBinderStatus(mStream->setPlaybackRateParameters(aidlRate));
}
status_t StreamOutHalAidl::setEventCallback(
@@ -738,18 +775,27 @@
return OK;
}
-status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
+status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ ::aidl::android::media::audio::common::AudioLatencyMode aidlMode = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
+ return statusTFromBinderStatus(mStream->setLatencyMode(aidlMode));
};
-status_t StreamOutHalAidl::getRecommendedLatencyModes(
- std::vector<audio_latency_mode_t> *modes __unused) {
+status_t StreamOutHalAidl::getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
+ if (modes == nullptr) {
+ return BAD_VALUE;
+ }
+ std::vector<::aidl::android::media::audio::common::AudioLatencyMode> aidlModes;
+ RETURN_STATUS_IF_ERROR(
+ statusTFromBinderStatus(mStream->getRecommendedLatencyModes(&aidlModes)));
+ *modes = VALUE_OR_RETURN_STATUS(
+ ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+ aidlModes,
+ ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
return OK;
};
@@ -845,11 +891,10 @@
std::move(context), getStreamCommon(stream)),
mStream(stream), mMicInfoProvider(micInfoProvider) {}
-status_t StreamInHalAidl::setGain(float gain __unused) {
+status_t StreamInHalAidl::setGain(float gain) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return statusTFromBinderStatus(mStream->setHwGain({gain}));
}
status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
@@ -922,19 +967,20 @@
return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
}
-status_t StreamInHalAidl::setPreferredMicrophoneDirection(
- audio_microphone_direction_t direction __unused) {
+status_t StreamInHalAidl::setPreferredMicrophoneDirection(audio_microphone_direction_t direction) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ ::aidl::android::hardware::audio::core::IStreamIn::MicrophoneDirection aidlDirection =
+ VALUE_OR_RETURN_STATUS(
+ ::aidl::android::legacy2aidl_audio_microphone_direction_t_MicrophoneDirection(
+ direction));
+ return statusTFromBinderStatus(mStream->setMicrophoneDirection(aidlDirection));
}
-status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
+status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom) {
TIME_CHECK();
if (!mStream) return NO_INIT;
- ALOGE("%s not implemented yet", __func__);
- return OK;
+ return statusTFromBinderStatus(mStream->setMicrophoneFieldDimension(zoom));
}
} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 157e8bb..75a1dd9 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -25,6 +25,7 @@
#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
#include <aidl/android/hardware/audio/core/BpStreamIn.h>
#include <aidl/android/hardware/audio/core/BpStreamOut.h>
+#include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
#include <fmq/AidlMessageQueue.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/StreamHalInterface.h>
@@ -34,6 +35,7 @@
#include "StreamPowerLog.h"
using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
+using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
namespace android {
@@ -47,21 +49,25 @@
::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
explicit StreamContextAidl(
- const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+ ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
bool isAsynchronous)
: mFrameSizeBytes(descriptor.frameSizeBytes),
mCommandMQ(new CommandMQ(descriptor.command)),
mReplyMQ(new ReplyMQ(descriptor.reply)),
mBufferSizeFrames(descriptor.bufferSizeFrames),
mDataMQ(maybeCreateDataMQ(descriptor)),
- mIsAsynchronous(isAsynchronous) {}
+ mIsAsynchronous(isAsynchronous),
+ mIsMmapped(isMmapped(descriptor)),
+ mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)) {}
StreamContextAidl(StreamContextAidl&& other) :
mFrameSizeBytes(other.mFrameSizeBytes),
mCommandMQ(std::move(other.mCommandMQ)),
mReplyMQ(std::move(other.mReplyMQ)),
mBufferSizeFrames(other.mBufferSizeFrames),
mDataMQ(std::move(other.mDataMQ)),
- mIsAsynchronous(other.mIsAsynchronous) {}
+ mIsAsynchronous(other.mIsAsynchronous),
+ mIsMmapped(other.mIsMmapped),
+ mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)) {}
StreamContextAidl& operator=(StreamContextAidl&& other) {
mFrameSizeBytes = other.mFrameSizeBytes;
mCommandMQ = std::move(other.mCommandMQ);
@@ -69,16 +75,19 @@
mBufferSizeFrames = other.mBufferSizeFrames;
mDataMQ = std::move(other.mDataMQ);
mIsAsynchronous = other.mIsAsynchronous;
+ mIsMmapped = other.mIsMmapped;
+ mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor);
return *this;
}
bool isValid() const {
return mFrameSizeBytes != 0 &&
mCommandMQ != nullptr && mCommandMQ->isValid() &&
mReplyMQ != nullptr && mReplyMQ->isValid() &&
- (mDataMQ != nullptr || (
+ (mDataMQ == nullptr || (
mDataMQ->isValid() &&
mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
- mFrameSizeBytes * mBufferSizeFrames));
+ mFrameSizeBytes * mBufferSizeFrames)) &&
+ (!mIsMmapped || mMmapBufferDescriptor.sharedMemory.fd.get() >= 0);
}
size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
@@ -87,6 +96,8 @@
size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
bool isAsynchronous() const { return mIsAsynchronous; }
+ bool isMmapped() const { return mIsMmapped; }
+ const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; }
private:
static std::unique_ptr<DataMQ> maybeCreateDataMQ(
@@ -97,6 +108,19 @@
}
return nullptr;
}
+ static bool isMmapped(
+ const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ return descriptor.audio.getTag() == Tag::mmap;
+ }
+ static MmapBufferDescriptor maybeGetMmapBuffer(
+ ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+ using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+ if (descriptor.audio.getTag() == Tag::mmap) {
+ return std::move(descriptor.audio.get<Tag::mmap>());
+ }
+ return {};
+ }
size_t mFrameSizeBytes;
std::unique_ptr<CommandMQ> mCommandMQ;
@@ -104,6 +128,8 @@
size_t mBufferSizeFrames;
std::unique_ptr<DataMQ> mDataMQ;
bool mIsAsynchronous;
+ bool mIsMmapped;
+ MmapBufferDescriptor mMmapBufferDescriptor;
};
class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
@@ -173,14 +199,12 @@
~StreamHalAidl() override;
- status_t getHalPid(pid_t *pid);
-
- bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
-
status_t getLatency(uint32_t *latency);
status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+ status_t getHardwarePosition(int64_t *frames, int64_t *timestamp);
+
status_t getXruns(int32_t *frames);
status_t transfer(void *buffer, size_t bytes, size_t *transferred);
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index c685345..2523ba6 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -128,13 +128,14 @@
std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
virtual int32_t getAAudioMixerBurstCount() = 0;
virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+
virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
// Update the connection status of an external device.
- virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) {
- ALOGE("%s override me port %p connected %d", __func__, port, connected);
- return OK;
- }
+ virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) = 0;
+
+ // Enable simulation of external devices connection at the HAL level.
+ virtual status_t setSimulateDeviceConnections(bool enabled) = 0;
virtual error::Result<audio_hw_sync_t> getHwAvSync() = 0;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 2f78dd0..8210f7d 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -20,18 +20,12 @@
default_applicable_licenses: ["frameworks_av_license"],
}
-cc_test {
- name: "EffectsFactoryHalInterfaceTest",
+cc_defaults {
+ name: "AudioHalTestDefaults",
test_suites: ["device-tests"],
-
- srcs: [
- "EffectsFactoryHalInterface_test.cpp",
- ],
-
defaults: [
"latest_android_media_audio_common_types_ndk_shared",
],
-
cflags: [
"-Wall",
"-Wextra",
@@ -48,8 +42,31 @@
"libutils",
"libvibrator",
],
+}
- header_libs: [
- "libaudiohal_headers",
+cc_test {
+ name: "EffectsFactoryHalInterfaceTest",
+ srcs: ["EffectsFactoryHalInterface_test.cpp"],
+ defaults: ["AudioHalTestDefaults"],
+ header_libs: ["libaudiohal_headers"],
+}
+
+cc_test {
+ name: "EffectProxyTest",
+ srcs: [
+ "EffectProxy_test.cpp",
+ ":audio_effectproxy_src_files",
],
+ defaults: [
+ "AudioHalTestDefaults",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ "libaudiohal_default",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ shared_libs: [
+ "android.hardware.common.fmq-V1-ndk",
+ "libbinder_ndk",
+ "libfmq",
+ ],
+ header_libs: ["libaudiohalimpl_headers"],
}
diff --git a/media/libaudiohal/tests/EffectProxy_test.cpp b/media/libaudiohal/tests/EffectProxy_test.cpp
new file mode 100644
index 0000000..92e3dce
--- /dev/null
+++ b/media/libaudiohal/tests/EffectProxy_test.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#define LOG_TAG "EffectProxyTest"
+
+#include <aidl/android/media/audio/common/AudioUuid.h>
+#include <aidl/Vintf.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include "EffectProxy.h"
+
+/**
+ * This test suite is depending on audio effect AIDL service.
+ */
+namespace android {
+
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::State;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioFormatDescription;
+using ::aidl::android::media::audio::common::AudioFormatType;
+using ::aidl::android::media::audio::common::AudioUuid;
+using ::aidl::android::media::audio::common::PcmType;
+using ::android::effect::EffectProxy;
+
+class EffectProxyTest : public testing::Test {
+ public:
+ void SetUp() override {
+ auto serviceName = android::getAidlHalInstanceNames(IFactory::descriptor);
+ // only unit test with the first one in case more than one EffectFactory service exist
+ ASSERT_NE(0ul, serviceName.size());
+ mFactory = IFactory::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(serviceName[0].c_str())));
+ ASSERT_NE(nullptr, mFactory);
+ mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &mDescs);
+ for (const auto& desc : mDescs) {
+ if (desc.common.id.proxy.has_value()) {
+ mProxyDescs.insert({desc.common.id, desc});
+ }
+ }
+ }
+
+ void TearDown() override {}
+
+ const AudioFormatDescription kDefaultFormatDescription = {
+ .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
+
+ Parameter::Common createParamCommon(
+ int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
+ long iFrameCount = 0x100, long oFrameCount = 0x100,
+ AudioChannelLayout inputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO),
+ AudioChannelLayout outputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO)) {
+ Parameter::Common common;
+ common.session = session;
+ common.ioHandle = ioHandle;
+
+ auto& input = common.input;
+ auto& output = common.output;
+ input.base.sampleRate = iSampleRate;
+ input.base.channelMask = inputChannelLayout;
+ input.base.format = kDefaultFormatDescription;
+ input.frameCount = iFrameCount;
+ output.base.sampleRate = oSampleRate;
+ output.base.channelMask = outputChannelLayout;
+ output.base.format = kDefaultFormatDescription;
+ output.frameCount = oFrameCount;
+ return common;
+ }
+
+ static bool isFlagSet(const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+ Flags::HardwareAccelerator flag) {
+ return desc.common.flags.hwAcceleratorMode == flag;
+ }
+
+ enum TupleIndex { HANDLE, DESCRIPTOR };
+ using EffectProxyTuple = std::tuple<std::shared_ptr<EffectProxy>, std::vector<Descriptor>>;
+
+ std::map<AudioUuid, EffectProxyTuple> createAllProxies() {
+ std::map<AudioUuid, EffectProxyTuple> proxyMap;
+ for (const auto& itor : mProxyDescs) {
+ const auto& uuid = itor.first.proxy.value();
+ if (proxyMap.end() == proxyMap.find(uuid)) {
+ std::get<TupleIndex::HANDLE>(proxyMap[uuid]) =
+ ndk::SharedRefBase::make<EffectProxy>(itor.first, mFactory);
+ }
+ }
+ return proxyMap;
+ }
+
+ bool addAllSubEffects(std::map<AudioUuid, EffectProxyTuple> proxyMap) {
+ for (auto& itor : mProxyDescs) {
+ const auto& uuid = itor.first.proxy.value();
+ if (proxyMap.end() == proxyMap.find(uuid)) {
+ return false;
+ }
+ auto& proxy = std::get<TupleIndex::HANDLE>(proxyMap[uuid]);
+ if (!proxy->addSubEffect(itor.second).isOk()) {
+ return false;
+ }
+ std::get<TupleIndex::DESCRIPTOR>(proxyMap[uuid]).emplace_back(itor.second);
+ }
+ return true;
+ }
+
+ std::shared_ptr<IFactory> mFactory;
+ std::vector<Descriptor> mDescs;
+ std::map<Descriptor::Identity, Descriptor> mProxyDescs;
+};
+
+TEST_F(EffectProxyTest, createProxy) {
+ auto proxyMap = createAllProxies();
+ // if there are some descriptor defined with proxy, then proxyMap can not be empty
+ EXPECT_EQ(mProxyDescs.size() == 0, proxyMap.size() == 0);
+}
+
+TEST_F(EffectProxyTest, addSubEffectsCreateAndDestroy) {
+ auto proxyMap = createAllProxies();
+ ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+ for (const auto& itor : proxyMap) {
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+TEST_F(EffectProxyTest, addSubEffectsCreateOpenCloseDestroy) {
+ auto proxyMap = createAllProxies();
+ EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+ Parameter::Common common = createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ for (const auto& itor : proxyMap) {
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+// Add sub-effects, set active sub-effect with different checkers
+TEST_F(EffectProxyTest, setOffloadParam) {
+ auto proxyMap = createAllProxies();
+ EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+ // Any flag exist should be able to set successfully
+ bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+ for (const auto& itor : mProxyDescs) {
+ isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+ isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+ isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+ }
+
+ Parameter::Common common = createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ for (const auto& itor : proxyMap) {
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+ effect_offload_param_t offloadParam{false, 0};
+ EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ offloadParam.isOffload = true;
+ EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+TEST_F(EffectProxyTest, destroyWithoutCreate) {
+ auto proxyMap = createAllProxies();
+ ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+ for (const auto& itor : proxyMap) {
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+TEST_F(EffectProxyTest, closeWithoutOpen) {
+ auto proxyMap = createAllProxies();
+ ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+ for (const auto& itor : proxyMap) {
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+// Add sub-effects, set active sub-effect, create, open, and send command, expect success handling
+TEST_F(EffectProxyTest, normalSequency) {
+ auto proxyMap = createAllProxies();
+ ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+ bool isTunnelExist = [&]() {
+ for (const auto& itor : mProxyDescs) {
+ if (isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL)) {
+ return true;
+ }
+ }
+ return false;
+ }();
+
+ Parameter::Common common = createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ Parameter::VolumeStereo volumeStereo({.left = .1f, .right = -0.8f});
+ Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
+ Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+ State state;
+ for (const auto& itor : proxyMap) {
+ Parameter expect;
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ effect_offload_param_t offloadParam{true, 0};
+ EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+
+ EXPECT_TRUE(proxy->setParameter(param).isOk());
+ EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+ EXPECT_EQ(expect, param);
+
+ EXPECT_TRUE(proxy->command(CommandId::START).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::PROCESSING, state);
+
+ EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::IDLE, state);
+
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+// setParameter, change active sub-effect, verify with getParameter
+TEST_F(EffectProxyTest, changeActiveSubAndVerifyParameter) {
+ auto proxyMap = createAllProxies();
+ EXPECT_TRUE(addAllSubEffects(proxyMap));
+
+ bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+ for (const auto& itor : mProxyDescs) {
+ isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+ isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+ isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+ }
+
+ Parameter::Common common = createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ Parameter::VolumeStereo volumeStereo({.left = .5f, .right = .8f});
+ Parameter param = Parameter::make<Parameter::volumeStereo>(volumeStereo);
+ Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::volumeStereo);
+ for (const auto& itor : proxyMap) {
+ Parameter expect;
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+ EXPECT_TRUE(proxy->setParameter(param).isOk());
+ EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+ EXPECT_EQ(expect, param);
+
+ effect_offload_param_t offloadParam{false, 0};
+ EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+ EXPECT_EQ(expect, param);
+
+ offloadParam.isOffload = true;
+ EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->getParameter(id, &expect).isOk());
+ EXPECT_EQ(expect, param);
+
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+// send command, change active sub-effect, then verify the state with getState
+TEST_F(EffectProxyTest, changeActiveSubAndVerifyState) {
+ auto proxyMap = createAllProxies();
+ ASSERT_TRUE(addAllSubEffects(proxyMap));
+
+ bool isNoneExist = false, isSimpleExist = false, isTunnelExist = false;
+ for (const auto& itor : mProxyDescs) {
+ isNoneExist = isNoneExist || isFlagSet(itor.second, Flags::HardwareAccelerator::NONE);
+ isSimpleExist = isSimpleExist || isFlagSet(itor.second, Flags::HardwareAccelerator::SIMPLE);
+ isTunnelExist = isTunnelExist || isFlagSet(itor.second, Flags::HardwareAccelerator::TUNNEL);
+ }
+
+ Parameter::Common common = createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ State state;
+ for (const auto& itor : proxyMap) {
+ Parameter expect;
+ auto& proxy = std::get<TupleIndex::HANDLE>(itor.second);
+ EXPECT_TRUE(proxy->create().isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::INIT, state);
+ EXPECT_TRUE(proxy->open(common, std::nullopt, &ret).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::IDLE, state);
+ EXPECT_TRUE(proxy->command(CommandId::START).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::PROCESSING, state);
+
+ effect_offload_param_t offloadParam{false, 0};
+ EXPECT_EQ(isNoneExist || isSimpleExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::PROCESSING, state);
+
+ offloadParam.isOffload = true;
+ EXPECT_EQ(isTunnelExist, proxy->setOffloadParam(&offloadParam).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::PROCESSING, state);
+
+ EXPECT_TRUE(proxy->command(CommandId::STOP).isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::IDLE, state);
+
+ EXPECT_TRUE(proxy->close().isOk());
+ EXPECT_TRUE(proxy->getState(&state).isOk());
+ EXPECT_EQ(State::INIT, state);
+ EXPECT_TRUE(proxy->destroy().isOk());
+ }
+}
+
+} // namespace android
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 736a086..7838117 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -92,6 +92,10 @@
"dynamicsprocessingdefaults",
],
+ static_libs: [
+ "libaudioaidlranges",
+ ],
+
visibility: [
"//hardware/interfaces/audio/aidl/default",
],
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index e508d48..1fed9a5 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -62,32 +62,135 @@
const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+static const Range::DynamicsProcessingRange kEngineConfigRange = {
+ .min = DynamicsProcessing::make<
+ DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+ {.resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = 1.0f,
+ .preEqStage = {.inUse = false, .bandCount = 0},
+ .postEqStage = {.inUse = false, .bandCount = 0},
+ .mbcStage = {.inUse = false, .bandCount = 0},
+ .limiterInUse = false})),
+ .max = DynamicsProcessing::make<
+ DynamicsProcessing::engineArchitecture>(DynamicsProcessing::EngineArchitecture(
+ {.resolutionPreference =
+ DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION,
+ .preferredProcessingDurationMs = 1000.0f,
+ .preEqStage = {.inUse = true, .bandCount = 128},
+ .postEqStage = {.inUse = true, .bandCount = 128},
+ .mbcStage = {.inUse = true, .bandCount = 128},
+ .limiterInUse = true}))};
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMin =
+ DynamicsProcessing::ChannelConfig({.channel = 0, .enable = false});
+
+static const DynamicsProcessing::ChannelConfig kChannelConfigMax =
+ DynamicsProcessing::ChannelConfig(
+ {.channel = std::numeric_limits<int>::max(), .enable = true});
+
+static const Range::DynamicsProcessingRange kPreEqChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEq>({kChannelConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcChannelConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::mbc>({kChannelConfigMax})};
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMin =
DynamicsProcessing::EqBandConfig({.channel = 0,
.band = 0,
.enable = false,
- .cutoffFrequencyHz = 220,
- .gainDb = std::numeric_limits<float>::min()});
-const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+ .cutoffFrequencyHz = 20,
+ .gainDb = -200});
+
+static const DynamicsProcessing::EqBandConfig kEqBandConfigMax =
DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
.band = std::numeric_limits<int>::max(),
.enable = true,
.cutoffFrequencyHz = 20000,
- .gainDb = std::numeric_limits<float>::max()});
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
- .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMin}),
- .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
- .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMin}),
- .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
- {DynamicsProcessingImpl::kEqBandConfigMax})};
-const Range DynamicsProcessingImpl::kRange =
- Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+ .gainDb = 200});
-const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+static const Range::DynamicsProcessingRange kPreEqBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kPostEqBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMin}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>({kEqBandConfigMax})};
+
+static const Range::DynamicsProcessingRange kMbcBandConfigRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+ {DynamicsProcessing::MbcBandConfig(
+ {.channel = 0,
+ .band = 0,
+ .enable = false,
+ .cutoffFrequencyHz = 20,
+ .attackTimeMs = 0,
+ .releaseTimeMs = 0,
+ .ratio = 1,
+ .thresholdDb = -200,
+ .kneeWidthDb = 0,
+ .noiseGateThresholdDb = -200,
+ .expanderRatio = 1,
+ .preGainDb = -200,
+ .postGainDb = -200})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+ {DynamicsProcessing::MbcBandConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .band = std::numeric_limits<int>::max(),
+ .enable = true,
+ .cutoffFrequencyHz = 20000,
+ .attackTimeMs = 60000,
+ .releaseTimeMs = 60000,
+ .ratio = 50,
+ .thresholdDb = 200,
+ .kneeWidthDb = 100,
+ .noiseGateThresholdDb = 200,
+ .expanderRatio = 50,
+ .preGainDb = 200,
+ .postGainDb = 200})})};
+
+static const Range::DynamicsProcessingRange kInputGainRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain(
+ {.channel = 0, .gainDb = -200.0f})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
+ .gainDb = 200.0f})})};
+
+static const Range::DynamicsProcessingRange kLimiterRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+ {DynamicsProcessing::LimiterConfig(
+ {.channel = 0,
+ .enable = false,
+ .linkGroup = std::numeric_limits<int>::min(),
+ .attackTimeMs = 0,
+ .releaseTimeMs = 0,
+ .ratio = 1,
+ .thresholdDb = -200,
+ .postGainDb = -200})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+ {DynamicsProcessing::LimiterConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .enable = true,
+ .linkGroup = std::numeric_limits<int>::max(),
+ .attackTimeMs = 60000,
+ .releaseTimeMs = 60000,
+ .ratio = 50,
+ .thresholdDb = 200,
+ .postGainDb = 200})})};
+
+const std::vector<Range::DynamicsProcessingRange> kRanges = {
+ kEngineConfigRange, kPreEqChannelConfigRange, kPostEqChannelConfigRange,
+ kMbcChannelConfigRange, kPreEqBandConfigRange, kPostEqBandConfigRange,
+ kMbcBandConfigRange, kInputGainRange, kLimiterRange};
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = kRanges};
const Descriptor DynamicsProcessingImpl::kDescriptor = {
.common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
@@ -158,14 +261,19 @@
}
}
+bool DynamicsProcessingImpl::isParamInRange(const Parameter::Specific& specific) {
+ auto& dp = specific.get<Parameter::Specific::dynamicsProcessing>();
+ return DynamicsProcessingRanges::isParamInRange(dp, kRanges);
+}
+
ndk::ScopedAStatus DynamicsProcessingImpl::setParameterSpecific(
const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ RETURN_IF(!isParamInRange(specific), EX_ILLEGAL_ARGUMENT, "outOfRange");
auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
- // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
auto tag = param.getTag();
switch (tag) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index d094c69..1e1e72e 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -18,8 +18,9 @@
#include <aidl/android/hardware/audio/effect/BnEffect.h>
-#include "effect-impl/EffectImpl.h"
#include "DynamicsProcessingContext.h"
+#include "EffectRangeSpecific.h"
+#include "effect-impl/EffectImpl.h"
namespace aidl::android::hardware::audio::effect {
@@ -51,14 +52,10 @@
std::string getEffectName() override { return kEffectName; }
private:
- static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
- static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
- static const Range::DynamicsProcessingRange kPreEqBandRange;
- static const Range::DynamicsProcessingRange kPostEqBandRange;
- static const Range kRange;
std::shared_ptr<DynamicsProcessingContext> mContext;
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
Parameter::Specific* specific);
+ bool isParamInRange(const Parameter::Specific& specific);
};
} // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index 69ff522..9d77135 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -16,11 +16,11 @@
#define LOG_TAG "AHAL_DPLibEffectsContext"
-#include "DynamicsProcessing.h"
#include "DynamicsProcessingContext.h"
+#include "DynamicsProcessing.h"
-#include <functional>
#include <sys/param.h>
+#include <functional>
#include <unordered_set>
namespace aidl::android::hardware::audio::effect {
@@ -83,7 +83,7 @@
if (block < minBlockSize) {
block = minBlockSize;
} else if (!powerof2(block)) {
- //find next highest power of 2.
+ // find next highest power of 2.
block = 1 << (32 - __builtin_clz(block));
}
mDpFreq->configure(block, block >> 1, sampleRate);
@@ -91,9 +91,6 @@
RetCode DynamicsProcessingContext::setEngineArchitecture(
const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
- RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
- "illegalEngineConfig");
-
std::lock_guard lg(mMutex);
if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
if (engineArchitecture.resolutionPreference ==
@@ -134,10 +131,12 @@
RetCode DynamicsProcessingContext::setPreEqBand(
const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
std::lock_guard lg(mMutex);
- RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
- "postEqNotInUse");
- return setBands_l<DynamicsProcessing::EqBandConfig>(
- bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
+ RETURN_VALUE_IF(!mEngineArchitecture.preEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+ "preEqNotInUse");
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.preEqStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::PREEQ);
}
RetCode DynamicsProcessingContext::setPostEqBand(
@@ -145,8 +144,10 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"postEqNotInUse");
- return setBands_l<DynamicsProcessing::EqBandConfig>(
- bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.postEqStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::EqBandConfig>(bands, StageType::POSTEQ);
}
RetCode DynamicsProcessingContext::setMbcBand(
@@ -154,8 +155,10 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"mbcNotInUse");
- return setBands_l<DynamicsProcessing::MbcBandConfig>(
- bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
+ RETURN_VALUE_IF(
+ !validateBandConfig(bands, mChannelCount, mEngineArchitecture.mbcStage.bandCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+ return setBands_l<DynamicsProcessing::MbcBandConfig>(bands, StageType::MBC);
}
RetCode DynamicsProcessingContext::setLimiter(
@@ -163,13 +166,17 @@
std::lock_guard lg(mMutex);
RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
"limiterNotInUse");
- return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
+ RETURN_VALUE_IF(!validateLimiterConfig(limiters, mChannelCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "limiterConfigNotValid");
+ return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, StageType::LIMITER);
}
RetCode DynamicsProcessingContext::setInputGain(
const std::vector<DynamicsProcessing::InputGain>& inputGains) {
std::lock_guard lg(mMutex);
- return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
+ RETURN_VALUE_IF(!validateInputGainConfig(inputGains, mChannelCount),
+ RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
+ return setBands_l<DynamicsProcessing::InputGain>(inputGains, StageType::INPUTGAIN);
}
DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
@@ -406,45 +413,33 @@
return eqBands;
}
-/**
- * When StageEnablement is in use, bandCount needs to be positive.
- */
-bool DynamicsProcessingContext::validateStageEnablement(
- const DynamicsProcessing::StageEnablement& enablement) {
- return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
-}
-
-bool DynamicsProcessingContext::validateEngineConfig(
- const DynamicsProcessing::EngineArchitecture& engine) {
- return engine.preferredProcessingDurationMs >= 0 &&
- validateStageEnablement(engine.preEqStage) &&
- validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
-}
-
-bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
- int maxChannel, int maxBand) {
- return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
-}
-
-bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
- int maxChannel, int maxBand) {
- return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
- validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
- validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
- validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
- validateRatio(band.expanderRatio);
+template <typename T>
+bool DynamicsProcessingContext::validateBandConfig(const std::vector<T>& bands, int maxChannel,
+ int maxBand) {
+ std::vector<float> freqs(bands.size(), -1);
+ for (auto band : bands) {
+ if (!validateChannel(band.channel, maxChannel)) return false;
+ if (!validateBand(band.band, maxBand)) return false;
+ freqs[band.band] = band.cutoffFrequencyHz;
+ }
+ if (std::count(freqs.begin(), freqs.end(), -1)) return false;
+ return std::is_sorted(freqs.begin(), freqs.end());
}
bool DynamicsProcessingContext::validateLimiterConfig(
- const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
- return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
- validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
- validateBandDb(limiter.thresholdDb);
+ const std::vector<DynamicsProcessing::LimiterConfig>& cfgs, int maxChannel) {
+ for (auto cfg : cfgs) {
+ if (!validateChannel(cfg.channel, maxChannel)) return false;
+ }
+ return true;
}
-bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
- int maxChannel) {
- return validateChannel(gain.channel, maxChannel);
+bool DynamicsProcessingContext::validateInputGainConfig(
+ const std::vector<DynamicsProcessing::InputGain>& cfgs, int maxChannel) {
+ for (auto cfg : cfgs) {
+ if (!validateChannel(cfg.channel, maxChannel)) return false;
+ }
+ return true;
}
template <typename D>
@@ -483,7 +478,6 @@
}
RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
- int maxCh, int maxBand,
std::set<std::pair<int, int>>& chBandSet) {
RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
RetCode ret = RetCode::SUCCESS;
@@ -494,8 +488,6 @@
case StageType::POSTEQ: {
dp_fx::DPEq* dp;
const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
- RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
- RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
RETURN_VALUE_IF(
nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
@@ -508,8 +500,6 @@
case StageType::MBC: {
dp_fx::DPMbc* dp;
const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
- RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
- RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
dp_fx::DPMbcBand band;
@@ -524,8 +514,6 @@
case StageType::LIMITER: {
dp_fx::DPChannel* dp;
const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
- RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
- RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
dp_fx::DPLimiter limiter;
@@ -539,8 +527,6 @@
case StageType::INPUTGAIN: {
dp_fx::DPChannel* dp;
const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
- RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
- RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
dp->setInputGain(config.gainDb);
@@ -555,14 +541,12 @@
}
template <typename T /* BandConfig */>
-RetCode DynamicsProcessingContext::setBands_l(
- const std::vector<T>& bands, int maxBand, StageType type) {
+RetCode DynamicsProcessingContext::setBands_l(const std::vector<T>& bands, StageType type) {
RetCode ret = RetCode::SUCCESS;
std::set<std::pair<int /* channel */, int /* band */>> bandSet;
for (const auto& it : bands) {
- if (RetCode::SUCCESS !=
- setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
+ if (RetCode::SUCCESS != setDpChannelBand_l(std::make_any<T>(it), type, bandSet)) {
LOG(WARNING) << __func__ << " skipping band " << it.toString();
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
continue;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
index 8be784e..b8539f6 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -103,28 +103,22 @@
RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
bool stageInUse, StageType type) REQUIRES(mMutex);
template <typename T /* BandConfig */>
- RetCode setBands_l(const std::vector<T>& bands, int maxBand, StageType type) REQUIRES(mMutex);
- RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type, int maxCh, int maxBand,
+ RetCode setBands_l(const std::vector<T>& bands, StageType type) REQUIRES(mMutex);
+ RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type,
std::set<std::pair<int, int>>& chBandSet) REQUIRES(mMutex);
std::vector<DynamicsProcessing::EqBandConfig> getEqBandConfigs(StageType type);
std::vector<DynamicsProcessing::ChannelConfig> getChannelConfig(StageType type);
- bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
- bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
- bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
- int maxBand);
- bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
- int maxBand);
- bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
- bool validateInputGainConfig(const DynamicsProcessing::InputGain& gain, int maxChannel);
+ template <typename T /* BandConfig */>
+ bool validateBandConfig(const std::vector<T>& bands, int maxChannel, int maxBand);
+ bool validateLimiterConfig(const std::vector<DynamicsProcessing::LimiterConfig>& cfgs,
+ int maxChannel);
+ bool validateInputGainConfig(const std::vector<DynamicsProcessing::InputGain>& cfgs,
+ int maxChannel);
- inline bool validateCutoffFrequency(float freq);
inline bool validateChannel(int ch, int maxCh) { return ch >= 0 && ch < maxCh; }
inline bool validateBand(int band, int maxBand) { return band >= 0 && band < maxBand; }
- inline bool validateTime(int time) { return time >= 0; }
- inline bool validateRatio(int ratio) { return ratio >= 0; }
- inline bool validateBandDb(int db) { return db <= 0; }
};
} // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/media/libheadtracking/PosePredictor.cpp b/media/libheadtracking/PosePredictor.cpp
index f67a966..5209d54 100644
--- a/media/libheadtracking/PosePredictor.cpp
+++ b/media/libheadtracking/PosePredictor.cpp
@@ -91,20 +91,23 @@
// Formatting
static inline std::vector<size_t> createDelimiterIdx(size_t predictors, size_t lookaheads) {
- if (predictors == 0) return {};
- --predictors;
- std::vector<size_t> delimiterIdx(predictors);
- for (size_t i = 0; i < predictors; ++i) {
- delimiterIdx[i] = (i + 1) * lookaheads;
+ if (lookaheads == 0) return {};
+ --lookaheads;
+ std::vector<size_t> delimiterIdx(lookaheads);
+ for (size_t i = 0; i < lookaheads; ++i) {
+ delimiterIdx[i] = (i + 1) * predictors;
}
return delimiterIdx;
}
PosePredictor::PosePredictor()
- : mPredictors{ // must match switch in getCurrentPredictor()
+ : mPredictors{
+ // First predictors must match switch in getCurrentPredictor()
std::make_shared<LastPredictor>(),
std::make_shared<TwistPredictor>(),
std::make_shared<LeastSquaresPredictor>(),
+ // After this, can place additional predictors here for comparison such as
+ // std::make_shared<LeastSquaresPredictor>(0.25),
}
, mLookaheadMs(kLookAheadMs.begin(), kLookAheadMs.end())
, mVerifiers(std::size(mLookaheadMs) * std::size(mPredictors))
@@ -195,7 +198,12 @@
if constexpr (kEnableVerification) {
// dump verification
ss.append(prefixSpace)
- .append(" Prediction abs error (L1) degrees [ type (last twist least-squares) x ( ");
+ .append(" Prediction abs error (L1) degrees [ type (");
+ for (size_t i = 0; i < mPredictors.size(); ++i) {
+ if (i > 0) ss.append(" , ");
+ ss.append(mPredictors[i]->name());
+ }
+ ss.append(" ) x ( ");
for (size_t i = 0; i < mLookaheadMs.size(); ++i) {
if (i > 0) ss.append(" : ");
ss.append(std::to_string(mLookaheadMs[i]));
diff --git a/media/libheadtracking/PosePredictor.h b/media/libheadtracking/PosePredictor.h
index 06983cc..53211e3 100644
--- a/media/libheadtracking/PosePredictor.h
+++ b/media/libheadtracking/PosePredictor.h
@@ -32,6 +32,7 @@
virtual void add(int64_t atNs, const Pose3f& pose, const Twist3f& twist) = 0;
virtual Pose3f predict(int64_t atNs) const = 0;
virtual void reset() = 0;
+ virtual std::string name() const = 0;
virtual std::string toString(size_t index) const = 0;
};
@@ -57,6 +58,10 @@
mLastPose = {};
}
+ std::string name() const override {
+ return "LAST";
+ }
+
std::string toString(size_t index) const override {
std::string s(index, ' ');
s.append("LastPredictor using last pose: ")
@@ -92,6 +97,10 @@
mLastTwist = {};
}
+ std::string name() const override {
+ return "TWIST";
+ }
+
std::string toString(size_t index) const override {
std::string s(index, ' ');
s.append("TwistPredictor using last pose: ")
@@ -130,13 +139,16 @@
void add(int64_t atNs, const Pose3f& pose, const Twist3f& twist) override;
Pose3f predict(int64_t atNs) const override;
void reset() override;
+ std::string name() const override {
+ return "LEAST_SQUARES(" + std::to_string(mAlpha) + ")";
+ }
std::string toString(size_t index) const override;
private:
const double mAlpha;
int64_t mLastAtNs{};
Pose3f mLastPose;
- static constexpr double kDefaultAlphaEstimator = 0.5;
+ static constexpr double kDefaultAlphaEstimator = 0.2;
static constexpr size_t kMinimumSamplesForPrediction = 4;
audio_utils::LinearLeastSquaresFit<double> mRw;
audio_utils::LinearLeastSquaresFit<double> mRx;
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 1b8656d..2bdcdd2 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -26,7 +26,6 @@
#include <binder/IMemory.h>
#include <binder/MemoryDealer.h>
#include <drm/drm_framework_common.h>
-#include <log/log.h>
#include <media/mediametadataretriever.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/foundation/ADebug.h>
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index 8a3b84e..86427ed 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -27,40 +27,6 @@
#include <utils/String8.h>
#include <utils/KeyedVector.h>
-// The binder is supposed to propagate the scheduler group across
-// the binder interface so that remote calls are executed with
-// the same priority as local calls. This is currently not working
-// so this change puts in a temporary hack to fix the issue with
-// metadata retrieval which can be a huge CPU hit if done on a
-// foreground thread.
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
-
-#undef LOG_TAG
-#define LOG_TAG "IMediaMetadataRetriever"
-#include <utils/Log.h>
-#include <cutils/sched_policy.h>
-
-namespace android {
-
-static void sendSchedPolicy(Parcel& data)
-{
- SchedPolicy policy;
- get_sched_policy(gettid(), &policy);
- data.writeInt32(policy);
-}
-
-static void setSchedPolicy(const Parcel& data)
-{
- SchedPolicy policy = (SchedPolicy) data.readInt32();
- set_sched_policy(gettid(), policy);
-}
-static void restoreSchedPolicy()
-{
- set_sched_policy(gettid(), SP_FOREGROUND);
-}
-}; // end namespace android
-#endif
-
namespace android {
enum {
@@ -157,9 +123,6 @@
data.writeInt32(option);
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_FRAME_AT_TIME, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -178,9 +141,6 @@
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
data.writeInt32(thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_IMAGE_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -202,9 +162,6 @@
data.writeInt32(top);
data.writeInt32(right);
data.writeInt32(bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_IMAGE_RECT_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -223,9 +180,6 @@
data.writeInt32(index);
data.writeInt32(colorFormat);
data.writeInt32(metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -238,9 +192,6 @@
{
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
status_t ret = reply.readInt32();
if (ret != NO_ERROR) {
@@ -253,9 +204,6 @@
{
Parcel data, reply;
data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- sendSchedPolicy(data);
-#endif
data.writeInt32(keyCode);
remote()->transact(EXTRACT_METADATA, data, &reply);
status_t ret = reply.readInt32();
@@ -366,9 +314,6 @@
bool metaOnly = (data.readInt32() != 0);
ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
timeUs, option, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
if (bitmap != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -376,9 +321,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case GET_IMAGE_AT_INDEX: {
@@ -389,9 +331,6 @@
bool thumbnail = (data.readInt32() != 0);
ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
index, colorFormat, metaOnly, thumbnail);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
if (bitmap != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -399,9 +338,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
@@ -415,9 +351,6 @@
int bottom = data.readInt32();
ALOGV("getImageRectAtIndex: index(%d), colorFormat(%d), rect {%d, %d, %d, %d}",
index, colorFormat, left, top, right, bottom);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> bitmap = getImageRectAtIndex(
index, colorFormat, left, top, right, bottom);
if (bitmap != 0) { // Don't send NULL across the binder interface
@@ -426,9 +359,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
@@ -439,9 +369,6 @@
bool metaOnly = (data.readInt32() != 0);
ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
index, colorFormat, metaOnly);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
if (frame != nullptr) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -449,16 +376,10 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case EXTRACT_ALBUM_ART: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
sp<IMemory> albumArt = extractAlbumArt();
if (albumArt != 0) { // Don't send NULL across the binder interface
reply->writeInt32(NO_ERROR);
@@ -466,16 +387,10 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
case EXTRACT_METADATA: {
CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- setSchedPolicy(data);
-#endif
int keyCode = data.readInt32();
const char* value = extractMetadata(keyCode);
if (value != NULL) { // Don't send NULL across the binder interface
@@ -484,9 +399,6 @@
} else {
reply->writeInt32(UNKNOWN_ERROR);
}
-#ifndef DISABLE_GROUP_SCHEDULE_HACK
- restoreSchedPolicy();
-#endif
return NO_ERROR;
} break;
default:
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index a36f1d6..91216cb 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -46,6 +46,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmediaplayerservice",
+ vector: "remote",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 32e40c3..fc49d69 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -238,6 +238,7 @@
"CallbackMediaSource.cpp",
"CameraSource.cpp",
"CameraSourceTimeLapse.cpp",
+ "CodecErrorLog.cpp",
"FrameDecoder.cpp",
"HevcUtils.cpp",
"InterfaceUtils.cpp",
diff --git a/media/libstagefright/CodecErrorLog.cpp b/media/libstagefright/CodecErrorLog.cpp
new file mode 100644
index 0000000..9785623
--- /dev/null
+++ b/media/libstagefright/CodecErrorLog.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecErrorLog"
+
+#include <log/log.h>
+#include <media/stagefright/CodecErrorLog.h>
+
+namespace android {
+
+void CodecErrorLog::log(const char *tag, const char *message) {
+ std::unique_lock lock(mLock);
+ ALOG(LOG_ERROR, tag, "%s", message);
+ mStream << message << std::endl;
+}
+
+void CodecErrorLog::log(const char *tag, const std::string &message) {
+ log(tag, message.c_str());
+}
+
+std::string CodecErrorLog::extract() {
+ std::unique_lock lock(mLock);
+ std::string msg = mStream.str();
+ mStream.str("");
+ return msg;
+}
+
+void CodecErrorLog::clear() {
+ std::unique_lock lock(mLock);
+ mStream.str("");
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 9b8cc5e..4a67876 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -41,6 +41,7 @@
#include <android/binder_ibinder.h>
#include <android/binder_manager.h>
#include <android/dlext.h>
+#include <android-base/stringprintf.h>
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryDealer.h>
@@ -874,10 +875,12 @@
};
}
if (!mGetCodecInfo) {
- mGetCodecInfo = [](const AString &name, sp<MediaCodecInfo> *info) -> status_t {
+ mGetCodecInfo = [&log = mErrorLog](const AString &name,
+ sp<MediaCodecInfo> *info) -> status_t {
*info = nullptr;
const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
if (!mcl) {
+ log.log(LOG_TAG, "Fatal error: failed to initialize MediaCodecList");
return NO_INIT; // if called from Java should raise IOException
}
AString tmp = name;
@@ -892,6 +895,8 @@
*info = mcl->getCodecInfo(codecIdx);
return OK;
}
+ log.log(LOG_TAG, base::StringPrintf("Codec with name '%s' is not found on the device.",
+ name.c_str()));
return NAME_NOT_FOUND;
};
}
@@ -947,6 +952,7 @@
void MediaCodec::updateMediametrics() {
if (mMetricsHandle == 0) {
+ ALOGW("no metrics handle found");
return;
}
@@ -1625,6 +1631,8 @@
status_t MediaCodec::init(const AString &name) {
status_t err = mResourceManagerProxy->init();
if (err != OK) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: failed to initialize ResourceManager (err=%d)", err));
mCodec = NULL; // remove the codec
return err;
}
@@ -1644,11 +1652,14 @@
if (!name.startsWith("android.filter.")) {
err = mGetCodecInfo(name, &mCodecInfo);
if (err != OK) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec info with name '%s' failed (err=%d)", name.c_str(), err));
mCodec = NULL; // remove the codec.
return err;
}
if (mCodecInfo == nullptr) {
- ALOGE("Getting codec info with name '%s' failed", name.c_str());
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec info with name '%s' failed", name.c_str()));
return NAME_NOT_FOUND;
}
secureCodec = name.endsWith(".secure");
@@ -1671,7 +1682,8 @@
mCodec = mGetCodecBase(name, owner);
if (mCodec == NULL) {
- ALOGE("Getting codec base with name '%s' (owner='%s') failed", name.c_str(), owner);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Getting codec base with name '%s' (from '%s' HAL) failed", name.c_str(), owner));
return NAME_NOT_FOUND;
}
@@ -1683,7 +1695,7 @@
mCodecLooper->setName("CodecLooper");
err = mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
if (OK != err) {
- ALOGE("Codec Looper failed to start");
+ mErrorLog.log(LOG_TAG, "Fatal error: codec looper failed to start");
return err;
}
}
@@ -1860,7 +1872,8 @@
// Prevent possible integer overflow in downstream code.
if (mWidth < 0 || mHeight < 0 ||
(uint64_t)mWidth * mHeight > (uint64_t)INT32_MAX / 4) {
- ALOGE("Invalid size(s), width=%d, height=%d", mWidth, mHeight);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid size(s), width=%d, height=%d", mWidth, mHeight));
return BAD_VALUE;
}
@@ -3030,17 +3043,17 @@
sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
// use mutex instead of a context switch
if (mReleasedByResourceManager) {
- ALOGE("getBufferAndFormat - resource already released");
+ mErrorLog.log(LOG_TAG, "resource already released");
return DEAD_OBJECT;
}
if (buffer == NULL) {
- ALOGE("getBufferAndFormat - null MediaCodecBuffer");
+ mErrorLog.log(LOG_TAG, "null buffer");
return INVALID_OPERATION;
}
if (format == NULL) {
- ALOGE("getBufferAndFormat - null AMessage");
+ mErrorLog.log(LOG_TAG, "null format");
return INVALID_OPERATION;
}
@@ -3048,7 +3061,9 @@
format->clear();
if (!isExecuting()) {
- ALOGE("getBufferAndFormat - not executing");
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in Executing states",
+ apiStateString().c_str()));
return INVALID_OPERATION;
}
@@ -3060,6 +3075,7 @@
if (index >= buffers.size()) {
ALOGE("getBufferAndFormat - trying to get buffer with "
"bad index (index=%zu buffer_size=%zu)", index, buffers.size());
+ mErrorLog.log(LOG_TAG, base::StringPrintf("Bad index (index=%zu)", index));
return INVALID_OPERATION;
}
@@ -3067,6 +3083,7 @@
if (!info.mOwnedByClient) {
ALOGE("getBufferAndFormat - invalid operation "
"(the index %zu is not owned by client)", index);
+ mErrorLog.log(LOG_TAG, base::StringPrintf("index %zu is not owned by client", index));
return INVALID_OPERATION;
}
@@ -3194,6 +3211,7 @@
void MediaCodec::cancelPendingDequeueOperations() {
if (mFlags & kFlagDequeueInputPending) {
+ mErrorLog.log(LOG_TAG, "Pending dequeue input buffer request cancelled");
PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
++mDequeueInputTimeoutGeneration;
@@ -3202,6 +3220,7 @@
}
if (mFlags & kFlagDequeueOutputPending) {
+ mErrorLog.log(LOG_TAG, "Pending dequeue output buffer request cancelled");
PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
++mDequeueOutputTimeoutGeneration;
@@ -3211,8 +3230,16 @@
}
bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
- if (!isExecuting() || (mFlags & kFlagIsAsync)
- || (newRequest && (mFlags & kFlagDequeueInputPending))) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in executing state",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (newRequest && (mFlags & kFlagDequeueInputPending)) {
+ mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue input request is pending");
PostReplyWithError(replyID, INVALID_OPERATION);
return true;
} else if (mFlags & kFlagStickyError) {
@@ -3235,8 +3262,16 @@
}
bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
- if (!isExecuting() || (mFlags & kFlagIsAsync)
- || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid in executing state",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "Invalid to call in async mode");
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ } else if (newRequest && (mFlags & kFlagDequeueOutputPending)) {
+ mErrorLog.log(LOG_TAG, "Invalid to call while another dequeue output request is pending");
PostReplyWithError(replyID, INVALID_OPERATION);
} else if (mFlags & kFlagStickyError) {
PostReplyWithError(replyID, getStickyError());
@@ -4027,6 +4062,9 @@
// callback can't be set after codec is executing,
// or before it's initialized (as the callback
// will be cleared when it goes to INITIALIZED)
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Invalid to call %s; only valid at Initialized state",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4058,6 +4096,9 @@
case kWhatConfigure:
{
if (mState != INITIALIZED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "configure() is valid only at Initialized state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4115,6 +4156,8 @@
CHECK(msg->findInt32("flags", (int32_t *)&flags));
if (flags & CONFIGURE_FLAG_USE_BLOCK_MODEL) {
if (!(mFlags & kFlagIsAsync)) {
+ mErrorLog.log(
+ LOG_TAG, "Block model is only valid with callback set (async mode)");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4187,9 +4230,13 @@
sp<Surface> surface = static_cast<Surface *>(obj.get());
if (mSurface == NULL) {
// do not support setting surface if it was not set
+ mErrorLog.log(LOG_TAG,
+ "Cannot set surface if the codec is not configured with "
+ "a surface already");
err = INVALID_OPERATION;
} else if (obj == NULL) {
// do not support unsetting surface
+ mErrorLog.log(LOG_TAG, "Unsetting surface is not supported");
err = BAD_VALUE;
} else {
err = connectToSurface(surface);
@@ -4220,6 +4267,9 @@
}
default:
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "setSurface() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
err = INVALID_OPERATION;
break;
}
@@ -4233,6 +4283,9 @@
{
// Must be configured, but can't have been started yet.
if (mState != CONFIGURED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "setInputSurface() is valid only at Configured state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4268,6 +4321,9 @@
PostReplyWithError(msg, OK);
break;
} else if (mState != CONFIGURED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "start() is valid only at Configured state; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
}
@@ -4345,6 +4401,7 @@
if (mFlags & kFlagIsAsync) {
onError(DEAD_OBJECT, ACTION_CODE_FATAL);
}
+ mErrorLog.log(LOG_TAG, "Released by resource manager");
mReleasedByResourceManager = true;
}
@@ -4381,6 +4438,7 @@
// the previous stop/release completes and then reply with OK.
status_t err = mState == targetState ? OK : INVALID_OPERATION;
response->setInt32("err", err);
+ // TODO: mErrorLog
if (err == OK && targetState == UNINITIALIZED) {
mComponentName.clear();
}
@@ -4489,13 +4547,13 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mFlags & kFlagIsAsync) {
- ALOGE("dequeueInputBuffer can't be used in async mode");
+ mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used in async mode");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
if (mHaveInputSurface) {
- ALOGE("dequeueInputBuffer can't be used with input surface");
+ mErrorLog.log(LOG_TAG, "dequeueInputBuffer can't be used with input surface");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4550,6 +4608,9 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "queueInputBuffer() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4577,7 +4638,7 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mFlags & kFlagIsAsync) {
- ALOGE("dequeueOutputBuffer can't be used in async mode");
+ mErrorLog.log(LOG_TAG, "dequeueOutputBuffer can't be used in async mode");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4632,6 +4693,9 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "releaseOutputBuffer() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4655,7 +4719,15 @@
case kWhatSignalEndOfInputStream:
{
- if (!isExecuting() || !mHaveInputSurface) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "signalEndOfInputStream() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(msg, INVALID_OPERATION);
+ break;
+ } else if (!mHaveInputSurface) {
+ mErrorLog.log(
+ LOG_TAG, "signalEndOfInputStream() called without an input surface set");
PostReplyWithError(msg, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4679,7 +4751,14 @@
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if (!isExecuting() || (mFlags & kFlagIsAsync)) {
+ if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "getInput/OutputBuffers() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ break;
+ } else if (mFlags & kFlagIsAsync) {
+ mErrorLog.log(LOG_TAG, "getInput/OutputBuffers() is not supported with callbacks");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4712,6 +4791,9 @@
case kWhatFlush:
{
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "flush() is valid only at Executing states; currently %s",
+ apiStateString().c_str()));
PostReplyWithError(msg, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4751,10 +4833,17 @@
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if ((mState != CONFIGURED && mState != STARTING &&
- mState != STARTED && mState != FLUSHING &&
- mState != FLUSHED)
- || format == NULL) {
+ if (mState != CONFIGURED && mState != STARTING &&
+ mState != STARTED && mState != FLUSHING &&
+ mState != FLUSHED) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "getInput/OutputFormat() is valid at Executing states "
+ "and Configured state; currently %s",
+ apiStateString().c_str()));
+ PostReplyWithError(replyID, INVALID_OPERATION);
+ break;
+ } else if (format == NULL) {
+ mErrorLog.log(LOG_TAG, "Fatal error: format is not initialized");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
} else if (mFlags & kFlagStickyError) {
@@ -4789,6 +4878,7 @@
CHECK(msg->senderAwaitsResponse(&replyID));
if (mComponentName.empty()) {
+ mErrorLog.log(LOG_TAG, "Fatal error: name is not set");
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
@@ -4956,7 +5046,7 @@
size_t i = 0;
for (;;) {
sp<ABuffer> csd;
- if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
+ if (!format->findBuffer(base::StringPrintf("csd-%zu", i).c_str(), &csd)) {
break;
}
if (csd->size() == 0) {
@@ -4991,7 +5081,7 @@
}
sDealer = new MemoryDealer(
newDealerCapacity,
- AStringPrintf("CSD(%dMB)", newDealerCapacity / 1048576).c_str());
+ base::StringPrintf("CSD(%zuMB)", newDealerCapacity / 1048576).c_str());
mem = sDealer->allocate(csd->size());
}
memcpy(mem->unsecurePointer(), csd->data(), csd->size());
@@ -5002,9 +5092,14 @@
FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
C2WriteView view{block->map().get()};
if (view.error() != C2_OK) {
+ mErrorLog.log(LOG_TAG, "Fatal error: failed to allocate and map a block");
return -EINVAL;
}
if (csd->size() > view.capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: allocated block is too small "
+ "(csd size %zu; block cap %u)",
+ csd->size(), view.capacity()));
return -EINVAL;
}
memcpy(view.base(), csd->data(), csd->size());
@@ -5015,10 +5110,16 @@
const sp<MediaCodecBuffer> &codecInputData = info.mData;
if (csd->size() > codecInputData->capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "CSD is too large to fit in input buffer "
+ "(csd size %zu; buffer cap %zu)",
+ csd->size(), codecInputData->capacity()));
return -EINVAL;
}
if (codecInputData->data() == NULL) {
ALOGV("Input buffer %zu is not properly allocated", bufferIndex);
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: input buffer %zu is not properly allocated", bufferIndex));
return -EINVAL;
}
@@ -5071,6 +5172,7 @@
mActivityNotify.clear();
mCallback.clear();
+ mErrorLog.clear();
}
if (newState == UNINITIALIZED) {
@@ -5191,6 +5293,7 @@
if (!hasCryptoOrDescrambler()) {
ALOGE("[%s] queuing secure buffer without mCrypto or mDescrambler!",
mComponentName.c_str());
+ mErrorLog.log(LOG_TAG, "queuing secure buffer without mCrypto or mDescrambler!");
return -EINVAL;
}
@@ -5214,6 +5317,8 @@
}
if (index >= mPortBuffers[kPortIndexInput].size()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "index out of range (index=%zu)", mPortBuffers[kPortIndexInput].size()));
return -ERANGE;
}
@@ -5234,6 +5339,7 @@
memory, (mFlags & kFlagIsSecure), key, iv, mode, pattern,
offset, subSamples, numSubSamples, buffer);
} else {
+ mErrorLog.log(LOG_TAG, "Fatal error: invalid queue request without a buffer");
err = UNKNOWN_ERROR;
}
@@ -5256,17 +5362,28 @@
offset = buffer->offset();
size = buffer->size();
if (err != OK) {
- ALOGI("block model buffer attach failed: err = %s (%d)",
+ ALOGE("block model buffer attach failed: err = %s (%d)",
StrMediaError(err).c_str(), err);
return err;
}
}
- if (buffer == nullptr || !info->mOwnedByClient) {
+ if (buffer == nullptr) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: failed to fetch buffer for index %zu", index));
+ return -EACCES;
+ }
+ if (!info->mOwnedByClient) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "client does not own the buffer #%zu", index));
return -EACCES;
}
if (offset + size > buffer->capacity()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "buffer offset and size goes beyond the capacity: "
+ "offset=%zu, size=%zu, cap=%zu",
+ offset, size, buffer->capacity()));
return -EINVAL;
}
@@ -5371,8 +5488,8 @@
if (it->getRenderTimeNs() < 0) {
continue; // dropped frame from tracking
}
- msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
- msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
+ msg->setInt64(base::StringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
+ msg->setInt64(base::StringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
++index;
}
return index;
@@ -5388,16 +5505,28 @@
}
if (!isExecuting()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "releaseOutputBuffer() is valid at Executing states; currently %s",
+ apiStateString().c_str()));
return -EINVAL;
}
if (index >= mPortBuffers[kPortIndexOutput].size()) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "index out of range (index=%zu)", mPortBuffers[kPortIndexOutput].size()));
return -ERANGE;
}
BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
- if (info->mData == nullptr || !info->mOwnedByClient) {
+ if (!info->mOwnedByClient) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "client does not own the buffer #%zu", index));
+ return -EACCES;
+ }
+ if (info->mData == nullptr) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "Fatal error: null buffer for index %zu", index));
return -EACCES;
}
@@ -5464,7 +5593,7 @@
status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
if (err == NO_INIT) {
- ALOGE("rendering to non-initilized(obsolete) surface");
+ mErrorLog.log(LOG_TAG, "rendering to non-initialized(obsolete) surface");
return err;
}
if (err != OK) {
@@ -5737,12 +5866,14 @@
memcpy(csd->data() + 4, nalStart, nalSize);
mOutputFormat->setBuffer(
- AStringPrintf("csd-%u", csdIndex).c_str(), csd);
+ base::StringPrintf("csd-%u", csdIndex).c_str(), csd);
++csdIndex;
}
if (csdIndex != 2) {
+ mErrorLog.log(LOG_TAG, base::StringPrintf(
+ "codec config data contains %u NAL units; expected 2.", csdIndex));
return ERROR_MALFORMED;
}
} else {
@@ -5784,6 +5915,32 @@
mDeferredMessages.clear();
}
+std::string MediaCodec::apiStateString() {
+ const char *rval = NULL;
+ char rawbuffer[16]; // room for "%d"
+
+ switch (mState) {
+ case UNINITIALIZED:
+ rval = (mFlags & kFlagStickyError) ? "at Error state" : "at Released state";
+ break;
+ case INITIALIZING: rval = "while constructing"; break;
+ case INITIALIZED: rval = "at Uninitialized state"; break;
+ case CONFIGURING: rval = "during configure()"; break;
+ case CONFIGURED: rval = "at Configured state"; break;
+ case STARTING: rval = "during start()"; break;
+ case STARTED: rval = "at Running state"; break;
+ case FLUSHING: rval = "during flush()"; break;
+ case FLUSHED: rval = "at Flushed state"; break;
+ case STOPPING: rval = "during stop()"; break;
+ case RELEASING: rval = "during release()"; break;
+ default:
+ snprintf(rawbuffer, sizeof(rawbuffer), "at %d", mState);
+ rval = rawbuffer;
+ break;
+ }
+ return rval;
+}
+
std::string MediaCodec::stateString(State state) {
const char *rval = NULL;
char rawbuffer[16]; // room for "%d"
diff --git a/media/libstagefright/httplive/fuzzer/Android.bp b/media/libstagefright/httplive/fuzzer/Android.bp
index 85fd8b7..dd49714 100644
--- a/media/libstagefright/httplive/fuzzer/Android.bp
+++ b/media/libstagefright/httplive/fuzzer/Android.bp
@@ -62,5 +62,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_httplive",
+ vector: "remote",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/libstagefright/include/media/stagefright/CodecErrorLog.h b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
new file mode 100644
index 0000000..673117a
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/CodecErrorLog.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_ERROR_LOG_H_
+
+#define CODEC_ERROR_LOG_H_
+
+#include <sstream>
+#include <string>
+
+#include <android-base/thread_annotations.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+/**
+ * CodecErrorLog gathers what happened during codec failures, and make them
+ * available to clients for debugging purpose.
+ */
+class CodecErrorLog {
+public:
+ CodecErrorLog() = default;
+
+ /**
+ * Log a line of message.
+ *
+ * \note the message should be readable to developers who may not be
+ * familiar with MediaCodec internals
+ */
+ void log(const char *tag, const char *message);
+ void log(const char *tag, const std::string &message);
+
+ /**
+ * Extract the accumulated log as string. This operation clears the log.
+ */
+ std::string extract();
+
+ /**
+ * Clears the previous log.
+ */
+ void clear();
+
+private:
+ mutable std::mutex mLock;
+ std::stringstream mStream GUARDED_BY(mLock);
+};
+
+} // namespace android
+
+#endif // CODEC_ERROR_LOG_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 29b196f..ec2d13b 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -28,6 +28,7 @@
#include <media/MediaMetrics.h>
#include <media/MediaProfiles.h>
#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/CodecErrorLog.h>
#include <media/stagefright/FrameRenderTracker.h>
#include <utils/Vector.h>
@@ -297,6 +298,8 @@
T value;
};
+ inline CodecErrorLog &getErrorLog() { return mErrorLog; }
+
protected:
virtual ~MediaCodec();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -321,6 +324,7 @@
RELEASING,
};
std::string stateString(State state);
+ std::string apiStateString();
enum {
kPortIndexInput = 0,
@@ -692,6 +696,8 @@
std::function<status_t(const AString &, sp<MediaCodecInfo> *)> mGetCodecInfo;
friend class MediaTestHelper;
+ CodecErrorLog mErrorLog;
+
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
diff --git a/media/libstagefright/tests/HEVC/Android.bp b/media/libstagefright/tests/HEVC/Android.bp
index 7f2ff12..7a0ba52 100644
--- a/media/libstagefright/tests/HEVC/Android.bp
+++ b/media/libstagefright/tests/HEVC/Android.bp
@@ -56,7 +56,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/tests/extractorFactory/Android.bp b/media/libstagefright/tests/extractorFactory/Android.bp
index 20ebe44..a067284 100644
--- a/media/libstagefright/tests/extractorFactory/Android.bp
+++ b/media/libstagefright/tests/extractorFactory/Android.bp
@@ -66,7 +66,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/timedtext/test/Android.bp b/media/libstagefright/timedtext/test/Android.bp
index 953da79..ae97c50 100644
--- a/media/libstagefright/timedtext/test/Android.bp
+++ b/media/libstagefright/timedtext/test/Android.bp
@@ -62,7 +62,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index b81f27e..58aa7cd 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -57,6 +57,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of all the various writers",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrnb/dec/test/Android.bp b/media/module/codecs/amrnb/dec/test/Android.bp
index de69cfc..74258e0 100644
--- a/media/module/codecs/amrnb/dec/test/Android.bp
+++ b/media/module/codecs/amrnb/dec/test/Android.bp
@@ -58,7 +58,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrnb/enc/fuzzer/Android.bp b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
index 2c041b7..bcbcee2 100644
--- a/media/module/codecs/amrnb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrnbenc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrnb/enc/test/Android.bp b/media/module/codecs/amrnb/enc/test/Android.bp
index 5871486..7e393e3 100644
--- a/media/module/codecs/amrnb/enc/test/Android.bp
+++ b/media/module/codecs/amrnb/enc/test/Android.bp
@@ -58,7 +58,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrnb/fuzzer/Android.bp b/media/module/codecs/amrnb/fuzzer/Android.bp
index 833a7ba..3f29267 100644
--- a/media/module/codecs/amrnb/fuzzer/Android.bp
+++ b/media/module/codecs/amrnb/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrnbdec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/dec/fuzzer/Android.bp b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
index 16f08fa..31a20ff 100644
--- a/media/module/codecs/amrwb/dec/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrwbdec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/dec/test/Android.bp b/media/module/codecs/amrwb/dec/test/Android.bp
index 7ea39ef..7d0c964 100644
--- a/media/module/codecs/amrwb/dec/test/Android.bp
+++ b/media/module/codecs/amrwb/dec/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/amrwb/enc/fuzzer/Android.bp b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
index f74fa4f..c2c13e1 100644
--- a/media/module/codecs/amrwb/enc/fuzzer/Android.bp
+++ b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
@@ -48,5 +48,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_amrwbenc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/amrwb/enc/test/Android.bp b/media/module/codecs/amrwb/enc/test/Android.bp
index f095d62..942f6c9 100644
--- a/media/module/codecs/amrwb/enc/test/Android.bp
+++ b/media/module/codecs/amrwb/enc/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/g711/fuzzer/Android.bp b/media/module/codecs/g711/fuzzer/Android.bp
index 376cce7..397fb9a 100644
--- a/media/module/codecs/g711/fuzzer/Android.bp
+++ b/media/module/codecs/g711/fuzzer/Android.bp
@@ -44,6 +44,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Alaw APIs",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
@@ -61,5 +69,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of codecs_g711dec library with a special focus on Mlaw APIs",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/m4v_h263/dec/test/Android.bp b/media/module/codecs/m4v_h263/dec/test/Android.bp
index 9dc756c..d8de569 100644
--- a/media/module/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/module/codecs/m4v_h263/dec/test/Android.bp
@@ -76,7 +76,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/m4v_h263/enc/test/Android.bp b/media/module/codecs/m4v_h263/enc/test/Android.bp
index d75e2d1..2b5e49c 100644
--- a/media/module/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/module/codecs/m4v_h263/enc/test/Android.bp
@@ -55,7 +55,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true",
- ],
}
diff --git a/media/module/codecs/m4v_h263/fuzzer/Android.bp b/media/module/codecs/m4v_h263/fuzzer/Android.bp
index a052c11..4d0ed18 100644
--- a/media/module/codecs/m4v_h263/fuzzer/Android.bp
+++ b/media/module/codecs/m4v_h263/fuzzer/Android.bp
@@ -50,6 +50,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of libstagefright_m4vh263dec library",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
@@ -98,6 +106,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of libstagefright_m4vh263enc library",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/mp3dec/fuzzer/Android.bp b/media/module/codecs/mp3dec/fuzzer/Android.bp
index 514a8a8..c5e0b1f 100644
--- a/media/module/codecs/mp3dec/fuzzer/Android.bp
+++ b/media/module/codecs/mp3dec/fuzzer/Android.bp
@@ -44,5 +44,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libstagefright_mp3dec",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/codecs/mp3dec/test/Android.bp b/media/module/codecs/mp3dec/test/Android.bp
index dd06bdc..f10b6ae 100644
--- a/media/module/codecs/mp3dec/test/Android.bp
+++ b/media/module/codecs/mp3dec/test/Android.bp
@@ -56,7 +56,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/codecserviceregistrant/fuzzer/Android.bp b/media/module/codecserviceregistrant/fuzzer/Android.bp
index 0b9affd..1cb8c2b 100644
--- a/media/module/codecserviceregistrant/fuzzer/Android.bp
+++ b/media/module/codecserviceregistrant/fuzzer/Android.bp
@@ -41,5 +41,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmedia_codecserviceregistrant",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
index b3e34d2..91ca7b1 100644
--- a/media/module/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -72,6 +72,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers targets the APIs of all the various extractors",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/media/module/extractors/tests/Android.bp b/media/module/extractors/tests/Android.bp
index f5eadbd..d6e79c7 100644
--- a/media/module/extractors/tests/Android.bp
+++ b/media/module/extractors/tests/Android.bp
@@ -100,7 +100,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true",
- ],
}
diff --git a/media/module/foundation/tests/OpusHeader/Android.bp b/media/module/foundation/tests/OpusHeader/Android.bp
index f052650..fa2b40e 100644
--- a/media/module/foundation/tests/OpusHeader/Android.bp
+++ b/media/module/foundation/tests/OpusHeader/Android.bp
@@ -54,7 +54,4 @@
],
cfi: true,
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true",
- ],
}
diff --git a/media/module/id3/test/Android.bp b/media/module/id3/test/Android.bp
index 0481e48..52cdfa5 100644
--- a/media/module/id3/test/Android.bp
+++ b/media/module/id3/test/Android.bp
@@ -57,7 +57,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
index f98b27d..459f0ae 100644
--- a/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -26,25 +26,16 @@
name: "MediaTranscoderBenchmark",
srcs: ["MediaTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
cc_test {
name: "MediaSampleReaderBenchmark",
srcs: ["MediaSampleReaderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
cc_test {
name: "MediaTrackTranscoderBenchmark",
srcs: ["MediaTrackTranscoderBenchmark.cpp"],
defaults: ["benchmarkdefaults"],
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
- ],
}
diff --git a/media/module/mpeg2ts/test/Android.bp b/media/module/mpeg2ts/test/Android.bp
index 4b1bacd..34a8d3e 100644
--- a/media/module/mpeg2ts/test/Android.bp
+++ b/media/module/mpeg2ts/test/Android.bp
@@ -74,7 +74,4 @@
"signed-integer-overflow",
],
},
- data: [
- ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true",
- ],
}
diff --git a/media/utils/include/mediautils/MethodStatistics.h b/media/utils/include/mediautils/MethodStatistics.h
index 6d7e990..c8b36d8 100644
--- a/media/utils/include/mediautils/MethodStatistics.h
+++ b/media/utils/include/mediautils/MethodStatistics.h
@@ -59,7 +59,7 @@
void event(C&& code, FloatType executeMs) {
std::lock_guard lg(mLock);
auto it = mStatisticsMap.lower_bound(code);
- if (it != mStatisticsMap.end() && it->first == code) {
+ if (it != mStatisticsMap.end() && it->first == static_cast<Code>(code)) {
it->second.add(executeMs);
} else {
// StatsType ctor takes an optional array of data for initialization.
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 6d4c3a3..f1797e6 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -19,11 +19,127 @@
],
}
+tidy_errors = [
+ // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+ // For many categories, the checks are too many to specify individually.
+ // Feel free to disable as needed - as warnings are generally ignored,
+ // we treat warnings as errors.
+ "android-*",
+ "bugprone-*",
+ "cert-*",
+ "clang-analyzer-security*",
+ "google-*",
+ "misc-*",
+ //"modernize-*", // explicitly list the modernize as they can be subjective.
+ "modernize-avoid-bind",
+ //"modernize-avoid-c-arrays", // std::array<> can be verbose
+ "modernize-concat-nested-namespaces",
+ //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+ "modernize-deprecated-ios-base-aliases",
+ "modernize-loop-convert",
+ "modernize-make-shared",
+ "modernize-make-unique",
+ // "modernize-pass-by-value",
+ "modernize-raw-string-literal",
+ "modernize-redundant-void-arg",
+ "modernize-replace-auto-ptr",
+ "modernize-replace-random-shuffle",
+ "modernize-return-braced-init-list",
+ "modernize-shrink-to-fit",
+ "modernize-unary-static-assert",
+ // "modernize-use-auto", // found in MediaMetricsService.h, debatable - auto can obscure type
+ "modernize-use-bool-literals",
+ "modernize-use-default-member-init",
+ "modernize-use-emplace",
+ "modernize-use-equals-default",
+ "modernize-use-equals-delete",
+ // "modernize-use-nodiscard",
+ "modernize-use-noexcept",
+ "modernize-use-nullptr",
+ "modernize-use-override",
+ //"modernize-use-trailing-return-type", // not necessarily more readable
+ "modernize-use-transparent-functors",
+ "modernize-use-uncaught-exceptions",
+ "modernize-use-using",
+ "performance-*",
+
+ // Remove some pedantic stylistic requirements.
+ "-google-readability-casting", // C++ casts not always necessary and may be verbose
+ "-google-readability-todo", // do not require TODO(info)
+
+ "-bugprone-unhandled-self-assignment",
+ "-bugprone-suspicious-string-compare",
+ "-cert-oop54-cpp", // found in TransactionLog.h
+ "-bugprone-narrowing-conversions", // b/182410845
+
+ // TODO(b/275642749) Reenable these warnings
+ "-bugprone-assignment-in-if-condition",
+ "-bugprone-forward-declaration-namespace",
+ "-bugprone-parent-virtual-call",
+ "-cert-dcl59-cpp",
+ "-cert-err34-c",
+ "-google-build-namespaces",
+ "-google-build-using-namespace",
+ "-google-default-arguments",
+ "-google-runtime-int",
+ "-misc-const-correctness",
+ "-misc-non-private-member-variables-in-classes",
+ "-modernize-concat-nested-namespaces",
+ "-modernize-loop-convert",
+ "-modernize-use-default-member-init",
+ "-modernize-use-equals-default",
+ "-modernize-use-nullptr",
+ "-modernize-use-override",
+ "-modernize-use-using",
+ "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+ name: "audioflinger_flags_defaults",
+ // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
+ cflags: [
+ "-Wall",
+ "-Wdeprecated",
+ "-Werror",
+ "-Werror=implicit-fallthrough",
+ "-Werror=sometimes-uninitialized",
+ "-Werror=conditional-uninitialized",
+ "-Wextra",
+
+ // suppress some warning chatter.
+ "-Wno-deprecated-copy-with-dtor",
+ "-Wno-deprecated-copy-with-user-provided-dtor",
+
+ "-Wredundant-decls",
+ "-Wshadow",
+ "-Wstrict-aliasing",
+ "-fstrict-aliasing",
+ "-Wthread-safety",
+ //"-Wthread-safety-negative", // experimental - looks broken in R.
+ "-Wunreachable-code",
+ "-Wunreachable-code-break",
+ "-Wunreachable-code-return",
+ "-Wunused",
+ "-Wused-but-marked-unused",
+ "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+ ],
+ // https://clang.llvm.org/extra/clang-tidy/
+ tidy: true,
+ tidy_checks: tidy_errors,
+ tidy_checks_as_errors: tidy_errors,
+ tidy_flags: [
+ "-format-style=file",
+ ],
+}
+
cc_library_shared {
name: "libaudioflinger",
defaults: [
"latest_android_media_audio_common_types_cpp_shared",
+ "audioflinger_flags_defaults",
],
srcs: [
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ba7c6b6..2ef4feb 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -229,6 +229,7 @@
BINDER_METHOD_ENTRY(getAAudioMixerBurstCount) \
BINDER_METHOD_ENTRY(getAAudioHardwareBurstMinUsec) \
BINDER_METHOD_ENTRY(setDeviceConnectedState) \
+BINDER_METHOD_ENTRY(setSimulateDeviceConnections) \
BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
@@ -499,6 +500,25 @@
return final_result;
}
+status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
+ bool at_least_one_succeeded = false;
+ status_t last_error = INVALID_OPERATION;
+ Mutex::Autolock _l(mLock);
+ AutoMutex lock(mHardwareLock);
+ mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
+ for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+ sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
+ status_t result = dev->setSimulateDeviceConnections(enabled);
+ if (result == OK) {
+ at_least_one_succeeded = true;
+ } else {
+ last_error = result;
+ }
+ }
+ mHardwareStatus = AUDIO_HW_IDLE;
+ return at_least_one_succeeded ? OK : last_error;
+}
+
// getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
if (mAudioVibratorInfos.empty()) {
@@ -694,7 +714,7 @@
}
status_t AudioFlinger::addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
@@ -704,7 +724,7 @@
}
status_t AudioFlinger::removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
AutoMutex lock(mHardwareLock);
AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(hwModuleId);
if (audioHwDevice == nullptr) {
@@ -822,6 +842,7 @@
}
status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
if (!dumpAllowed()) {
dumpPermissionDenial(fd, args);
@@ -924,7 +945,6 @@
// to lookup the service if it's not running, as it will block for a second
if (sMediaLogServiceAsBinder != 0) {
dprintf(fd, "\nmedia.log:\n");
- Vector<String16> args;
sMediaLogServiceAsBinder->dump(fd, args);
}
@@ -1421,8 +1441,9 @@
if (NO_ERROR == ret) {
Mutex::Autolock _l(mLock);
mMode = mode;
- for (size_t i = 0; i < mPlaybackThreads.size(); i++)
+ for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
mPlaybackThreads.valueAt(i)->setMode(mode);
+ }
}
mediametrics::LogItem(mMetricsId)
@@ -1760,7 +1781,7 @@
// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
void AudioFlinger::forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- std::function<bool(const sp<PlaybackThread>&)> useThread)
+ const std::function<bool(const sp<PlaybackThread>&)>& useThread)
{
std::vector<PatchPanel::SoftwarePatch> swPatches;
if (mPatchPanel.getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
@@ -1776,7 +1797,7 @@
// Update downstream patches for all playback threads attached to an MSD module
void AudioFlinger::updateDownStreamPatches_l(const struct audio_patch *patch,
- const std::set<audio_io_handle_t> streams)
+ const std::set<audio_io_handle_t>& streams)
{
for (const audio_io_handle_t stream : streams) {
PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
@@ -1982,24 +2003,29 @@
mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+
std::vector<audio_channel_mask_t> channelMasks = {channelMask};
- if (channelMask != AUDIO_CHANNEL_IN_MONO)
+ if (channelMask != AUDIO_CHANNEL_IN_MONO) {
channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
- if (channelMask != AUDIO_CHANNEL_IN_STEREO)
+ }
+ if (channelMask != AUDIO_CHANNEL_IN_STEREO) {
channelMasks.push_back(AUDIO_CHANNEL_IN_STEREO);
+ }
std::vector<audio_format_t> formats = {format};
- if (format != AUDIO_FORMAT_PCM_16_BIT)
+ if (format != AUDIO_FORMAT_PCM_16_BIT) {
formats.push_back(AUDIO_FORMAT_PCM_16_BIT);
+ }
std::vector<uint32_t> sampleRates = {sampleRate};
static const uint32_t SR_44100 = 44100;
static const uint32_t SR_48000 = 48000;
-
- if (sampleRate != SR_48000)
+ if (sampleRate != SR_48000) {
sampleRates.push_back(SR_48000);
- if (sampleRate != SR_44100)
+ }
+ if (sampleRate != SR_44100) {
sampleRates.push_back(SR_44100);
+ }
mHardwareStatus = AUDIO_HW_IDLE;
@@ -2468,7 +2494,7 @@
// session and move it to this thread.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l(thread->mLock);
+ Mutex::Autolock _l2(thread->mLock);
thread->addEffectChain_l(chain);
}
break;
@@ -2848,7 +2874,7 @@
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output,
audio_config_t *halConfig,
- audio_config_base_t *mixerConfig __unused,
+ audio_config_base_t *mixerConfig,
audio_devices_t deviceType,
const String8& address,
audio_output_flags_t flags)
@@ -2970,7 +2996,6 @@
aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
audio_io_handle_t output;
- uint32_t latencyMs;
ALOGI("openOutput() this %p, module %d Device %s, SamplingRate %d, Format %#08x, "
"Channels %#x, flags %#x",
@@ -2993,6 +3018,7 @@
sp<ThreadBase> thread = openOutput_l(module, &output, &halConfig,
&mixerConfig, deviceType, address, flags);
if (thread != 0) {
+ uint32_t latencyMs = 0;
if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
latencyMs = playbackThread->latency();
@@ -3341,7 +3367,7 @@
continue;
}
if (t->hasAudioSession(chain->sessionId()) != 0) {
- Mutex::Autolock _l(t->mLock);
+ Mutex::Autolock _l2(t->mLock);
ALOGV("closeInput() found thread %d for effect session %d",
t->id(), chain->sessionId());
t->addEffectChain_l(chain);
@@ -3546,7 +3572,8 @@
}
for (size_t i = 0; i < chains.size(); i++) {
- sp<EffectChain> ec = chains[i];
+ // clang-tidy suggests const ref
+ sp<EffectChain> ec = chains[i]; // NOLINT(performance-unnecessary-copy-initialization)
int sessionid = ec->sessionId();
sp<ThreadBase> t = ec->thread().promote();
if (t == 0) {
@@ -3715,7 +3742,7 @@
PlaybackThread *thread = primaryPlaybackThread_l();
if (thread == NULL) {
- return DeviceTypeSet();
+ return {};
}
return thread->outDeviceTypes();
@@ -4227,7 +4254,7 @@
// session and used it instead of creating a new one.
sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
if (chain != 0) {
- Mutex::Autolock _l(thread->mLock);
+ Mutex::Autolock _l2(thread->mLock);
thread->addEffectChain_l(chain);
}
}
@@ -4345,6 +4372,7 @@
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread)
+NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
{
ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
sessionId, srcThread, dstThread);
@@ -4374,11 +4402,12 @@
// transfer all effects one by one so that new effect chain is created on new thread with
// correct buffer sizes and audio parameters and effect engines reconfigured accordingly
sp<EffectChain> dstChain;
- sp<EffectModule> effect = chain->getEffectFromId_l(0);
Vector< sp<EffectModule> > removed;
status_t status = NO_ERROR;
std::string errorString;
- while (effect != nullptr) {
+ // process effects one by one.
+ for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+ effect = chain->getEffectFromId_l(0)) {
srcThread->removeEffect_l(effect);
removed.add(effect);
status = dstThread->addEffect_l(effect);
@@ -4399,7 +4428,6 @@
break;
}
}
- effect = chain->getEffectFromId_l(0);
}
size_t restored = 0;
@@ -4503,6 +4531,7 @@
}
bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
+NO_THREAD_SAFETY_ANALYSIS // thread lock for getEffectChain_l.
{
if (mGlobalEffectEnableTime != 0 &&
((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebfe32c..9079be9 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -293,6 +293,8 @@
virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected);
+ virtual status_t setSimulateDeviceConnections(bool enabled);
+
virtual status_t setRequestedLatencyMode(
audio_io_handle_t output, audio_latency_mode_t mode);
@@ -328,12 +330,12 @@
static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
status_t addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect);
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect);
void updateDownStreamPatches_l(const struct audio_patch *patch,
- const std::set<audio_io_handle_t> streams);
+ const std::set<audio_io_handle_t>& streams);
std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
@@ -376,7 +378,7 @@
audio_session_t triggerSession,
audio_session_t listenerSession,
sync_event_callback_t callBack,
- wp<RefBase> cookie)
+ const wp<RefBase>& cookie)
: mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
mCallback(callBack), mCookie(cookie)
{}
@@ -848,7 +850,7 @@
void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
- std::function<bool(const sp<PlaybackThread>&)> useThread = nullptr);
+ const std::function<bool(const sp<PlaybackThread>&)>& useThread = nullptr);
// AudioStreamIn is immutable, so their fields are const.
// For emphasis, we could also make all pointers to them be "const *",
@@ -861,7 +863,8 @@
sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
- AudioStreamIn(AudioHwDevice *dev, sp<StreamInHalInterface> in, audio_input_flags_t flags) :
+ AudioStreamIn(AudioHwDevice *dev, const sp<StreamInHalInterface>& in,
+ audio_input_flags_t flags) :
audioHwDev(dev), stream(in), flags(flags) {}
status_t read(void *buffer, size_t bytes, size_t *read) override {
return stream->read(buffer, bytes, read);
@@ -932,6 +935,7 @@
AUDIO_HW_GET_MASTER_MUTE, // get_master_mute
AUDIO_HW_GET_MICROPHONES, // getMicrophones
AUDIO_HW_SET_CONNECTED_STATE, // setConnectedState
+ AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
};
mutable hardware_call_state mHardwareStatus; // for dump only
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 1749f3f..d071922 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -46,7 +46,7 @@
AudioHwDevice(audio_module_handle_t handle,
const char *moduleName,
- sp<DeviceHalInterface> hwDevice,
+ const sp<DeviceHalInterface>& hwDevice,
Flags flags)
: mHandle(handle)
, mModuleName(strdup(moduleName))
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/AutoPark.h
index 9ac7b65..83f6b7d 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/AutoPark.h
@@ -58,4 +58,4 @@
FastThreadState::Command mPreviousCommand;
}; // class AutoPark
-} // namespace
+} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 3a8c1bc..8484f95 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -160,7 +160,9 @@
return status;
}
-void AudioFlinger::DeviceEffectManager::dump(int fd) {
+void AudioFlinger::DeviceEffectManager::dump(int fd)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
+{
const bool locked = dumpTryLock(mLock);
if (!locked) {
String8 result("DeviceEffectManager may be deadlocked\n");
@@ -264,7 +266,7 @@
return false;
}
-void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(sp<Command> command) {
+void AudioFlinger::DeviceEffectManager::CommandThread::sendCommand(const sp<Command>& command) {
Mutex::Autolock _l(mLock);
mCommands.push_back(command);
mWaitWorkCV.signal();
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index d2faa70..493800e 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -47,11 +47,11 @@
int32_t sessionId, int32_t deviceId,
sp<EffectHalInterface> *effect);
status_t addEffectToHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
return mAudioFlinger.addEffectToHal(deviceId, hwModuleId, effect);
};
status_t removeEffectFromHal(audio_port_handle_t deviceId, audio_module_handle_t hwModuleId,
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
return mAudioFlinger.removeEffectFromHal(deviceId, hwModuleId, effect);
};
@@ -73,7 +73,7 @@
RELEASE_AUDIO_PATCH,
};
- CommandThread(DeviceEffectManager& manager)
+ explicit CommandThread(DeviceEffectManager& manager)
: Thread(false), mManager(manager) {}
~CommandThread() override;
@@ -94,7 +94,7 @@
class Command: public RefBase {
public:
Command() = default;
- Command(int command, sp<CommandData> data)
+ Command(int command, const sp<CommandData>& data)
: mCommand(command), mData(data) {}
int mCommand = -1;
@@ -117,13 +117,13 @@
class ReleaseAudioPatchData : public CommandData {
public:
- ReleaseAudioPatchData(audio_patch_handle_t handle)
+ explicit ReleaseAudioPatchData(audio_patch_handle_t handle)
: mHandle(handle) {}
audio_patch_handle_t mHandle;
};
- void sendCommand(sp<Command> command);
+ void sendCommand(const sp<Command>& command);
Mutex mLock;
Condition mWaitWorkCV;
@@ -145,7 +145,7 @@
class DeviceEffectManagerCallback : public EffectCallbackInterface {
public:
- DeviceEffectManagerCallback(DeviceEffectManager *manager)
+ explicit DeviceEffectManagerCallback(DeviceEffectManager *manager)
: mManager(*manager) {}
status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -176,10 +176,10 @@
size_t frameCount() const override { return 0; }
uint32_t latency() const override { return 0; }
- status_t addEffectToHal(sp<EffectHalInterface> effect __unused) override {
+ status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
return NO_ERROR;
}
- status_t removeEffectFromHal(sp<EffectHalInterface> effect __unused) override {
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
return NO_ERROR;
}
@@ -204,11 +204,11 @@
int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
status_t addEffectToHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
return mManager.addEffectToHal(deviceId, hwModuleId, effect);
}
status_t removeEffectFromHal(audio_port_handle_t deviceId,
- audio_module_handle_t hwModuleId, sp<EffectHalInterface> effect) {
+ audio_module_handle_t hwModuleId, const sp<EffectHalInterface>& effect) {
return mManager.removeEffectFromHal(deviceId, hwModuleId, effect);
}
private:
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 98829d0..e912bff 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -498,6 +498,7 @@
}
void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
@@ -1249,13 +1250,13 @@
return -EINVAL;
}
if (cmdCode == EFFECT_CMD_GET_PARAM &&
- (maxReplySize < sizeof(effect_param_t) ||
+ (maxReplySize < static_cast<signed>(sizeof(effect_param_t)) ||
param->psize > maxReplySize - sizeof(effect_param_t))) {
android_errorWriteLog(0x534e4554, "29251553");
return -EINVAL;
}
if (cmdCode == EFFECT_CMD_GET_PARAM &&
- (sizeof(effect_param_t) > maxReplySize
+ (static_cast<signed>(sizeof(effect_param_t)) > maxReplySize
|| param->psize > maxReplySize - sizeof(effect_param_t)
|| param->vsize > maxReplySize - sizeof(effect_param_t)
- param->psize
@@ -1685,6 +1686,7 @@
}
void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
EffectBase::dump(fd, args);
@@ -1939,7 +1941,7 @@
}
mCblkMemory.clear(); // free the shared memory before releasing the heap it belongs to
// Client destructor must run with AudioFlinger client mutex locked
- Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
+ Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
mClient.clear();
}
}
@@ -2003,14 +2005,14 @@
}
if (cmdCode == EFFECT_CMD_ENABLE) {
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < static_cast<signed>(sizeof(int))) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
writeToBuffer(NO_ERROR, response);
return enable(_aidl_return);
} else if (cmdCode == EFFECT_CMD_DISABLE) {
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < static_cast<signed>(sizeof(int))) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
@@ -2034,7 +2036,7 @@
RETURN(INVALID_OPERATION);
}
- if (maxResponseSize < sizeof(int)) {
+ if (maxResponseSize < (signed)sizeof(int)) {
android_errorWriteLog(0x534e4554, "32095713");
RETURN(BAD_VALUE);
}
@@ -2043,7 +2045,7 @@
// No need to trylock() here as this function is executed in the binder thread serving a
// particular client process: no risk to block the whole media server process or mixer
// threads if we are stuck here
- Mutex::Autolock _l(mCblk->lock);
+ Mutex::Autolock _l2(mCblk->lock);
// keep local copy of index in case of client corruption b/32220769
const uint32_t clientIndex = mCblk->clientIndex;
const uint32_t serverIndex = mCblk->serverIndex;
@@ -2146,6 +2148,7 @@
}
void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
@@ -2400,7 +2403,7 @@
}
} else {
effect->setInBuffer(mInBuffer);
- if (idx_insert == previousSize) {
+ if (idx_insert == static_cast<ssize_t>(previousSize)) {
if (idx_insert != 0) {
mEffects[idx_insert-1]->configure();
mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
@@ -2460,7 +2463,7 @@
}
// remember position of first insert effect and by default
// select this as insert position for new effect
- if (idx_insert == size) {
+ if (idx_insert == static_cast<ssize_t>(size)) {
idx_insert = i;
}
// remember position of last insert effect claiming
@@ -2690,6 +2693,7 @@
}
void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
String8 result;
@@ -3027,7 +3031,7 @@
}
status_t AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
@@ -3043,7 +3047,7 @@
}
status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
status_t result = NO_INIT;
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
@@ -3185,15 +3189,20 @@
return t->frameCount();
}
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const {
+uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+NO_THREAD_SAFETY_ANALYSIS // latency_l() access
+{
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
return 0;
}
+ // TODO(b/275956781) - this requires the thread lock.
return t->latency_l();
}
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const {
+void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+NO_THREAD_SAFETY_ANALYSIS // setVolumeForOutput_l() access
+{
sp<ThreadBase> t = thread().promote();
if (t == nullptr) {
return;
@@ -3437,7 +3446,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
}
@@ -3446,7 +3455,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
if (mHalEffect == nullptr) {
return NO_INIT;
}
@@ -3484,7 +3493,9 @@
return audio_channel_count_from_in_mask(channelMask());
}
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces) {
+void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
+{
const Vector<String16> args;
EffectBase::dump(fd, args);
@@ -3563,7 +3574,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return NO_INIT;
@@ -3572,7 +3583,7 @@
}
status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
- sp<EffectHalInterface> effect) {
+ const sp<EffectHalInterface>& effect) {
sp<DeviceEffectProxy> proxy = mProxy.promote();
if (proxy == nullptr) {
return NO_INIT;
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 78788df..bad86bc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -45,8 +45,8 @@
// Non trivial methods usually implemented with help from ThreadBase:
// pay attention to mutex locking order
virtual uint32_t latency() const { return 0; }
- virtual status_t addEffectToHal(sp<EffectHalInterface> effect) = 0;
- virtual status_t removeEffectFromHal(sp<EffectHalInterface> effect) = 0;
+ virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+ virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
virtual void setVolumeForOutput(float left, float right) const = 0;
virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
@@ -159,8 +159,8 @@
bool isPinned() const { return mPinned; }
void unPin() { mPinned = false; }
- void lock() { mLock.lock(); }
- void unlock() { mLock.unlock(); }
+ void lock() ACQUIRE(mLock) { mLock.lock(); }
+ void unlock() RELEASE(mLock) { mLock.unlock(); }
status_t updatePolicyState();
@@ -459,10 +459,10 @@
void process_l();
- void lock() {
+ void lock() ACQUIRE(mLock) {
mLock.lock();
}
- void unlock() {
+ void unlock() RELEASE(mLock) {
mLock.unlock();
}
@@ -605,8 +605,8 @@
size_t frameCount() const override;
uint32_t latency() const override;
- status_t addEffectToHal(sp<EffectHalInterface> effect) override;
- status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left, float right) const override;
@@ -721,8 +721,8 @@
size_t removeEffect(const sp<EffectModule>& effect);
- status_t addEffectToHal(sp<EffectHalInterface> effect);
- status_t removeEffectFromHal(sp<EffectHalInterface> effect);
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect);
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
const AudioDeviceTypeAddr& device() { return mDevice; };
bool isOutput() const;
@@ -766,8 +766,8 @@
size_t frameCount() const override { return 0; }
uint32_t latency() const override { return 0; }
- status_t addEffectToHal(sp<EffectHalInterface> effect) override;
- status_t removeEffectFromHal(sp<EffectHalInterface> effect) override;
+ status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
+ status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
void setVolumeForOutput(float left __unused, float right __unused) const override {}
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/FastCaptureDumpState.cpp
index b8b3866..243dfa5 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/FastCaptureDumpState.cpp
@@ -51,4 +51,4 @@
periodSec * 1e3, mSilenced ? "true" : "false");
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/FastCaptureDumpState.h
index a1b8706..34ce456 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/FastCaptureDumpState.h
@@ -38,6 +38,6 @@
bool mSilenced = false; // capture is silenced
};
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/FastCaptureState.cpp
index c4d5e45..918ba9c 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/FastCaptureState.cpp
@@ -42,4 +42,4 @@
LOG_ALWAYS_FATAL("%s", __func__);
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/FastMixerDumpState.cpp
index 3f20282..d041882 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/FastMixerDumpState.cpp
@@ -203,4 +203,4 @@
}
}
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/FastMixerDumpState.h
index 9b91cbc..294ef78 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/FastMixerDumpState.h
@@ -81,6 +81,6 @@
TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
};
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
index 3f6b206..2f0f73f 100644
--- a/services/audioflinger/FastThread.h
+++ b/services/audioflinger/FastThread.h
@@ -92,6 +92,6 @@
}; // class FastThread
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/FastThreadDumpState.cpp
index 964a725..e91073f 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/FastThreadDumpState.cpp
@@ -56,4 +56,4 @@
}
#endif
-} // android
+} // namespace android
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/FastThreadDumpState.h
index 1ce0914..0b20e55 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/FastThreadDumpState.h
@@ -67,6 +67,6 @@
}; // struct FastThreadDumpState
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/FastThreadState.h
index 54c0dc6..9fb4e06 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/FastThreadState.h
@@ -50,6 +50,6 @@
static const char *commandToString(Command command);
}; // struct FastThreadState
-} // android
+} // namespace android
#endif // ANDROID_AUDIO_FAST_THREAD_STATE_H
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 68a3800..5555766 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -199,7 +199,7 @@
return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
- void setThread(sp<ThreadBase> thread) { mThread = thread; }
+ void setThread(const sp<ThreadBase>& thread) { mThread = thread; }
wp<ThreadBase> thread() const { return mThread; }
// returns the latency of the patch (from record to playback).
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index 9d4188f..38ce2c2 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -187,7 +187,9 @@
} // namespace android
-// hack for gcc
+// Hack to avoid explicit template instantiation of
+// template class StateQueue<FastCaptureState>;
+// template class StateQueue<FastMixerState>;
#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS
+#include STATE_QUEUE_INSTANTIATIONS // NOLINT(bugprone-suspicious-include)
#endif
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 37b8fe8..9e68cd3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -374,7 +374,7 @@
// try three times to get the clock offset, choose the one
// with the minimum gap in measurements.
const int tries = 3;
- nsecs_t bestGap, measured;
+ nsecs_t bestGap = 0, measured = 0; // not required, initialized for clang-tidy
for (int i = 0; i < tries; ++i) {
const nsecs_t tmono = systemTime(SYSTEM_TIME_MONOTONIC);
const nsecs_t tbase = systemTime(clockbase);
@@ -623,6 +623,7 @@
// sendConfigEvent_l() must be called with ThreadBase::mLock held
// Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+NO_THREAD_SAFETY_ANALYSIS // condition variable
{
status_t status = NO_ERROR;
@@ -936,6 +937,7 @@
}
void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
+NO_THREAD_SAFETY_ANALYSIS // conditional try lock
{
dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
this, mThreadName, getTid(), type(), threadTypeToString(type()));
@@ -1304,7 +1306,9 @@
void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
audio_session_t sessionId,
- bool threadLocked) {
+ bool threadLocked)
+NO_THREAD_SAFETY_ANALYSIS // manual locking
+{
if (!threadLocked) {
mLock.lock();
}
@@ -1768,6 +1772,7 @@
void AudioFlinger::ThreadBase::lockEffectChains_l(
Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::lock()
{
effectChains = mEffectChains;
for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -1777,6 +1782,7 @@
void AudioFlinger::ThreadBase::unlockEffectChains(
const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+NO_THREAD_SAFETY_ANALYSIS // calls EffectChain::unlock()
{
for (size_t i = 0; i < effectChains.size(); i++) {
effectChains[i]->unlock();
@@ -1884,7 +1890,7 @@
template <typename T>
void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
- sp<ThreadBase> thread, bool force) {
+ const sp<ThreadBase>& thread, bool force) {
// Updates ActiveTracks client uids to the thread wakelock.
if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
thread->updateWakeLockUids_l(getWakeLockUids());
@@ -2716,6 +2722,7 @@
// addTrack_l() must be called with ThreadBase::mLock held
status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
status_t status = ALREADY_EXISTS;
@@ -2825,6 +2832,9 @@
if (!trackActive) {
removeTrack_l(track);
} else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
+ if (track->isPausePending()) {
+ track->pauseAck();
+ }
track->mState = TrackBase::STOPPING_1;
}
@@ -2865,7 +2875,7 @@
if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
return out_s8;
}
- return String8();
+ return {};
}
status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
@@ -3575,10 +3585,10 @@
size_t numSamples = mNormalFrameCount
* (audio_channel_count_from_out_mask(mMixerChannelMask)
+ mHapticChannelCount);
- status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+ const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(effect_buffer_t),
&halInBuffer);
- if (result != OK) return result;
+ if (allocateStatus != OK) return allocateStatus;
#ifdef FLOAT_EFFECT_CHAIN
buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
#else
@@ -3664,8 +3674,8 @@
}
// detach all tracks with same session ID from this chain
- for (size_t i = 0; i < mTracks.size(); ++i) {
- sp<Track> track = mTracks[i];
+ for (size_t j = 0; j < mTracks.size(); ++j) {
+ sp<Track> track = mTracks[j];
if (session == track->sessionId()) {
track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
chain->decTrackCnt();
@@ -3718,6 +3728,7 @@
}
bool AudioFlinger::PlaybackThread::threadLoop()
+NO_THREAD_SAFETY_ANALYSIS // manual locking of AudioFlinger
{
tlNBLogWriter = mNBLogWriter.get();
@@ -3786,7 +3797,7 @@
// is more informational.
if (mAudioFlinger->mLock.tryLock() == NO_ERROR) {
std::vector<PatchPanel::SoftwarePatch> swPatches;
- double latencyMs;
+ double latencyMs = 0.; // not required; initialized for clang-tidy
status_t status = INVALID_OPERATION;
audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
@@ -3806,8 +3817,7 @@
ALOGVV("new downstream latency %lf ms", latencyMs);
} else {
ALOGD("out of range downstream latency %lf ms", latencyMs);
- if (latencyMs < minLatency) latencyMs = minLatency;
- else if (latencyMs > maxLatency) latencyMs = maxLatency;
+ latencyMs = std::clamp(latencyMs, minLatency, maxLatency);
}
mDownstreamLatencyStatMs.add(latencyMs);
}
@@ -4489,6 +4499,7 @@
// removeTracks_l() must be called with ThreadBase::mLock held
void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
for (const auto& track : tracksToRemove) {
mActiveTracks.remove(track);
@@ -4609,8 +4620,8 @@
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
- deviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
- patch->sinks[i].ext.device.address));
+ deviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address);
}
audio_port_handle_t sinkPortId = patch->sinks[0].id;
@@ -4818,14 +4829,15 @@
// When it wakes up after a maximum latency, it runs a few cycles quickly before
// finally blocking. Note the pipe implementation rounds up the request to a power of 2.
MonoPipe *monoPipe = new MonoPipe(mNormalFrameCount * 4, format, true /*writeCanBlock*/);
- const NBAIO_Format offers[1] = {format};
- size_t numCounterOffers = 0;
+ const NBAIO_Format offersFast[1] = {format};
+ size_t numCounterOffersFast = 0;
#if !LOG_NDEBUG
ssize_t index =
#else
(void)
#endif
- monoPipe->negotiate(offers, 1, NULL, numCounterOffers);
+ monoPipe->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
monoPipe->setAvgFrames((mScreenState & 1) ?
(monoPipe->maxFrames() * 7) / 8 : mNormalFrameCount * 2);
@@ -5237,7 +5249,7 @@
// tallyUnderrunFrames() is called to update the track counters
// with the number of underrun frames for a particular mixer period.
// We defer tallying until we know the final mixer status.
- void tallyUnderrunFrames(sp<Track> track, size_t underrunFrames) {
+ void tallyUnderrunFrames(const sp<Track>& track, size_t underrunFrames) {
mUnderrunFrames.emplace_back(track, underrunFrames);
}
@@ -5486,7 +5498,7 @@
// during last round
size_t desiredFrames;
const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
- AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+ const AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
desiredFrames = sourceFramesNeededWithTimestretch(
sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
@@ -5670,12 +5682,12 @@
AudioMixer::SAMPLE_RATE,
(void *)(uintptr_t)reqSampleRate);
- AudioPlaybackRate playbackRate = proxy->getPlaybackRate();
mAudioMixer->setParameter(
trackId,
AudioMixer::TIMESTRETCH,
AudioMixer::PLAYBACK_RATE,
- &playbackRate);
+ // cast away constness for this generic API.
+ const_cast<void *>(reinterpret_cast<const void *>(&playbackRate)));
/*
* Select the appropriate output buffer for the track.
@@ -6059,12 +6071,12 @@
mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
for (const auto &track : mTracks) {
const int trackId = track->id();
- status_t status = mAudioMixer->create(
+ const status_t createStatus = mAudioMixer->create(
trackId,
track->mChannelMask,
track->mFormat,
track->mSessionId);
- ALOGW_IF(status != NO_ERROR,
+ ALOGW_IF(createStatus != NO_ERROR,
"%s(): AudioMixer cannot create track(%d)"
" mask %#x, format %#x, sessionId %d",
__func__,
@@ -6193,12 +6205,17 @@
if (left > GAIN_FLOAT_UNITY) {
left = GAIN_FLOAT_UNITY;
}
- left *= v * mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
right = float_from_gain(gain_minifloat_unpack_right(vlr));
if (right > GAIN_FLOAT_UNITY) {
right = GAIN_FLOAT_UNITY;
}
- right *= v * mMasterBalanceRight;
+ left *= v;
+ right *= v;
+ if (mAudioFlinger->getMode() != AUDIO_MODE_IN_COMMUNICATION
+ || audio_channel_count_from_out_mask(mChannelMask) > 1) {
+ left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
+ right *= mMasterBalanceRight;
+ }
}
if (lastTrack) {
@@ -6236,7 +6253,8 @@
mFlushPending = true;
}
} else /* mType == OFFLOAD */ {
- if (previousTrack->sessionId() != latestTrack->sessionId()) {
+ if (previousTrack->sessionId() != latestTrack->sessionId() ||
+ previousTrack->isFlushPending()) {
mFlushPending = true;
}
}
@@ -7111,7 +7129,7 @@
void AudioFlinger::DuplicatingThread::threadLoop_mix()
{
// mix buffers...
- if (outputsReady(outputTracks)) {
+ if (outputsReady()) {
mAudioMixer->process();
} else {
if (mMixerBufferValid) {
@@ -7182,7 +7200,7 @@
}
}
-void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
{
MixerThread::dumpInternals_l(fd, args);
@@ -7286,9 +7304,7 @@
}
}
-
-bool AudioFlinger::DuplicatingThread::outputsReady(
- const SortedVector< sp<OutputTrack> > &outputTracks)
+bool AudioFlinger::DuplicatingThread::outputsReady()
{
for (size_t i = 0; i < outputTracks.size(); i++) {
sp<ThreadBase> thread = outputTracks[i]->thread().promote();
@@ -7617,14 +7633,16 @@
// pipe will be shared directly with fast clients, so clear to avoid leaking old information
memset(pipeBuffer, 0, pipeSize);
Pipe *pipe = new Pipe(pipeFramesP2, format, pipeBuffer);
- const NBAIO_Format offers[1] = {format};
- size_t numCounterOffers = 0;
- [[maybe_unused]] ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+ const NBAIO_Format offersFast[1] = {format};
+ size_t numCounterOffersFast = 0;
+ [[maybe_unused]] ssize_t index = pipe->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
mPipeSink = pipe;
PipeReader *pipeReader = new PipeReader(*pipe);
- numCounterOffers = 0;
- index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+ numCounterOffersFast = 0;
+ index = pipeReader->negotiate(offersFast, std::size(offersFast),
+ nullptr /* counterOffers */, numCounterOffersFast);
ALOG_ASSERT(index == 0);
mPipeSource = pipeReader;
mPipeFramesP2 = pipeFramesP2;
@@ -7972,7 +7990,7 @@
// copy to the right place. Permitted because mRsmpInBuffer was over-allocated.
int32_t rear = mRsmpInRear & (mRsmpInFramesP2 - 1);
- ssize_t framesRead;
+ ssize_t framesRead = 0; // not needed, remove clang-tidy warning.
const int64_t lastIoBeginNs = systemTime(); // start IO timing
// If an NBAIO source is present, use it to read the normal capture's data
@@ -8165,8 +8183,9 @@
// straight from RecordThread buffer to RecordTrack buffer.
AudioBufferProvider::Buffer buffer;
buffer.frameCount = framesOut;
- status_t status = activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
- if (status == OK && buffer.frameCount != 0) {
+ const status_t getNextBufferStatus =
+ activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+ if (getNextBufferStatus == OK && buffer.frameCount != 0) {
ALOGV_IF(buffer.frameCount != framesOut,
"%s() read less than expected (%zu vs %zu)",
__func__, buffer.frameCount, framesOut);
@@ -8176,7 +8195,7 @@
} else {
framesOut = 0;
ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
- __func__, status, buffer.frameCount);
+ __func__, getNextBufferStatus, buffer.frameCount);
}
} else {
// process frames from the RecordThread buffer provider to the RecordTrack
@@ -8596,7 +8615,6 @@
// or using a separate command thread
recordTrack->mState = TrackBase::STARTING_1;
mActiveTracks.add(recordTrack);
- status_t status = NO_ERROR;
if (recordTrack->isExternalTrack()) {
mLock.unlock();
status = AudioSystem::startInput(recordTrack->portId());
@@ -8787,7 +8805,7 @@
// "best effort" behavior of the API.
if (sharedOffset < 0) {
sharedAudioStartFrames = mRsmpInRear;
- } else if (sharedOffset > mRsmpInFrames) {
+ } else if (sharedOffset > static_cast<signed>(mRsmpInFrames)) {
sharedAudioStartFrames =
audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
}
@@ -9162,7 +9180,7 @@
return out_s8;
}
}
- return String8();
+ return {};
}
void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -9397,7 +9415,7 @@
maxFilled = filled;
}
}
- if (maxFilled > mRsmpInFrames) {
+ if (maxFilled > static_cast<signed>(mRsmpInFrames)) {
(void)__builtin_sub_overflow(mRsmpInRear, mRsmpInFrames, &oldestFront);
}
return oldestFront;
@@ -9589,7 +9607,7 @@
AudioFlinger::MmapThread::MmapThread(
const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady, bool isOut)
+ AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady, bool isOut)
: ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
mSessionId(AUDIO_SESSION_NONE),
mPortId(AUDIO_PORT_HANDLE_NONE),
@@ -9794,8 +9812,10 @@
mHalVolFloat = -1.0f;
} else if (!track->isSilenced_l()) {
for (const sp<MmapTrack> &t : mActiveTracks) {
- if (t->isSilenced_l() && t->uid() != client.attributionSource.uid)
+ if (t->isSilenced_l()
+ && t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
t->invalidate();
+ }
}
}
@@ -10021,7 +10041,7 @@
if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
return out_s8;
}
- return String8();
+ return {};
}
void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
@@ -10051,6 +10071,7 @@
status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *patch,
audio_patch_handle_t *handle)
+NO_THREAD_SAFETY_ANALYSIS // elease and re-acquire mLock
{
status_t status = NO_ERROR;
@@ -10068,8 +10089,8 @@
"as it does not support audio patches",
patch->sinks[i].ext.device.type);
type = static_cast<audio_devices_t>(type | patch->sinks[i].ext.device.type);
- sinkDeviceTypeAddrs.push_back(AudioDeviceTypeAddr(patch->sinks[i].ext.device.type,
- patch->sinks[i].ext.device.address));
+ sinkDeviceTypeAddrs.emplace_back(patch->sinks[i].ext.device.type,
+ patch->sinks[i].ext.device.address);
}
deviceId = patch->sinks[0].id;
numDevices = mPatch.num_sinks;
@@ -10272,6 +10293,7 @@
}
void AudioFlinger::MmapThread::checkInvalidTracks_l()
+NO_THREAD_SAFETY_ANALYSIS // release and re-acquire mLock
{
sp<MmapStreamCallback> callback;
for (const sp<MmapTrack> &track : mActiveTracks) {
@@ -10426,6 +10448,7 @@
}
void AudioFlinger::MmapPlaybackThread::processVolume_l()
+NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
{
float volume;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ce90767..63ad4e6 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -163,7 +163,7 @@
class SetParameterConfigEventData : public ConfigEventData {
public:
- explicit SetParameterConfigEventData(String8 keyValuePairs) :
+ explicit SetParameterConfigEventData(const String8& keyValuePairs) :
mKeyValuePairs(keyValuePairs) {}
virtual void dump(char *buffer, size_t size) {
@@ -175,7 +175,7 @@
class SetParameterConfigEvent : public ConfigEvent {
public:
- explicit SetParameterConfigEvent(String8 keyValuePairs) :
+ explicit SetParameterConfigEvent(const String8& keyValuePairs) :
ConfigEvent(CFG_EVENT_SET_PARAMETER) {
mData = new SetParameterConfigEventData(keyValuePairs);
mWaitStatus = true;
@@ -789,7 +789,7 @@
// ThreadBase thread.
void clear();
// periodically called in the threadLoop() to update power state uids.
- void updatePowerState(sp<ThreadBase> thread, bool force = false);
+ void updatePowerState(const sp<ThreadBase>& thread, bool force = false);
/** @return true if one or move active tracks was added or removed since the
* last time this function was called or the vector was created.
@@ -1260,7 +1260,7 @@
template <typename T>
class Tracks {
public:
- Tracks(bool saveDeletedTrackIds) :
+ explicit Tracks(bool saveDeletedTrackIds) :
mSaveDeletedTrackIds(saveDeletedTrackIds) { }
// SortedVector methods
@@ -1289,7 +1289,7 @@
return mTracks.end();
}
- size_t processDeletedTrackIds(std::function<void(int)> f) {
+ size_t processDeletedTrackIds(const std::function<void(int)>& f) {
for (const int trackId : mDeletedTrackIds) {
f(trackId);
}
@@ -1411,7 +1411,7 @@
class IsTimestampAdvancing {
public:
// The timestamp will not be checked any faster than the specified time.
- IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
+ explicit IsTimestampAdvancing(nsecs_t minimumTimeBetweenChecksNs)
: mMinimumTimeBetweenChecksNs(minimumTimeBetweenChecksNs)
{
clear();
@@ -1700,7 +1700,7 @@
void dumpInternals_l(int fd, const Vector<String16>& args) override;
private:
- bool outputsReady(const SortedVector< sp<OutputTrack> > &outputTracks);
+ bool outputsReady();
protected:
// threadLoop snippets
virtual void threadLoop_mix();
@@ -2066,7 +2066,7 @@
#include "MmapTracks.h"
MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
- AudioHwDevice *hwDev, sp<StreamHalInterface> stream, bool systemReady,
+ AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
bool isOut);
virtual ~MmapThread();
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 20bfbb0..42f7b47 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -122,7 +122,7 @@
* This may be called without the thread lock.
*/
virtual double bufferLatencyMs() const {
- return mServerProxy->framesReadySafe() * 1000 / sampleRate();
+ return mServerProxy->framesReadySafe() * 1000. / sampleRate();
}
/** returns whether the track supports server latency computation.
@@ -430,7 +430,7 @@
{
public:
using Timeout = std::optional<std::chrono::nanoseconds>;
- PatchTrackBase(sp<ClientProxy> proxy, const ThreadBase& thread,
+ PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
const Timeout& timeout);
void setPeerTimeout(std::chrono::nanoseconds timeout);
template <typename T>
diff --git a/services/audioflinger/TrackMetrics.h b/services/audioflinger/TrackMetrics.h
index 6fc70d6..ed3928a 100644
--- a/services/audioflinger/TrackMetrics.h
+++ b/services/audioflinger/TrackMetrics.h
@@ -113,7 +113,8 @@
mDeviceStartupMs.add(startupMs);
}
- void updateMinMaxVolume(int64_t durationNs, double deviceVolume) {
+ void updateMinMaxVolume_l(int64_t durationNs, double deviceVolume)
+ REQUIRES(mLock) {
if (deviceVolume > mMaxVolume) {
mMaxVolume = deviceVolume;
mMaxVolumeDurationNs = durationNs;
@@ -165,7 +166,7 @@
mDeviceTimeNs += durationNs;
mCumulativeTimeNs += durationNs;
}
- updateMinMaxVolume(durationNs, mVolume); // always update.
+ updateMinMaxVolume_l(durationNs, mVolume); // always update.
mVolume = volume;
mLastVolumeChangeTimeNs = timeNs;
}
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 300ad9f..123d5a9 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -303,7 +303,7 @@
return NO_ERROR;
}
-AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(sp<ClientProxy> proxy,
+AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
const ThreadBase& thread,
const Timeout& timeout)
: mProxy(proxy)
@@ -1298,8 +1298,9 @@
// must be called with thread lock held
void AudioFlinger::PlaybackThread::Track::flushAck()
{
- if (!isOffloaded() && !isDirect())
+ if (!isOffloaded() && !isDirect()) {
return;
+ }
// Clear the client ring buffer so that the app can prime the buffer while paused.
// Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
@@ -1812,23 +1813,23 @@
//To be called with thread lock held
bool AudioFlinger::PlaybackThread::Track::isResumePending() {
-
- if (mState == RESUMING)
+ if (mState == RESUMING) {
return true;
+ }
/* Resume is pending if track was stopping before pause was called */
if (mState == STOPPING_1 &&
- mResumeToStopping)
+ mResumeToStopping) {
return true;
+ }
return false;
}
//To be called with thread lock held
void AudioFlinger::PlaybackThread::Track::resumeAck() {
-
-
- if (mState == RESUMING)
+ if (mState == RESUMING) {
mState = ACTIVE;
+ }
// Other possibility of pending resume is stopping_1 state
// Do not update the state from stopping as this prevents
@@ -2094,7 +2095,10 @@
if (thread != 0 && !thread->standby()) {
if (mBufferQueue.size() < kMaxOverFlowBuffers) {
pInBuffer = new Buffer;
- pInBuffer->mBuffer = malloc(inBuffer.frameCount * mFrameSize);
+ const size_t bufferSize = inBuffer.frameCount * mFrameSize;
+ pInBuffer->mBuffer = malloc(bufferSize);
+ LOG_ALWAYS_FATAL_IF(pInBuffer->mBuffer == nullptr,
+ "%s: Unable to malloc size %zu", __func__, bufferSize);
pInBuffer->frameCount = inBuffer.frameCount;
pInBuffer->raw = pInBuffer->mBuffer;
memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * mFrameSize);
@@ -2258,7 +2262,7 @@
buf.mFrameCount = buffer->frameCount;
buf.mRaw = buffer->raw;
mPeerProxy->releaseBuffer(&buf);
- TrackBase::releaseBuffer(buffer);
+ TrackBase::releaseBuffer(buffer); // Note: this is the base class.
}
status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
@@ -2872,7 +2876,7 @@
{
void *ptr = nullptr;
(void)posix_memalign(&ptr, alignment, size);
- return std::unique_ptr<void, decltype(free)*>(ptr, free);
+ return {ptr, free};
}
AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 496591a..7ad9f6c 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -245,6 +245,8 @@
unsigned int *num_ports,
struct audio_port_v7 *ports,
unsigned int *generation) = 0;
+ virtual status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) = 0;
virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index 7d21ae0..de501ee 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -162,6 +162,10 @@
DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const override;
+ void initializeDeviceSelectionCache() override;
+
+ void updateDeviceSelectionCache() override;
+
private:
/**
* Get media devices as the given role
@@ -190,6 +194,28 @@
/** current forced use configuration. */
audio_policy_forced_cfg_t mForceUse[AUDIO_POLICY_FORCE_USE_CNT] = {};
+
+protected:
+ /**
+ * Set the device information for a given strategy.
+ *
+ * @param strategy the strategy to set devices information
+ * @param devices the devices selected for the strategy
+ */
+ virtual void setStrategyDevices(const sp<ProductStrategy>& /*strategy*/,
+ const DeviceVector& /*devices*/) {
+ // In EngineBase, do nothing. It is up to the actual engine to decide if it is needed to
+ // set devices information for the given strategy.
+ }
+
+ /**
+ * Get devices that will be used for the given product strategy.
+ *
+ * @param strategy the strategy to query
+ */
+ virtual DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const = 0;
+
+ DeviceStrategyMap mDevicesForStrategies;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 99507ee..83a8e4d 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -627,6 +627,26 @@
return activeDevices;
}
+void EngineBase::initializeDeviceSelectionCache() {
+ // Initializing the device selection cache with default device won't be harmful, it will be
+ // updated after the audio modules are initialized.
+ auto defaultDevices = DeviceVector(getApmObserver()->getDefaultOutputDevice());
+ for (const auto &iter : getProductStrategies()) {
+ const auto &strategy = iter.second;
+ mDevicesForStrategies[strategy->getId()] = defaultDevices;
+ setStrategyDevices(strategy, defaultDevices);
+ }
+}
+
+void EngineBase::updateDeviceSelectionCache() {
+ for (const auto &iter : getProductStrategies()) {
+ const auto& strategy = iter.second;
+ auto devices = getDevicesForProductStrategy(strategy->getId());
+ mDevicesForStrategies[strategy->getId()] = devices;
+ setStrategyDevices(strategy, devices);
+ }
+}
+
void EngineBase::dumpCapturePresetDevicesRoleMap(String8 *dst, int spaces) const
{
dst->appendFormat("\n%*sDevice role per capture preset dump:", spaces, "");
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index 518f86e..57174c7 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -421,6 +421,16 @@
*/
virtual DeviceVector getActiveMediaDevices(const DeviceVector& availableDevices) const = 0;
+ /**
+ * @brief initializeDeviceSelectionCache. Device selection for AudioAttribute / Streams is
+ * cached in the engine in order to speed up process when the audio system is stable. When the
+ * audio system is initializing, not all audio devices information will be available. In that
+ * case, calling this function can allow the engine to initialize the device selection cache
+ * with default values.
+ * This must only be called when audio policy manager is initializing.
+ */
+ virtual void initializeDeviceSelectionCache() = 0;
+
virtual void dump(String8 *dst) const = 0;
protected:
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2831a9b..a802646 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -354,14 +354,6 @@
return availableInputDevices.getDevice(deviceType, String8(address.c_str()), AUDIO_FORMAT_DEFAULT);
}
-void Engine::updateDeviceSelectionCache()
-{
- for (const auto &iter : getProductStrategies()) {
- const auto &strategy = iter.second;
- mDevicesForStrategies[strategy->getId()] = getDevicesForProductStrategy(strategy->getId());
- }
-}
-
void Engine::setDeviceAddressForProductStrategy(product_strategy_t strategy,
const std::string &address)
{
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4b559f0..001dde9 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -66,8 +66,6 @@
sp<AudioPolicyMix> *mix = nullptr)
const override;
- void updateDeviceSelectionCache() override;
-
///
/// from AudioPolicyPluginInterface
///
@@ -122,15 +120,17 @@
status_t loadAudioPolicyEngineConfig();
- DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
DeviceVector getCachedDevices(product_strategy_t ps) const;
+ ///
+ /// from EngineBase
+ ///
+ DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
+
/**
* Policy Parameter Manager hidden through a wrapper.
*/
ParameterManagerWrapper *mPolicyParameterMgr;
-
- DeviceStrategyMap mDevicesForStrategies;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 45c5eac..e72249f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -279,7 +279,8 @@
getLastRemovableMediaDevices(GROUP_NONE, {AUDIO_DEVICE_OUT_BLE_HEADSET}));
if (!devices.isEmpty()) break;
devices = availableOutputDevices.getFirstDevicesFromTypes({
- AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE});
+ AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_EARPIECE,
+ AUDIO_DEVICE_OUT_SPEAKER});
} break;
case STRATEGY_SONIFICATION:
@@ -641,15 +642,9 @@
return device;
}
-void Engine::updateDeviceSelectionCache()
-{
- for (const auto &iter : getProductStrategies()) {
- const auto& strategy = iter.second;
- auto devices = getDevicesForProductStrategy(strategy->getId());
- mDevicesForStrategies[strategy->getId()] = devices;
- strategy->setDeviceTypes(devices.types());
- strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
- }
+void Engine::setStrategyDevices(const sp<ProductStrategy>& strategy, const DeviceVector &devices) {
+ strategy->setDeviceTypes(devices.types());
+ strategy->setDeviceAddress(devices.getFirstValidAddress().c_str());
}
product_strategy_t Engine::getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const {
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 595e289..be9f4cc 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -67,7 +67,10 @@
sp<AudioPolicyMix> *mix = nullptr)
const override;
- void updateDeviceSelectionCache() override;
+ void setStrategyDevices(const sp<ProductStrategy>& strategy,
+ const DeviceVector& devices) override;
+
+ DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
private:
/* Copy facilities are put private to disable copy. */
@@ -87,8 +90,6 @@
DeviceVector availableOutputDevices,
const SwAudioOutputCollection &outputs) const;
- DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const;
-
sp<DeviceDescriptor> getDeviceForInputSource(audio_source_t inputSource) const;
product_strategy_t getProductStrategyFromLegacy(legacy_strategy legacyStrategy) const;
@@ -97,8 +98,6 @@
DeviceVector getPreferredAvailableDevicesForProductStrategy(
const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
- DeviceStrategyMap mDevicesForStrategies;
-
std::map<product_strategy_t, legacy_strategy> mLegacyStrategyMap;
};
} // namespace audio_policy
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 9f6b703..621f643 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -63,6 +63,15 @@
],
data: [":audiopolicyfuzzer_configuration_files"],
fuzz_config: {
- cc: ["mnaganov@google.com"],
+ cc: ["mnaganov@google.com"],
+ componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libaudiopolicy",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index c64497f..0239627 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4242,6 +4242,28 @@
return NO_ERROR;
}
+status_t AudioPolicyManager::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) {
+ auto pushPort = [&](const sp<DeviceDescriptor>& dev) -> status_t {
+ audio_port_v7 port;
+ dev->toAudioPort(&port);
+ auto aidlPort = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
+ _aidl_return->push_back(std::move(aidlPort));
+ return OK;
+ };
+
+ for (const auto& module : mHwModulesAll) {
+ for (const auto& dev : module->getDeclaredDevices()) {
+ if (role == media::AudioPortRole::NONE ||
+ ((role == media::AudioPortRole::SOURCE)
+ == audio_is_input_device(dev->type()))) {
+ RETURN_STATUS_IF_ERROR(pushPort(dev));
+ }
+ }
+ }
+ return OK;
+}
+
status_t AudioPolicyManager::getAudioPort(struct audio_port_v7 *port)
{
if (port == nullptr || port->id == AUDIO_PORT_HANDLE_NONE) {
@@ -5652,7 +5674,9 @@
}
}
- mEngine->updateDeviceSelectionCache();
+ // The actual device selection cache will be updated when calling `updateDevicesAndOutputs`
+ // at the end of this function.
+ mEngine->initializeDeviceSelectionCache();
mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
@@ -6058,6 +6082,14 @@
}
if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ // first call getAudioPort to get the supported attributes from the HAL
+ struct audio_port_v7 port = {};
+ device->toAudioPort(&port);
+ status_t status = mpClientInterface->getAudioPort(&port);
+ if (status == NO_ERROR) {
+ device->importAudioPort(port);
+ }
+
// look for input profiles that can be routed to this device
SortedVector< sp<IOProfile> > profiles;
for (const auto& hwModule : mHwModules) {
@@ -6109,11 +6141,7 @@
desc = new AudioInputDescriptor(profile, mpClientInterface);
audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
- status_t status = desc->open(nullptr,
- device,
- AUDIO_SOURCE_MIC,
- AUDIO_INPUT_FLAG_NONE,
- &input);
+ status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input);
if (status == NO_ERROR) {
const String8& address = String8(device->address().c_str());
@@ -7684,12 +7712,17 @@
ioHandle, String8(AudioParameter::keyStreamSupportedFormats));
ALOGV("%s: supported formats %d, %s", __FUNCTION__, ioHandle, reply.string());
AudioParameter repliedParameters(reply);
+ FormatVector formats;
if (repliedParameters.get(
- String8(AudioParameter::keyStreamSupportedFormats), reply) != NO_ERROR) {
- ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
+ String8(AudioParameter::keyStreamSupportedFormats), reply) == NO_ERROR) {
+ formats = formatsFromString(reply.string());
+ } else if (devDesc->hasValidAudioProfile()) {
+ ALOGD("%s: using the device profiles", __func__);
+ formats = devDesc->getAudioProfiles().getSupportedFormats();
+ } else {
+ ALOGE("%s: failed to retrieve format, bailing out", __func__);
return;
}
- FormatVector formats = formatsFromString(reply.string());
mReportedFormatsMap[devDesc] = formats;
if (device == AUDIO_DEVICE_OUT_HDMI
|| isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
@@ -7699,7 +7732,7 @@
}
for (audio_format_t format : profiles.getSupportedFormats()) {
- ChannelMaskSet channelMasks;
+ std::optional<ChannelMaskSet> channelMasks;
SampleRateSet samplingRates;
AudioParameter requestedParameters;
requestedParameters.addInt(String8(AudioParameter::keyFormat), format);
@@ -7714,6 +7747,8 @@
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedSamplingRates), reply) == NO_ERROR) {
samplingRates = samplingRatesFromString(reply.string());
+ } else {
+ samplingRates = devDesc->getAudioProfiles().getSampleRatesFor(format);
}
}
if (profiles.hasDynamicChannelsFor(format)) {
@@ -7725,14 +7760,17 @@
if (repliedParameters.get(
String8(AudioParameter::keyStreamSupportedChannels), reply) == NO_ERROR) {
channelMasks = channelMasksFromString(reply.string());
- if (device == AUDIO_DEVICE_OUT_HDMI
- || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD)) {
- modifySurroundChannelMasks(&channelMasks);
- }
+ } else {
+ channelMasks = devDesc->getAudioProfiles().getChannelMasksFor(format);
+ }
+ if (channelMasks.has_value() && (device == AUDIO_DEVICE_OUT_HDMI
+ || isDeviceOfModule(devDesc, AUDIO_HARDWARE_MODULE_ID_MSD))) {
+ modifySurroundChannelMasks(&channelMasks.value());
}
}
addDynamicAudioProfileAndSort(
- profiles, new AudioProfile(format, channelMasks, samplingRates));
+ profiles, new AudioProfile(
+ format, channelMasks.value_or(ChannelMaskSet()), samplingRates));
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 8466d097..e0411ab 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -261,6 +261,8 @@
unsigned int *num_ports,
struct audio_port_v7 *ports,
unsigned int *generation);
+ status_t listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* result) override;
virtual status_t getAudioPort(struct audio_port_v7 *port);
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index fdf5787..f34427c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1516,6 +1516,17 @@
return Status::ok();
}
+Status AudioPolicyService::listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) {
+ Mutex::Autolock _l(mLock);
+ if (mAudioPolicyManager == NULL) {
+ return binderStatusFromStatusT(NO_INIT);
+ }
+ AutoCallerClear acc;
+ return binderStatusFromStatusT(mAudioPolicyManager->listDeclaredDevicePorts(
+ role, _aidl_return));
+}
+
Status AudioPolicyService::getAudioPort(int portId,
media::AudioPortFw* _aidl_return) {
audio_port_v7 port{ .id = portId };
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 09b6f3b..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1816,14 +1816,12 @@
void AudioPolicyService::SensorPrivacyPolicy::registerSelf() {
SensorPrivacyManager spm;
mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
- (void)spm.addToggleSensorPrivacyListener(this);
spm.addSensorPrivacyListener(this);
}
void AudioPolicyService::SensorPrivacyPolicy::unregisterSelf() {
SensorPrivacyManager spm;
spm.removeSensorPrivacyListener(this);
- spm.removeToggleSensorPrivacyListener(this);
}
bool AudioPolicyService::SensorPrivacyPolicy::isSensorPrivacyEnabled() {
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 860bd18..7f682c8 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -174,6 +174,8 @@
binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
Int* count, std::vector<media::AudioPortFw>* ports,
int32_t* _aidl_return) override;
+ binder::Status listDeclaredDevicePorts(media::AudioPortRole role,
+ std::vector<media::AudioPortFw>* _aidl_return) override;
binder::Status getAudioPort(int portId,
media::AudioPortFw* _aidl_return) override;
binder::Status createAudioPatch(const media::AudioPatchFw& patch, int32_t handle,
diff --git a/services/audiopolicy/service/SpatializerPoseController.cpp b/services/audiopolicy/service/SpatializerPoseController.cpp
index 63f53b7..4cba8cc 100644
--- a/services/audiopolicy/service/SpatializerPoseController.cpp
+++ b/services/audiopolicy/service/SpatializerPoseController.cpp
@@ -108,8 +108,8 @@
.freshnessTimeout = Ticks(kFreshnessTimeout).count(),
.predictionDuration = []() -> float {
const int duration_ms =
- property_get_int32("audio.spatializer.prediction_duration_ms", 0);
- if (duration_ms > 0) {
+ property_get_int32("audio.spatializer.prediction_duration_ms", -1);
+ if (duration_ms >= 0) {
return duration_ms * 1'000'000LL;
} else {
return Ticks(kPredictionDuration).count();
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 1c40cfd..3821f97 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1681,19 +1681,19 @@
// Connecting a valid output device with valid parameters should trigger a routing update
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(1, mClient->getRoutingUpdatedCounter());
// Disconnecting a connected device should succeed and trigger a routing update
ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
// Disconnecting a disconnected device should fail and not trigger a routing update
ASSERT_EQ(INVALID_OPERATION, mManager->setDeviceConnectionState(
AUDIO_DEVICE_OUT_BLUETOOTH_SCO, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
- "a", "b", AUDIO_FORMAT_DEFAULT));
+ "00:11:22:33:44:55", "b", AUDIO_FORMAT_DEFAULT));
ASSERT_EQ(2, mClient->getRoutingUpdatedCounter());
// Changing force use should trigger an update
@@ -1820,9 +1820,9 @@
DeviceConnectionTestParams({AUDIO_DEVICE_OUT_HDMI, "test_out_hdmi",
"audio_policy_test_out_hdmi"}),
DeviceConnectionTestParams({AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, "bt_hfp_in",
- "hfp_client_in"}),
+ "00:11:22:33:44:55"}),
DeviceConnectionTestParams({AUDIO_DEVICE_OUT_BLUETOOTH_SCO, "bt_hfp_out",
- "hfp_client_out"})
+ "00:11:22:33:44:55"})
)
);
diff --git a/services/medialog/fuzzer/Android.bp b/services/medialog/fuzzer/Android.bp
index 9ff0ce4..c96c37b 100644
--- a/services/medialog/fuzzer/Android.bp
+++ b/services/medialog/fuzzer/Android.bp
@@ -38,5 +38,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmedialogservice library",
+ vector: "local_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "future_version",
},
}
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 8b33f10..20a6378 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -68,5 +68,13 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzer targets the APIs of libmediametricsservice",
+ vector: "local_no_privileges_required",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index 9f08eca..e5f7190 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -281,9 +281,9 @@
const int32_t uid = IPCThreadState::self()->getCallingUid();
int32_t frontend = 0;
if (!item->getInt32("frontend", &frontend)) return false;
- int32_t requested_security_level = -1;
+ int32_t requested_security_level = 0;
if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
- int32_t opened_security_level = -1;
+ int32_t opened_security_level = 0;
if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
// Optional to be included
@@ -325,12 +325,10 @@
if (!item->getInt32("frontend", &frontend)) return false;
std::string object_nonce = "";
if (!item->getString("object_nonce", &object_nonce)) return false;
- int32_t security_level = -1;
- if (!item->getInt32("security_level", &security_level)) return false;
std::string api_str = "";
if (!item->getString("api", &api_str)) return false;
const int32_t api = MediaDrmStatsdHelper::findDrmApi(api_str);
- int32_t error_code = -1;
+ int32_t error_code = 0;
if (!item->getInt32("error_code", &error_code)) return false;
// Optional to be included
@@ -338,12 +336,14 @@
item->getString("version", &version);
std::string session_nonce = "";
item->getString("session_nonce", &session_nonce);
+ int32_t security_level = 0;
+ item->getInt32("security_level", &security_level);
int32_t cdm_err = 0;
item->getInt32("cdm_err", &cdm_err);
int32_t oem_err = 0;
item->getInt32("oem_err", &oem_err);
- int32_t error_context = -1;
+ int32_t error_context = 0;
item->getInt32("error_context", &error_context);
const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,
diff --git a/services/mediaresourcemanager/OWNERS b/services/mediaresourcemanager/OWNERS
index 82abf8f..4fc3728 100644
--- a/services/mediaresourcemanager/OWNERS
+++ b/services/mediaresourcemanager/OWNERS
@@ -1 +1,3 @@
-dwkang@google.com
+girishshetty@google.com
+lajos@google.com
+wonsik@google.com
diff --git a/services/tuner/mediatuner.rc b/services/tuner/mediatuner.rc
index 6a3e199..d813b7d 100644
--- a/services/tuner/mediatuner.rc
+++ b/services/tuner/mediatuner.rc
@@ -1,6 +1,7 @@
service media.tuner /system/bin/mediatuner
class main
group media
+ user root
ioprio rt 4
onrestart restart vendor.tuner-hal-1-0
onrestart restart vendor.tuner-hal-1-1