Merge "Updated fuzz_config in Android.bp file"
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/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/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/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/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 5d2856a..9c054f0 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -356,7 +356,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..56e6e8a 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -362,7 +362,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/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/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..cb1a67d 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -2484,11 +2484,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 +2517,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/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/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..9901fc0 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",
@@ -297,3 +298,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..3894cbf 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,7 +935,7 @@
TIME_CHECK();
if (!mModule) return NO_INIT;
return mModule->dump(fd, Args(args).args(), args.size());
-};
+}
int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
TIME_CHECK();
@@ -772,6 +943,73 @@
return INVALID_OPERATION;
}
+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) {
if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
return p.ext.get<AudioPortExt::Tag::device>().device == device;
@@ -865,7 +1103,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 +1112,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 +1122,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 +1158,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 +1176,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 +1209,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 +1257,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 +1285,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..5ab7c84 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -29,6 +29,7 @@
#include <utils/Log.h>
#include "EffectConversionHelperAidl.h"
+#include "EffectProxy.h"
namespace android {
namespace effect {
@@ -37,7 +38,9 @@
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;
@@ -72,7 +75,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 +101,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,
@@ -154,22 +159,55 @@
}
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", __func__,
+ android::internal::ToString(state).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);
+ }
+ 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 +225,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 +330,20 @@
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 *static_cast<int32_t*>(pReplyData) = OK;
}
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 54df1b8..1200264 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,15 @@
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; }
protected:
const int32_t mSessionId;
@@ -42,7 +48,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 +64,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 +81,9 @@
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;
status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
void* pReplyData);
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c19ac8..d6135af 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);
}
}
@@ -160,34 +164,49 @@
// 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();
+ if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
+ !outputQ->isValid()) {
+ ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
+ inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
+ 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;
}
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 +229,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..8966363 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -31,11 +31,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 +78,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 +93,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..c4d85e5
--- /dev/null
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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..3048580 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -40,6 +40,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 {
@@ -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;
}
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 157e8bb..147c131 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 {
@@ -181,6 +207,8 @@
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..f1619a8 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 = 0,
+ .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_FREQUENCY_RESOLUTION,
+ .preferredProcessingDurationMs = std::numeric_limits<float>::max(),
+ .preEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .postEqStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .mbcStage = {.inUse = true, .bandCount = std::numeric_limits<int>::max()},
+ .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 =
+ .gainDb = std::numeric_limits<float>::lowest()});
+
+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});
-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 = 220,
+ .attackTimeMs = 0,
+ .releaseTimeMs = 0,
+ .ratio = 0,
+ .thresholdDb = std::numeric_limits<float>::lowest(),
+ .kneeWidthDb = 0,
+ .noiseGateThresholdDb = std::numeric_limits<float>::lowest(),
+ .expanderRatio = 0,
+ .preGainDb = std::numeric_limits<float>::lowest(),
+ .postGainDb = std::numeric_limits<float>::lowest()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::mbcBand>(
+ {DynamicsProcessing::MbcBandConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .band = std::numeric_limits<int>::max(),
+ .enable = true,
+ .cutoffFrequencyHz = 20000,
+ .attackTimeMs = std::numeric_limits<float>::max(),
+ .releaseTimeMs = std::numeric_limits<float>::max(),
+ .ratio = std::numeric_limits<float>::max(),
+ .thresholdDb = 0,
+ .kneeWidthDb = std::numeric_limits<float>::max(),
+ .noiseGateThresholdDb = 0,
+ .expanderRatio = std::numeric_limits<float>::max(),
+ .preGainDb = std::numeric_limits<float>::max(),
+ .postGainDb = std::numeric_limits<float>::max()})})};
+
+static const Range::DynamicsProcessingRange kInputGainRange = {
+ .min = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain(
+ {.channel = 0, .gainDb = std::numeric_limits<float>::lowest()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+ {DynamicsProcessing::InputGain({.channel = std::numeric_limits<int>::max(),
+ .gainDb = std::numeric_limits<float>::max()})})};
+
+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 = 0,
+ .thresholdDb = std::numeric_limits<float>::min(),
+ .postGainDb = std::numeric_limits<float>::min()})}),
+ .max = DynamicsProcessing::make<DynamicsProcessing::limiter>(
+ {DynamicsProcessing::LimiterConfig(
+ {.channel = std::numeric_limits<int>::max(),
+ .enable = true,
+ .linkGroup = std::numeric_limits<int>::max(),
+ .attackTimeMs = std::numeric_limits<float>::max(),
+ .releaseTimeMs = std::numeric_limits<float>::max(),
+ .ratio = std::numeric_limits<float>::max(),
+ .thresholdDb = 0,
+ .postGainDb = std::numeric_limits<float>::max()})})};
+
+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/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/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/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/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index ba7c6b6..9a3dd98 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()) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index ebfe32c..4b8bfbd 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);
@@ -932,6 +934,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/Threads.cpp b/services/audioflinger/Threads.cpp
index 37b8fe8..16c72cc 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2825,6 +2825,9 @@
if (!trackActive) {
removeTrack_l(track);
} else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
+ if (track->isPausePending()) {
+ track->pauseAck();
+ }
track->mState = TrackBase::STOPPING_1;
}
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/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..f7a3273 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) {
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.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